CSRF occurs when a malicious site or program causes a user's browser to perform an unwanted action on a trusted site when the user is authenticated. Any malicious action is limited to the capability of the website to which the user is authenticated.
For example, Jane might login to her online banking portal while checking her email. While there, she may click a link in a phishing email (likely obfuscated by a link-shortening site) which would include a request for Jane's bank to transfer money to an account the attacker controls. Since Jane has already been authenticated by her bank during this session (and the bank's website has a CSRF vulnerability), they automatically carry out the transaction, believing that because it is being requested by Jane's browser, that she has authorized it.
Let's start with a brief overview of HTTP requests and cookies.
HTTP GET: Request used to request data from a web server (ex. typing in a URL (requesting a website) and it loading).
HTTP POST: Request used to send data to a web server (ex. submitting a web form).
Some GET and POST requests are triggered automatically, without user interaction (ex. fetching search suggestions or loading image content with the img src attribute).
Session cookies: Cookies are a way for HTTP to handle state (since it doesn't handle state natively). They contain a unique ID and are used by websites to identify users and to retain their session. After being set, the user's browser sends the cookie to the server with every request it makes in order to identify the user to the site. An attacker can leverage the cookie to impersonate a user by forcing a user's browser to execute a request. If the user is already logged into the site, the cookie will be sent automatically with the request.
How does CSRF work?
In order for a CSRF attack to be carried out, several things need to be true:
- There is an action allowed by the application which an attacker wants to take - changing a password, transferring funds, etc.
- There are not unpredictable request parameters - the attacker can guess (or knows) all of the parameters which the application expects to see from this type of request.
- The action can be carried out by HTTP request(s) and it relies only on cookies (or in some cases browser authentication or client side certificates) in order to verify that the request is coming from the user.
A CSRF attack can either leverage a GET request or a POST request (though a POST request is more complicated and thus less common). Either needs to start with an attacker tricking a victim into loading or submitting the information to a web application. This can take place in a number of ways - for example via a phishing link.
Alternatively, similar to XSS, CSRF can be a stored vulnerability. Stored CSRF occurs when an attacker stores the attack in a field which accepts HTML such as an IMG or IFRAME tag. This would mean that anyone who views the webpage could be impacted. The exploit can be disguised as an ordinary link or hidden in an image tag.
For example, as an ordinary link on a webpage: <a href=“malicious link”>Unsubscribe here</a>
Or, as an image tag : <img src=“malicious link” width=“0” height=“0” border=“0”>
Give me an example.
Imagine that your bank (bank.com) processes transfers using GET requests which include several parameters (the identity of the recipient of the transfer, and how much you want to transfer). For example, if Jim wants to send his friend Bob $10, the request might look like this:
The request also includes a session cookie identifying the account owner so the bank knows where to get the money from.
Now, an attacker may convince Jim to click a link that looks like this (but has been shorted by a URL shortener or hyperlinked cleverly):
Because Jim is already logged in, his browser sends his cookie with the request, his bank believes it is him requesting the transfer, and it is carried out.
Choosing Frameworks Carefully: Use frameworks which have built in protections against CSRF, like .NET. Correct configuration is key. If the framework you're using doesn't have protection, you can add protection with Anti-CSRF Tokens.
Anti-CSRF Tokens: Tokens (also known as synchronizer token patterns) are a server-side protection where the server provides a user's browser with a unique, randomly generated token and checks each request to see if the browser sends it back before carrying out a request. This token is sent via a hidden field and should be a non-predictable, random number which expires after a short time and cannot be reused. Depending on the sensitivity of the page, different tokens can be used for each request, or simply for different forms. The tokens should be compared in a safe way (such as by comparing hashes) and should not be sent in an HTTP get request so they are not a part of the URL and cannot leak via the Referer header.
Use SameSite Flag in Cookies: The SameSite flag marks a cookie so it can only be sent for requests which originate from the same domain. Essentially if www.bank.com wants to make a request to www.bank.com/updatepassword, it's allowed to, but if www.maliciousdomain.com wants to make a request to www.bank.com/updatepassword, it can't send the session cookie and therefore cannot carry out the attack. Most browsers now support this flag, but not all. This should be used as part of a comprehensive defense strategy.
Practice Defense in Depth: Implement a number of controls which, when used together, can provide protection against CSRF. For example, verify the origin with standard headers (determine where the request originates and where it's targeted to ensure they match), use a custom request header (so that without the header the site will not accept the request), or double submit cookies (essentially a second, randomly generated and unknown (to the attacker) parameter which an attacker has to submit with a request in order for it to be successful).
Involve the User in the Transaction: For sensitive actions such as money transfers or password changes, require the user to take action (such as CAPTCHA, one-time tokens, or re-authentication). This shouldn't be over-used as it may annoy users, but it is a good way to protect highly sensitive transactions.
Examples of Measures that Don't Work:
- Multi-Step Transactions: It doesn't matter how many steps there are as long as the attacker can predict/determine each one.
- HTTPS: Always a good idea, but doesn't do anything to protect against CSRF.
- URL Rewriting: This would prevent attackers from guessing the victim's session ID during a CSRF attack, but would then allow an attacker to see it in the URL. Swapping one flaw for another isn't a good idea.
- Using a Secret Cookie: Even a secret cookie is submitted as part of the request, meaning that the attacker can still leverage it.
- Only Accepting POST Requests/avoiding GET Requests: Forged POST requests can still be used to execute a CSRF attack.
Other Names for CSRF:
CSRF is also known as XSRF, Sea Surf, Session Riding, Cross-Site Reference Forgery, Hostile Linking, One-Click Attack.