Cross-site request forgery (CSRF)

What is cross-site request forgery?

Cross-site request forgery (CSRF, XSRF, sea surf, session riding, one-click attack) is a cybersecurity term for a specific class of web application security vulnerabilities. If a malicious hacker is able to trick the victim into submitting a request that lets the attacker perform state-changing actions on behalf of the victim, it means the application has a cross-site request forgery vulnerability.

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

How does cross-site request forgery work?

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:

  1. The victim is authenticated in the target web application (such as example.com).
  2. The attacker uses social engineering to trick the victim into visiting a malicious website (for example, testinvicti.com).
  3. The malicious web page includes code (such as an image tag) that causes the victim’s browser to send an implicit request to the target (such as example.com).
  4. The malicious request causes the target to perform actions that were not intended by the user. The consequences will vary depending on the application.

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.

Types of cross-site request forgery vulnerabilities

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.

Example of a cross-site request forgery attack

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.

Potential consequences of a cross-site request forgery attack

Cross-site request forgery vulnerabilities are considered medium severity for several reasons:

  • In this type of attack, the attacker never receives the HTTP response and therefore cannot use this technique to directly read/access sensitive information. They don’t even have access to the session cookie value that is sent with the malicious request.
  • The attack is limited by the functionality of the web application, or, more precisely, what the application allows the current user to do using a state-changing request. For example, if you have a ticketing system and the current user can only create and resolve issues, the most that an attacker can achieve with CSRF is clear the ticket queue. They won’t, for example, be able to get the administrator’s credentials.
  • This type of attack is most effective when aimed at a specific person or a small group of people with high privileges. Unlike with cross-site scripting (XSS), it often makes no sense to send a malicious CSRF payload to a large number of random victims. CSRF 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.

Examples of known cross-site request forgery vulnerabilities

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.

How to detect cross-site request forgery vulnerabilities?

The best way to detect CSRF vulnerabilities varies depending on whether they are already known or unknown.

  • If you only use commercial or open-source web applications and do not develop web applications of your own, it may be enough to identify the exact version of the application you are using. If the identified version is susceptible to CSRF, you can assume that your website is vulnerable. You can identify the version manually or use a suitable security tool, such as a software composition analysis (SCA) solution.
  • If you develop your own web applications or want the ability to potentially find previously unknown CSRF vulnerabilities (zero-days) in known applications, you must be able to successfully exploit the CSRF vulnerability to be certain that it exists. This requires either performing manual penetration testing with the help of security researchers or using a security testing tool (scanner) that can use automation to exploit web vulnerabilities. Examples of such tools are Invicti and Acunetix by Invicti. We recommend using this method even for known vulnerabilities.

How to prevent cross-site request forgery vulnerabilities in web applications?

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.

Anti-CSRF tokens

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.

SameSite cookies

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.

Other protection techniques

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.

How to mitigate cross-site request forgery attacks?

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.

ClassificationID
CAPEC62
CWE352
WASC9
OWASP 2021A1

Related blog posts