What is CSRF?
Cross Site Request Forgery (CSRF), Sea Surf, or XSRF for short, is considered a sleeping giant in the world of web security, due to the fact that it may not be taken as seriously as it should, even though it can prove to be a stealthy and powerful attack if executed properly. Additionally, it is also a common attack that is regularly exploited, which is why it has secured its spot on OWASP’s Top 10 list several times in a row. This being said, an exploited Cross-site Scripting (XSS) vulnerability will always trump any CSRF vulnerability, as CSRF attacks have a major limitation. CSRF only allows for state changes to occur and therefore cannot cater attacks that require the attacker receiving the contents of the HTTP response.
Cross Site Request Forgery (CSRF) is an attack whereby a malicious entity tricks a victim into performing actions on behalf of the attacker. The impact of the attack would depend on the level of permissions that the victim being exploited has. The actions being perpetrated by the attacker will surely have a greater effect if the victim performing the actions is at an administrative level versus a low level user, with less privileges. CSRF attacks take advantage of the fact that a web application completely trusts a user, once it can confirm that the user is indeed who they say they are.
There are two main parts to executing a Cross Site Request Forgery (CSRF) attack, the first part being to trick the victim into clicking a link or loading up a page. This is normally done through social engineering which works exceptionally well into leveraging a victim’s curiosity to click on malicious links. The second part is to send a crafted request in the victim’s browser, that will send a legitimate looking request to the web application. The request will be sent with the values that the attacker wants, including any Cookies that the victim has associated with that website. This way, the web application knows that this victim can perform certain actions on the website and any request sent with these HTTP credentials or Cookies, will be considered as legitimate, even though the victim would be sending the request on the attacker’s command.
When a request is made to a web application, the browser will check if it has any Cookies associated with the web application’s origin that will need to be sent with the request. If it is the case, this authentication data, such as Cookies for example, will be included in any request being sent to this web application. This is done to provide the victim with a seamless experience, so they would not be required to re-authenticate for every page that they visit. If the website approves of the Cookie being sent and considers the session as still being valid, an attacker may use CSRF to send requests as if the victim is sending them, without the website being able to distinguish between requests being sent by the attacker or by the victim, since requests are always being sent by the victim with their own Cookie.
A CSRF attack simply takes advantage of the fact that the browser sends the Cookie to the web application automatically with each and every request.
Understanding how an attack is carried out
Cross-site Request Forgery (CSRF) will only be effective if a victim is authenticated. This means that the victim will need to be logged-in, in order for the attack to succeed. Since CSRF attacks are used to bypass the authentication process, there may be some elements that are not affected by CSRF attacks, even though they are not protected against it, such as those that are publicly accessible. These do not require a logged in victim to send the request, since anyone can do this. For example, let’s take a contact form on a website, where visitors can send queries through the form. This does not require the victim having any privileges to submit the form, meaning that it does not matter if an administrator victim or a low privilege victim submits the form. The problem arises when a victim with additional privileges would be performing actions that are not accessible to everyone, which is when CSRF attacks are utilised.
To ensure that the victim is logged in to the web application that is to be exploited, attackers started targeting specific victims of the same web application, to ensure that the CSRF attack will be a success.
A CSRF attack example, using a GET request
The example that will be described in this section is rather simple and it does not necessarily reflect a real-world example, however, it serves as a good example to show how CSRF attacks work.
GET requests are by their very nature meant to be idempotent, which means that they should not be used to perform state changes, therefore, sending a GET request should have not change any data. Of course, some web applications still use GET instead of the more appropriate POST to perform state changes for operations such as changing a password or adding a user.
When the malicious link that we mentioned earlier is clicked, the attacker may direct the victim to their own malicious web application that will execute a script that will in turn trigger the victim’s browser to send an illegal request. This request is defined as illegal since the victim is not aware that it is being sent, even though it appears to the web server as if the user sent it, because it includes the necessary Cookies that the web server needs to verify that a victim is who they say they are.
Imagine if www.example.com processed fund transfers through a GET request that will include two parameters: the amount that is to be transferred and the identifier of the account to which the money will be transferred. The below example shows a legitimate URL, which will request that the web application transfers a 100,000 units of the appropriate currency to Fred’s account.
The request will include with it the Cookie for the authenticated user, so there would be no need to define which account the money will be transferred from. This means that if a normal user would access this URL, they would be required to authenticate, so the web application will know from which account the funds will be withdrawn. Now that we know how this request can be used for legitimate reasons, we can figure out a way how to trick a victim into sending the request that the attacker wants, while authenticated as the victim .
If the web application being exploited is expecting a GET request, then the attacker can include an tag on their own website, that instead of linking to an image, it will send a request to the bank’s web application:
<img src="http://example.com/transfer?amount=1000000&account=Fred" />
The browser, under normal circumstances, will automatically send the Cookies that are related to that web application, therefore allowing the victim to perform a state change on behalf of the attacker, where the state change is a transfer of funds.
CSRF attacks using POST requests
Although this attack works on GET requests considerably easily, attackers can also make use of the POST method to send requests. In fact, most state changing requests will be done through POST requests which will send any parameters and values in the request body and not the URL itself as in a GET request. This means that exploitable web applications will be more likely to accept POST instead of GET requests when a state change is involved.
Take the following example using the onload function, which will automatically send a request from the victim’s browser as soon as the page loads up. Let’s take the following example:
<body onload="document.csrf.submit()"> <form action="http://example.com/transfer" method="POST" name="csrf"> <input type="hidden" name="amount" value="1000000"> <input type="hidden" name="account" value="Fred"> </form>
As soon as the page loads, the onload function ensures that the form named csrf is submitted, which will in turn send the POST request. Taking a look at the csrf form, we can see that it includes two parameters and their values, that have been statically set up by the attacker, where example.com will identify the request as legitimate, since it will include the victim’s Cookies.
This is not the only way to execute this attack. An attacker can also make use of an iframe, that would have its attributes set up to make it invisible. Using the same onload function, the attacker can then load up the iframe of their own malicious web application and as soon as the iframe loads, the request will be sent.
Preventing CSRF vulnerabilities
Although there have been a variety of proposed CSRF prevention mechanisms, not all of them are effective in all scenarios. The following implementations prove to be effective for a variety of web applications while still providing protection against CSRF attacks.
The most popular implementation to prevent Cross-site Request Forgery (CSRF), is to make use of a challenge token that is associated with a particular user and can be found as a hidden value in every state changing form which is present on the web application. This token, called a CSRF Token or a Synchronizer Token, works as follows:
- The web server generates a token
- The token is statically set as a hidden input on the protected form
- The form is submitted by the user
- The token is included in the POST data
- The web application compares the token generated by the web application with the token sent in through the request
- If these tokens match, the request is valid, as it has been sent through the actual form in the web application
- If there is no match, the request will be considered as illegal and will be rejected.
This protects the form against Cross-site Request Forgery (CSRF) attacks, because an attacker crafting a request will also need to guess the anti-CSRF token for them to successfully trick a victim into sending a valid request. What’s more, is that this token should be invalidated after some time and after the user logs out.
For the anti-CSRF mechanism to be implemented properly, it will also need to be cryptographically secure, so that the token itself cannot be easily guessed, which is a possibility if the token is being generated based on a predictable pattern.
It is also recommended that you make use of the readily available option in popular frameworks that will defend against CSRF attacks for you, meaning that you should refrain from rolling your own anti-CSRF mechanism, if possible. This allows less room for error, while making the implementation quicker and easier.
Same Site Cookies
CSRF attacks are only possible since Cookies are always sent with any requests that are sent to a particular origin, which is related to that Cookie. Due to the nature of a CSRF attack, a flag can be set against a Cookie, tuning it into a same-site Cookie. A same-site Cookie is a Cookie which can only be sent, if the request is being made from the same origin that is related to the Cookie being sent. The Cookie and the page from where the request is being made, are considered to have the same origin if the protocol, port (if applicable) and host is the same for both.
A current limitation of same-site Cookies is that not all modern browsers support them, while older browsers do not cater for web applications that make use of same-site Cookies (click here for a list of supported browsers). At the moment, same-site Cookies are better suited as an additional defense-in-depth layer due to this limitation, while still making use of other CSRF protection mechanisms.
Cookies are intrinsically vulnerable as they are automatically sent with each request, allowing attackers to easily craft malicious requests leading to CSRF. Although the attacker cannot obtain the response body or the Cookie itself, the attacker can perform actions with the victim’s elevated rights. The impact of a CSRF vulnerability is also related to the privilege of the victim, whose Cookie is being sent with the attacker’s request. While data retrieval is not the main scope of a CSRF attack, state changes will surely have an adverse effect on the web application being exploited.