Cross-site request forgery (CSRF) is a web vulnerability that lets a malicious hacker trick the victim into submitting a request that allows the attacker to perform state-changing actions on behalf of the victim. Cross-site request forgery is also called XSRF, sea surf, session riding, or one-click attack.
Severity: |
![]() ![]() |
severe in rare circumstances |
Prevalence: |
![]() ![]() ![]() ![]() |
discovered often |
Scope: |
![]() ![]() ![]() |
web applications with authentication |
Technical impact: | attacker triggers unauthorized actions | |
Worst-case consequences: | depend on application capabilities | |
Quick fix: | use anti-CSRF tokens |
Most web applications require authentication and some authenticated users are able to perform very sensitive actions. Authentication in web applications is often performed based on user sessions. After you authenticate, your browser stores a session cookie on your computer and sends it with every request you make to that web application. Less commonly, applications can also use NTLM or Basic Auth for authentication instead of session cookies, or even recognize users based on their IP address.
When you are using an application, many HTTP requests sent from your browser to the application are the result of your explicit actions, for example, when you type an URL in the address bar or click a link. However, other HTTP requests are sent by your browser implicitly as it processes code included on the current web page. For example, if the page includes an image, the image will be fetched by a separate HTTP request.
Such implicit requests can also be directed to domains that have nothing to do with the location of the page you’re viewing. For example, an image displayed on testinvicti.com may in reality come from example.com. The crucial thing in such cases is that requests to both locations come from the same browser, so your current authentication method (whether it’s a session cookie or another method) applies to both locations. So if your browser opens testinvicti.com and fetches an image from example.com, thus creating a user session at example.com, the example.com web application will treat you as an authenticated user (even though you originally opened testinvicti.com, not example.com).
Combined, these two behaviors can be exploited to perform cross-site request forgery attacks in the following way:
Note that CSRF used to have its own separate category in the OWASP Top 10 (for example, A5:2013). However, with the development of more efficient AppSec and therefore the reduced impact of such vulnerabilities, since 2017 OWASP decided to merge CSRF into another, more generic category.
CSRF vulnerabilities can be based on GET or POST requests.
In the case of CSRF based on GET requests, the attacker can simply use an image tag (or any other tag that allows for cross-site requests) on a malicious page:
<img src="http://example.com/bank.php/?action=transfer&target=attacker_account">
When the user visits the page with the above image tag (for example, after clicking a malicious link), the user’s browser tries to open the image but instead makes a GET request to the targeted site, thus performing a malicious action while logged into the user’s account. Assuming that the user is authenticated on example.com, the web application will be unable to differentiate between a legitimate user request and a malicious request, since they are both sent from the same browser.
In the case of CSRF based on POST requests, the attacker needs to work a bit harder. The simplest way to perform such an attack is to force the user’s browser to automatically submit a form by using JavaScript:
<body onload="document.csrf.submit()">
<form action="http://example.com/bank.php" method="POST" name="csrf">
<input type="hidden" name="action" value="transfer">
<input type="hidden" name="target" value="attacker_account">
</form>
The onload
argument of the <body>
tag will cause the browser to submit the form as soon as the user opens the malicious page.
The developer of a financial business application creates a function that allows users to set the email address they want to use for daily financial reports from the application. To set or change the email address, an authenticated user must fill out an HTML form on the http://example.com/set_email.php page:
<form action="/set_email.php" method="post" id="set_email">
<label for="email">Enter the email address to receive reports:</label>
<input type="email" id="email" name="email">
<button type="submit" form="submit" value="submit">Set email</button>
</form>
The attacker creates a malicious page http://example.attacker/exploit.html with the following content:
<body onload=document.email.submit()>
<form action="http://example.com/set_email.php" method="post" name="email">
<input type="hidden" id="email" value="attacker@example.attacker">
</form>
</body>
Then, the attacker creates a phishing email and sends it to a user of the financial application, tricking the user into visiting http://example.attacker/set_email.html. Assuming that the user is already logged in to the application at example.com, the application will receive the forged request and change the reporting email to attacker@example.attacker. As a result, the attacker will receive daily sensitive reports about the company’s financial operations.
Cross-site request forgery vulnerabilities are considered medium severity for several reasons:
Due to the nature of CSRF, there are no known major breaches caused by successful CSRF attacks. However, in the past, several popular web applications were found to be vulnerable to cross-site request forgery and could have been used in targeted attacks:
These are just a few examples out of many and while we are not aware of any dire consequences of these vulnerabilities, it is possible that they were used for individually targeted attacks that simply never made it to the media.
The best way to detect CSRF vulnerabilities varies depending on whether they are already known or unknown.
The primary method of protecting against CSRF attacks is to create a way for the web application to differentiate between legitimate requests (made on behalf of that application) and potentially malicious ones (sent by the application under outside influence). The following two techniques are the most effective and widely used.
This protection technique is based on sending a special token with each legitimate request and always validating that token when receiving requests. This anti-CSRF token, sometimes called a synchronizer token, is generated on the server side and attackers have no way of knowing its correct value – it is known only to the web application and the browser. Requests sent as CSRF attack attempts won’t have a valid token, which allows the application to ignore them as invalid, log them as attack attempts, or even raise an alarm.
Once you have generated an anti-CSRF token, you can include it in a hidden form field or automatically add it in a special header for every request. Note that anti-CSRF tokens should be used not just for every form in the authenticated zone of the web application but also for unauthenticated login forms, APIs, and AJAX requests (XMLHttpRequest
).
There are many libraries available to generate and verify anti-CSRF tokens safely using cryptographic techniques, for example, Paragonie anti-CSRF for PHP and GDS anti-CSRF for Java. We recommend using such libraries instead of trying to create your own code, which would be more prone to errors and harder to maintain.
Also note that while many modern development frameworks already have synchronizer tokens built in, their CSRF protection is often limited to HTTP methods that are designed for state-changing requests. This means that GET requests are typically not covered. Therefore, if a developer creates state-changing functions that take their input from GET requests, which is very bad programming practice, these requests will not be covered by built-in CSRF protection.
Another very effective way to differentiate legitimate requests from potentially harmful ones is by looking at the origin of the request. You can safely assume that if the request comes from the same domain/site, it’s most likely legitimate. If it comes from an external domain, it could be harmful. To take advantage of this method, you can use a specific cookie security flag.
Modern browsers support the SameSite
cookie attribute, which you can use when setting your session cookies. This can have one of three settings:
Lax
: The browser does not send cookies for cross-site subrequests, for example, to load images or frames into a third-party site, but does send cookies when a user follows a link.Strict
: The browser sends cookies only in a first-party context and does not send them at all with requests initiated by third-party websites.None
: The browser sends cookies in all contexts, but you must also set the Secure
attribute or the browser will block the cookie.While most modern browsers set the SameSite
attribute to Lax
by default for all cookies, we recommend that you manually set it in your web application anyway (to Lax
or Strict
, depending on whether you need cross-site subrequests or not). This is in case you get users with older browser versions that set SameSite
to None
by default.
Unfortunately, if this is the only method you use to protect your users against CSRF, a small number of users with legacy browsers such as Internet Explorer that don’t support SameSite cookies at all will remain vulnerable to CSRF attacks.
While synchronizer tokens and SameSite cookies are considered the best methods of CSRF protection, there are also other ways to differentiate between legitimate and potentially malicious requests. Some developers will, for example, use the referer header to spot this difference. Others attempt to implement protection based on mechanisms such as the same-origin policy, which is ineffective against CSRF.
While methods such as referrer detection can be effective, they are not as foolproof as anti-CSRF tokens, so we do not recommend using any methods other than synchronizer tokens and SameSite cookies, preferably together.
The best way to mitigate CSRF attacks is to make sure that all users in your business use modern, fully updated web browsers that support SameSite cookies. This allows your web applications to use SameSite cookies as the primary CSRF protection and your developers don’t have to implement any safeguards in the web application code (because all cookies are set to Lax
by default).
You can enforce mitigation by disabling access to your web applications for browsers that don’t support SameSite cookies. However, this method could have a negative impact on your users (for example, it will block all Internet Explorer users) and therefore should be introduced with caution.
Classification | ID |
---|---|
CAPEC | 62 |
CWE | 352 |
WASC | 9 |
OWASP 2021 | A1 |
Cross-site request forgery (CSRF) is a web vulnerability that can allow malicious hackers to trick users into sending requests that perform malicious state-changing actions on behalf of the victim.
CSRF is typically considered a medium-severity vulnerability because for this type of attack to be effective, it needs to be aimed at a specific person or a small group with high privileges. CSRF attacks is usually carefully prepared to take advantage of a specific user in the business, such as the CEO, the administrator, or a financial department employee.
Find out more about a critical CSRF vulnerability in Facebook in 2019.
The most popular way to protect against CSRF is to use anti-CSRF tokens. This protection method is based on sending a special token with each legitimate request and always validating that token when receiving requests.