In this chapter, we are going to learn about cross-site request forgery (or also called CSRF).
|Type of vulnerability:||Client-Side|
|Chances to find:||Common; CSRF is part of “Broken Access Control” ranked #1 in the “OWASP Top-10 Vulnerabilities“|
|TL;DR:||A CSRF vulnerability enables an attacker to trick a victim into performing an unintended action. The targeted person has no idea about a specific click they have performed.|
What is cross-site request forgery?
Cross-Site Request Forgery (CSRF) is an attack that forces an end user to execute unwanted actions on a web application in which they’re currently authenticated. With a little help of social engineering (such as sending a link via email or chat), an attacker may trick the users of a web application into executing actions of the attacker’s choosing. If the victim is a normal user, a successful CSRF attack can force the user to perform state changing requests like transferring funds, changing their email address, and so forth. If the victim is an administrative account, CSRF can compromise the entire web application. (src: OWASP)
Let’s have a look at an example. You are logging in to your banking app and you want to transfer money to your best friend.
You probably need your friend’s IBAN (international bank account number), an amount you want to send and some nice words. An example HTTP request could look like this:
POST /onlinebanking/transfer/funds/ HTTP/1.1 Host: example.com Content-Length: 92 recipient=mybestfriend&iban=BE71096123456769&amount=100&message=thanks+for+paying+for+dinner
A couple of days later, the money would land in the account of your friend and everything is good. If it was not for an attacker who exploited you at the same time, sending 1337€ to his own account. So let’s see how he is doing that. First, he needs to set up a custom HTML page and host it on his server:
<html> <body> <form action="https://example.com/onlinebanking/transfer/funds" method="POST"> <input type="hidden" name="recipient" value="attacker" /> <input type="hidden" name="iban" value="BE13371337" /> <input type="hidden" name="amount" value="1337" /> <input type="hidden" name="message" value="thanks+for+donating+to+the+attacker" /> <input type="submit" value="automated" /> </form> <script> document.forms.submit(); </script> </body> </html>
Basically, the attacker creates a form that only shows a button saying “automated” (line 8). This button is immediately clicked in an automated fashion by the included script in line 10 as soon as this website is visited.
If the victim is logged in into the banking app, he will have a session cookie stored in the browser’s cookie jar. If the victim then visits the attacker’s page, a request initiating a money transfer is made and the browser automatically adds the valid session cookie. At this point, the attacker has successfully transferred money to his own account.
The impact of cross-site request forgery!
CSRF is very much dependent on the application, the attacker is trying to exploit. Only if the vulnerable application has some functionality that would harm a victim if arbitrarily used by an attacker, there is realistic impact. Next to the example shown above, you could think of functionality to e.g. order a product to a specific address, change your user data, post to social media platforms, etc.
Even though CSRF requires user interaction the impact can be quite severe like for example an account takeover. The impact of CSRF is limited to the functionality of the application (changing data, creating/placing content, …).
An example of CSRF with no real security impact is adding items to someone else’s shopping cart. This also goes for login & logout CSRF, but that doesn’t mean they can’t be used to chain bugs to achieve real impact.
Here are some public write-ups of CSRF vulnerabilities exploited in the wild:
- An example on how login CSRF can be misused by using it in combination with another bug by Ron Chan
- Facebook CSRF protection bypass which leads to Account Takeover by Samm0uda
- How I could have hijacked a victim’s YouTube notifications! (by Yash Sodha)
- How I hijacked your account when you opened my cat picture by Matti Bijnens
- Uber Bug Bounty: Turning Self-XSS into Good-XSS by Jack
- News article demonstrating how CSRF has been exploited on routers
How to prevent cross-site request forgery?
There are various different ways to protect your application against CSRF. Start with checking if the web development framework that you are using has a dedicated capability to protect against CSRF. If not, make sure to implement the following mechanisms:
- Send a CSRF token for every single HTTP request that changes state and validate it on the server-side
- Use the Same-Site cookie attribute to additionally secure your cookies against misuse
Additional reading on CSRF prevention:
- CSRF prevention cheat sheet by OWASP
- Specially for our .NET developers, a post about CSRF in .NET by Troy Hunt
- CAPTCHA does not prevent cross-site request forgery (CSRF) by Linus Särud
Let’s have a look at a video example of a CSRF vulnerability:
Let’s have a look at another video, where we are going to bypass a basic CSRF protection mechanism:
This video by PwnFunction gives a very good visual explanation of CSRF:
Following links are valuable to learn more about CSRF:
- CSRF overview and free labs by Portswigger
- Understanding CSRF, the video tutorial edition by Troy Hunt
- Simple explanation about Cross-Site Request Forgery by Computerphile
Follow us on twitter for more #BugBountyTips and don’t forget to subscribe to our weekly Bug Bytes. A newsletter curated by Pentester Land & powered by intigriti containing more write-ups and helpful resources.