Cross-site request forgery (CSRF) is an attack technique that exploits the trust that a web application has in a user’s browser. It allows an attacker to execute an action in the name of an unsuspecting user without their knowledge or consent. It occurs when an attacker tricks a user into sending a malicious request to a web server without their knowledge or consent. The malicious request can be used to gain access to private data, steal credentials, or perform any other action the attacker desires.
In the most typical CSRF attack, the attacker will first craft a malicious request to a vulnerable web application that is triggered by visiting the attacker’s site. Then, the attacker will target victim users. This is often done by embedding it in an email, or by using a malicious link on a website. From then on, depending on which type of request was crafted, the possibilities are numerous. For example, if the malicious request was used to change the user’s email and password and to notify the attacker, they could proceed to steal the account for nefarious purposes. Sometimes, this exploit is chained with other attacks, such as XSS or injection, with the intent to cause more harm to an application while using CSRF to bypass authentication.
CSRF attacks are sometimes referred to by other names such as XSRF, “Sea Surf”, Session Riding, Cross-Site Reference Forgery, Hostile Linking, and One-Click attack (as Microsoft calls it in their threat modeling process). This vulnerability is also formally defined by Mitre in CWE-352: Cross-Site Request Forgery (CSRF).
- GET scenario
The application uses GET requests for administrative functions such as adding and deleting users. In this scenario, the attacker can trick a victim admin user into sending the following request:
GET http://example.com/admin?adduser=BOBemail@example.com&setpermission=admin HTTP/1.1
The attacker tricks the user to browsing that URL by sending the victim admin user a phishing email with the link embedded within it.
The attacker now has an admin account in the example application.
- POST scenario
The main distinction between GET and POST CSRF attacks lies in the manner in which the attack is executed by the target victim. Suppose the example application above has changed to using POST requests, and the vulnerable request looks like this:
POST http://example.com/admin HTTP/1.1 adduser=BOBfirstname.lastname@example.org&setpermission=admin
Such a request can be delivered using FORM tags:
The impact of a CSRF attack can be significant. For example, this vulnerability can be used to steal user information such as passwords, credit card numbers, or other sensitive data. Additionally, it can be used to manipulate web application data, such as deleting records from a database or changing account settings. In some cases, CSRF can be used for elevation of privilege, information disclosure, and/or tampering of data. Furthermore, depending on functions within the application, the attacker might be able to completely take over a user’s account or, in the worst cases, even all the application’s data and functionality.
In addition to the direct impact of a CSRF attack on the users and the application, there can also be indirect impacts. For example, if a user’s account is compromised due to a CSRF attack, it can lead to financial losses or identity theft. Additionally, it can lead to reputational damage for the affected web application’s company, as well as the user who was targeted.
CSRF can result in damage to the integrity, availability, and/or confidentiality of data depending on what the attacker does.
How does CSRF work?
A Cross-Site Request Forgery (CSRF) attack web applications with a design that fails to differentiate between legitimate requests and forged requests controlled by an attacker. It works by including a malicious request from a user that the website trusts. The request can be in the form of a link, an image, a form submission, or a script. If the user has an active session with the website, that session can be used to perform the malicious action on their behalf.
However, CSRF is not possible if any of the three conditions below are true:
- No user ever clicks on untrusted URLs or loads untrusted content.
- The application has no functions that could be used for a CSRF attack.
- The application has strong anti-CSRF controls in place for all relevant functions.
Condition 1 is, simply put, unrealistic. No matter how much users are trained, there is always a risk of a user falling for a phishing or even waterholing attack. Some highly trained attackers even target applications restricted to internal networks and very small user bases just because the application could be used to pivot further into an internal network or help the attacker establish persistent access.
Condition 2 is a bit more realistic. After all, static pages that do not allow stateful changes leave simply no path for CSRF. Altogether, two factors play into wether condition 2 is true or not:
- An action of interest: There is a stateful change / action that an attacker may seek to induce. Examples include:
- Privileged function such as changing permissions for other users, adding or deleting other users.
- Functions limited to users that could be abused by a bad actor such as functionality that allows arbitrary local commands to run on the server or unrestricted file upload.
- Functionality related to a user’s data such as changing their profile picture or changing their password.
- Cookie-based sessions: Performing the action of interest involves sending one or more HTTP requests that rely only on session cookies to identify the person who has made the requests.There is no other mechanism for monitoring sessions or confirming user requests.
If there is no action of interest or no cookie-based sessions (as defined above), CSRF is not possible.
Condition 3 applies to all requests that may potentially be used to perform actions of interest and must be performed by users with active sessions. If all requests have strong mitigation controls in place such as anti-crf tokens or unpredictable parameters, CSRF is not possible.
Prevention mechanisms that DO NOT work
There are a lot of myths out there about how to defend against CSRF that do not work. Once has already been mentioned further up in the article: relying on anti-phishing training or otherwise trusting users to never be phished. Other similar misconceptions include assuming POST requests prevent CSRF, assuming that because there are not many users that the application could not be exploited and using any of the flawed mechanisms listed below:
- Using HTTPS: Using HTTPS correctly ensures that data is encrypted in motion. Although HTTPS alone cannot protect against CSRF, it must be implemented correctly in order for most other security measures to be effective.
- Adding a ‘secret’ cookie: All cookies, even hidden ones, will be sent with every request. Additionally, session identifiers are just utilized by the application container to link the request to a certain session object. The session identifier does not verify that the end-user wanted to submit the request.
- Using Multi-Step Transactions: Multi-Step transactions alone are not enough to stop CSRF attacks, as long as an attacker can predict or figure out what the steps of the transaction are, they can still take advantage of CSRF vulnerabilities.
- URL Rewriting: Putting the user’s session ID in the URL is not recommended as it introduces other security risks.
How to prevent Cross-Site Request Forgery
CSRF attacks are a major threat to web security and can be devastating for businesses and users alike. By taking the necessary steps to protect against CSRF attacks, businesses can protect both users and the application itself.
In order to protect against CSRF attacks, web developers should implement security measures that can be summarized as follows:
- Check if the framework you are using has an integrated CSRF defense mechanism. Many frameworks come with a Synchronizer token system already in place that just needs to be configured correctly. It is highly recommended that you explore if your framework has a built-in CSRF prevention option before you attempt to create a custom token system.
- If your framework does not come with a built-in protection against CSRF attacks, add anti-CSRF tokens to all requests that cause stateful changes and validate them on the server-side. Tokens cannot be guessable by attackers and should not be submitted as cookies.
- Implement a strong Cross-origin resource sharing (CORS) policy.
- Implement custom request headers
- Set and correctly configure the SameSite Cookie Attribute
- Whenever possible, avoid using GET requests for stateful changes
- Make sure that your site is not vulnerable Cross-Site Scripting (XSS). XSS can be used to bypass all CSRF mitigation controls
How to find Cross-Site Request Forgery Vulnerabilities
Predictable parameters: Requests that perform the action of interest do not have any parameters whose cannot be guessed or known by an attacker. For example, when prompting a user to change their password, the function is secure if an attacker must submit a valid current password.