CSRF Today: Techniques, Mitigations and Bypasses

Chirag Rai
9 min readSep 2, 2021

--

Hi folks, hope you all are doing great! This is my second blog post and is a pretty long one. The reason being the depth I have gone to with the topic, to include all the relevant information as much as possible into one blog. Hope you all enjoy it and learn something new. I would also like to add that this blog is more of from an attackers point of view rather than from a developers point of view; nonetheless, I have tried to make this blog as simple as possible so as to help out maximum audience belonging to different fields. Lets begin!

Cross-Site Request Forgery (CSRF) is an attack where an attacker forces a user to perform unwanted actions on a web application in which they’re currently authenticated, without users knowledge (Eg; Money Transfer, Password Change, Comments on a post,etc). CSRF attacks are also known by a number of other names, including XSRF, “Sea Surf”, Session Riding, etc.

How does an attacker achieve this?

An overview of how an attacker may successfully perform this type of attack is as follows:
1) The victim user authenticates himself on the vulnerable application using his credentials.
2) The attacker lures the victim user to visit a malicious site.(Using the same browser on which the victim is authenticated on the vulnerable application)
3) The victim user visits the malicious site.
4) The site shows a button “Click Here”. As soon as the victim user clicks on the button the malicious site sends a request to the vulnerable application to perform some critical action on behalf of the victim user(For eg; some monetary transaction or password change).
5) Since the web browser is built to automatically attach the user’s cookies along with every authenticated request, for ease of usage, the browser will directly send the request to the vulnerable site along with user’s session cookies, hence making it an authenticated request.
6) The vulnerable application receives this request which contains victim user’s session cookies and processes it as a genuine request. The victim user is completely unaware of any action performed by him in this process.

CSRF zine created by sec_r0

The code used by the attacker to send an authenticated request to the vulnerable site from the attacker-controlled domain can be similar to this code mentioned here:

<html>
<body>
<script>history.pushState('', '', '/')</script>
<form action="https://www.vulnerbale-site.com/index.php?page=transfer-amount.html" method="POST">
<input type="hidden" name="amount" value="5000" />
<input type="hidden" name="to" value="attacker -account-id"/>
<input type="hidden" name="send" value="send" />
<input type="submit" value="Click Here" />
</form>
</body>
</html>

All the attacker needs to do here is to host the malicious code on his website and lure the victim user to visit the malicious site in his browser where he is logged in to the vulnerable application.

Victim opens CSRF POC in his Browser

The moment, the victim clicks on “Please Click Here”, a request sent in the back-end from the victim’s browser containing his session cookies.

Request sent from victims browser to the application server

This request is accepted by the server and BOOM! Attack successful. The victim doesn’t have a slightest clue that he just transferred 5000 worth of currency to the attackers account.

Note- For successful exploitation of this kind of attack , it is not required for the victim to click on something on the malicious site, like “Please Click Here” button in the above example. The attacker can just as easily create an HTML code that automatically sends the request to the vulnerable site as soon as the victim user opens the malicious webpage in his browser. The impact of this vulnerability depends on the vulnerable application functionality. This attack can also be escalated to victim account takeover depending on the application functionality.

How can a user prevent himself from being victim to such attacks?

  • A user should completely avoid visiting any untrusted website in his browser. One should even avoid opening any kind of untrusted HTML code in his browser to prevent such attacks.
  • Always logout of the current application and close browser session before opening any other website in the same browser. Avoid opening multiple tabs with different website open in each one when using a critical application.

How does a developer mitigate this vulnerability?

Overall this vulnerability can simply be mitigated by having a mechanism in place that differentiates a genuine request from a non-genuine one on the server-side.

This can be achieved using:

  • Anti-CSRF Tokens
  • Double Submit Cookie
  • Validating the Referrer and Origin of the request
  • Sending data in JSON/XML format
  • Sending some data in the request headers that violates the Browser’s Same Origin Policy if the request is sent cross-domain. (For eg; Authorization header that is used to authorize a user on the application, also used for authentication in certain applications)
  • SameSite Cookie attribute
  • Captcha
  • Viewstate

Let us discuss these mitigations in detail and how an attacker may attempt to bypass these restrictions:

1)Application has Anti-CSRF token implemented:

A unique, non guessable and long enough token that is sent along with every authenticated request where the user performs some action on the vulnerable site.

For example, observe the request below where a user is adding a new entry to his blog

POST /index.php?page=add-to-your-blog.php HTTP/1.1
Host: testsite.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:89.0) Gecko/20100101 Firefox/89.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 78
Origin: http://testsite.com
Connection: close
Cookie: showhints=1; PHPSESSID=tr7qoooe0ifkb93s59jsjel1u4
Upgrade-Insecure-Requests: 1

Anti-Csrf-token=jhGHU12HJUJJSKfb1CKPOEGDCNDMFKGHSSgh&blog_entry=test&add-to-your-blog-php-submit-button=Save+Blog+Entry

This kind of setup if properly implemented is one of the best mitigations available against CSRF. Since the token is long, unique per session and unguessable, an attacker cannot guess the value of the Anti-CSRF Token sent in the above request for the victim user and hence won’t be able to attack the victim user.

However, an attacker may attempt the below mentioned methods to try and bypass the protection:

-One can try and remove the Anti-CSRF TOKEN entirely from the request

POST /index.php?page=add-to-your-blog.php HTTP/1.1
Host: testsite.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:89.0) Gecko/20100101 Firefox/89.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 78
Origin: http://testsite.com
Connection: close
Cookie: showhints=1; PHPSESSID=tr7qoooe0ifkb93s59jsjel1u4
Upgrade-Insecure-Requests: 1

blog_entry=test&add-to-your-blog-php-submit-button=Save+Blog+Entry

-Or just omit the value of the Anti-CSRF token

POST /index.php?page=add-to-your-blog.php HTTP/1.1
Host: testsite.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:89.0) Gecko/20100101 Firefox/89.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 78
Origin: http://testsite.com
Connection: close
Cookie: showhints=1; PHPSESSID=tr7qoooe0ifkb93s59jsjel1u4
Upgrade-Insecure-Requests: 1

Anti-Csrf-token=&blog_entry=test&add-to-your-blog-php-submit-button=Save+Blog+Entry

-If the attacker has two accounts on the vulnerable application he can try using a CSRF token meant for one of the accounts in the second account’s request. If this is accepted ,it means the application isn’t validating the CSRF token against the session for which it is valid on the server side.

-An attacker can also try re-sending an old valid CSRF token in the current session and check if the application accepts this old token.

2) Application uses Double Submit Cookie

A Double Submit Cookie is when the application sends an Anti-CSRF token in the cookie as well as in the request body.

Double Submit Cookie sent in the request

On the server-end, the application checks if the token sent in the cookie matches the token sent in the request body. If there’s a mismatch, the application discards the request, if not, the application will further process the request.
Certain times in this kind of setup, the developer doesn’t feel the need to validate the token sent in the request against the active session. This may pave in a way for bypassing the protection mechanism, in case the attacker can find a way to manipulate the application cookies (Specifically the Anti-CSRF token value sent in the cookie) using Session Fixation vulnerability.

The attack can be demonstrated as below;
1) The attacker finds the application is using Double Submit Cookie to prevent CSRF.
2) The attacker looks for a session fixation vulnerability in the application and finds out the application is vulnerable to it.
3) The attacker now finds a way to fix the session for the victim user and manipulates the victims Anti-CSRF-Token Cookie to his own Anti-CSRF token value. For eg; if the application had set ‘Anti-CSRF-Token= jhGHU12HJUJJSKfb1CKPOEGDCNDMFKGHSSgh’ as a cookie for the victim, the attacker will manipulate this cookie into ‘Anti-CSRF-Token=Manipulated CSRF Token’ in victims browser by exploiting the Session Fixation vulnerability he found.
4) The attacker generates a CSRF POC with this manipulated cookie value(Anti-CSRF-Token=Manipulated CSRF Token) in the CSRF body and hosts this code on ‘attacker.com/csrf.html’

<html>
<body>
<script>history.pushState('', '', '/')</script>
<form action="https://www.vulnerbale-site.com/index.php?page=add-to-your-blog.php" method="POST">
<input type="hidden" name="blog_entry" value="test" />
<input type="hidden" name="CSRFToken" value="Manipulated CSRF Token"/>
<input type="hidden" name="add-to-your-blog-php-submit-button" value="Save+Blog+Entry" />
<input type="submit" value="Submit request" />
</form>
</body>
</html>

5) The attacker sends this URL to the victim. The victim opens this URL in his browser where he is authenticated on the vulnerable application.
6) The POC executes and sends a request to the vulnerable application which will contain the FIXED Anti-CSRF token in the cookie and the same Anti-CSRF token in the request body.

Manipulated Double Submit Cookie sent in the request

7) The server receives this request and checks the Anti-CSRF token values in the Cookie and the body. It confirms the values are same and accepts the request as a valid one since it does not validate the token against the logged in session.
8) The attacker has successfully performed a CSRF attack.

3) Application validates the Referrer or the Origin of the request received

The Referrer and Origin header in a request tells the server about the page from where the request originated.

A request sent from attacker.com will have a request as such

Request sent from attacker.com to vulnerablesite.com

An application validating Origin and Referrer of a request received can prevent possible CSRF attack. Possible bypasses for this kind of protection can be

-Restricting the CSRF POC from sending the Referrer header using
<head>
<meta name=”referrer” content=”no-referrer”>
</head>

-One may also try to bypass the whitelisting/blacklisting mechanism used by the application.
If an application validates the Referrer header to contain vulnerable-site.com, attacker may register a domain as vulnerable-site.com.attacker.com and upload your CSRF POC here. Other possible bypass scenarios are;
Using @ character in the domain. For example: https://vulnerable-site.com@attacker.com
Using the # character to indicate a URL fragment. For eg; https://attacker.com#vulnerable-site.com
-One may even search for a malicious file upload vulnerability on the application where he may try uploading the CSRF POC to the application itself or to any of its sub domains. Now, he may share the url of this uploaded CSRF POC(If publicly accessible)with the victim. Since the request is generated from the application itself, the Referrer and the Origin will contain the valid application domain and hence the attack can be successfully executed. One more way to achieve this is to find an exploitable Cross-Site Scripting vulnerability in the application or a sub domain. Cross-Site Scripting can also be used to steal a valid CSRF Token belonging to the victim.

Continued here

References:

Special Thanks to Rohit(sec_r0) for allowing me to use his CSRF Zine for better explanation:

--

--

Chirag Rai

A Cyber Security Enthusiast by heart and a Security Consultant by profession. Twitter: https://twitter.com/crai_in