What Is Cross-Site Request Forgery (CSRF)
Networking
15/04/2021
Imagine the following example: A user is logged into his online bank account which allows him to send money to another person by specifying an account number and amount in a form.
Suddenly, (s)he receives a dubious email from his/her bank and makes the foolish decision to click on a link inside the email. Before (s)he knows it, some money has been sent to another individual, all unwittingly! 😭
What happened? Cross-Site Request Forgery, that's what happened.
How it works
The idea behind this exploit is simple: the server cannot (easily) distinguish where a request is coming from. Even if it's from another tab, i.e. website, in your browser.
In the earlier scenario, the malicious hacker recreated the bank transfer form on another website. How? Well, maybe he's got access to the same bank and can therefore inspect the code in his browser.
All he needs to know is what kind of information the server is expecting (e.g. bank_account_number
and amount
) and which endpoint to send it to (e.g. /transfer?confirm=true
).
Hidden and ready to send
Okay, so the link that the user clicked on opened the hacker's malicious website which contains the duplicated form. Yet, all the user sees is a webpage full of cat pictures (why not? 😎).
What the user doesn't know is that there's a hidden form on the page, prefilled with values and ready to be sent (using JavaScript) as soon as the page is loaded.
Credentials abuse
Some of you might be asking, doesn't the request to the server need to be authorized? Well, yes. But remember that the user is already logged in. And in case you weren't already aware of it, the cookie containing the session ID is automatically sent to the server, even if the request is done from a completely different website.
How to prevent it
As mentioned earlier, this exploit relies on the server not knowing where the request originated from. While in theory, it could figure that out with the Referer
header in a request, in practice, it isn't always sent for various reasons such as security and privacy.
Using a token
The most common solution to this problem are CSRF tokens, which are used in all modern web frameworks. The idea is as follows:
- Generate a random string of letters and numbers on the server-side (e.g.
CIwNZNlR4Xbi1JF39I8yWnWX9wX4WFoz
), then - Embed this token in the form when it's sent to the client, and
- Only accept form submissions that contain this very token
More often than not, the token is single-use only, which makes it impossible to do any CSRF attacks.