After reading the text, you will know:
- What CSRF vulnerability is.
- What the sample attack scenarios look like.
- How CSRF is used simultaneously with other vulnerabilities.
- How to protect yourself.
CSRF (Cross-Site Request Forgery; alternatively used names: XSRF, session riding or one-click attack) is probably one of the least understood vulnerabilities described in the famous OWASP Top Ten project. It is often confused with the vulnerability of XSS, sometimes also presented simultaneously with other vulnerabilities, which also obscures the image of the essence of the problem.
So what is the essence of this vulnerability? The definition of OWASP says this:
A CSRF attack forces a logged-on victim’s browser to send a forged HTTP request, including the victim’s session cookie and any other automatically included authentication information, to a vulnerable web application. This allows the attacker to force the victim’s browser to generate requests the vulnerable application thinks are legitimate requests from the victim.
Basically: it is forcing the victim’s browser to perform some unauthorized action, such as an HTTP request). Note that this is an attack on the web browser (not the server part of the web application; for the server, the requests created as a result of the attack are fully legal communication from the user’s browser).
CSRF should not be confused with the Man-in-The-Browser attack, where the attacker can also affect the operation of the browser, but it is associated with earlier installation in the victim’s malware system. In the case of CSRF, the system as well as the victim’s browser are not modified permanently in any way. A certain property of web architectures and web browsers is simply used.
CSRF is also not the same as XSS. If we have XSS, it’s possible to implement CSRF, but if our application is susceptible to CSRF, we do not necessarily have to be susceptible to XSS. In turn, Cross-Site Scripting itself can be used to bypass methods of protection against CSRF (see later in the text).
It’s best to learn from specific examples, so let’s see the first scenario of using CSRF susceptibility, forcing the web application administrator to perform the HTTP request, which will add a new user to it.
Example 1 – The Admin Panel of the Forum.
In this case, we have an application (discussion forum) on one domain. The administration panel has limited access (login only from a specific pool of IP addresses). The attacker will want to force the administrator’s browser (use the CSRF susceptibility) to register a new account.
The whole process takes place in a few steps:
attacker registers the account by providing in his login: <img
Other attack methods are also possible (the <img> tag is just an example).
- The administrator logs in and enters the site accepting new accounts.
- When you try to download the image from the <img> tag, the administrator’s browser automatically submits the request to the administrative panel (here we have CSRF) and thus creates a new account in the system with administrative rights.
- For an attacker to be able to log in, it would be sufficient to once again use the CSRF to perform, for example, a request to remove a user’s IP block.
- The attack worked despite the fact that the victim initially could not even get to the administration panel (restriction to the IP address).
- The attacker did not know the administrator’s login or password.
- In the web server logs, the real IP address of the attacked administrator will be visible as the source IP address of the request that added the unauthorized user (this will not be the IP address of the attacker).
- The attacker does not see the response to the request that the administrator was forced to perform, but this does not affect the attack’s performance.
In such a scenario, any Web administration panel can be attacked, which processes (e.g., displays) certain data controlled from the user.
The example shows that by default, web applications are vulnerable to CSRF (unless they used separate libraries or protective mechanisms)—this is how the web architecture was designed.
At this point, a question may arise: what would be the case if the application properly filtered the values passed by the user to the login field? CSRF would also be possible, but the attack path would look a bit different. So let’s see another example.
Example 2. CSRF and Internet Access Router.
This time, let’s trace the scenario using two domains (one domain is the target and the other is an auxiliary domain with some changes introduced by the attacker). In addition, the scenario uses additional vulnerabilities in the web application aside from CSRF.
Vulnerability in the ASMAX router
Some time ago I managed to find some security bugs in the ASMAX router. The most severe one was the possibility of executing the code in the router’s operating system by referring, without being authenticated, to the resource /cgi-bin/script in this way:
So we had two vulnerabilities here:
1. Operating system code injection.
2. Bypassing the authentication (well… total lack of the authentication).
Vulnerability in the router ASMAX – CSRF
How about CSRF in this context? Let’s see an example scenario of an attack on the device, with the additional assumption that the device’s control panel is not available at all from the Internet. This attack will result in unrestricted access (as root) on the device’s operating system.
The whole attack takes place in a few steps (figures 1-4 on the screenshot above):
- The attacker places the <img> tag on any web page with the parameter src directing to the local network, and specifically at: “http://192.168.1.1/cgi-bin/script?system reboot”.
- The victim enters the above page (must be encouraged to do so; this is a frequent requirement of the CSRF)—the HTML page—and the image are downloaded to the victim’s computer (to be rendered in the next step).
- When trying to download the image, the browser performs the request to the router (here the browser has been forced to perform an unauthorized action within the LAN)—CSRF!
- The router is rebooted (or executes any command stitched in point 1. of the image).
- To perform an effective attack, the victim did not have to be logged in to the router (here the fact that access to /cgi-bin/script did not require authentication was used).
- XSS vulnerability was not exploited in the attack.
- The attacker did not know the login or password of the router’s administrator.
- The attack was successful despite the inaccessibility of the device’s administration panel from the Internet.
- The attack required getting the victim to visit another page.
- Instead of executing the reboot command—any other command in the router’s OS could be executed—e.g., tightening the external binary file (backdoor) or unblocking access to the administration panel.
CSRF on a network device – an alternative scenario
Interestingly, if we could not find the vulnerability allowing unauthenticated requests, you could try to use: For example, such a picture <img src=”http://admin: firstname.lastname@example.org/aaa>
In the HTML source of the article, I have placed such a picture, and browsers usually perform the request contained in it (also sending a login and password—assuming that we have the Basic Access Authentication mechanism). Interestingly, for example, if Firefox inserts the URL into the URL bar (http://admin: email@example.com/aaa), it displays the following message:
But when the same URL is included in the IMG tag, the message is no longer present (and the request is sent). It is worth noting that this method could also be used to bruteforce the access password to the router (by generating a large number of IMG tags).
Example 3. – Electronic Banking.
Let’s see another often cited example of using CSRF—this time requiring authentication:
In this case:
- The attacker places a <img> tag on the eeeevil-zite.com website that performs the request corresponding to the transfer of the electronic banking, to their account. It could equally be a self-submitting POST form.
- Victim logs into electronic banking.
- The victim enters another browser tab on eeeevil-zite.com
- The victim through point three realizes unconsciously the request (transfer) to their logged session in electronic banking.
Of course, most electronic banking systems are currently protected against both the susceptibility of CSRF and additionally require additional authorization when transferring to an unknown account—at least this is what is said in theory.
Note also that if the banking would accept HTTP requests only using the POST method, on eeeevil-zite.com we could simply use a properly crafted and self-sending POST form. Therefore, using only POST requests does not protect against CSRF. In this case, OWASP gives a simple example:
Now let’s see what we have for possible methods of protection.
Methods of Protection Against CSRF.
We can implement protection here in several alternative ways. At the same time, it is worth remembering that the most important thing is to protect the functionalities (requests) that perform events that change certain values in the system (e.g., transfer, change password, etc.). The attacker does not see the result of the action directly (see the victim); e.g., CSRF, on the list of information about transfers usually does not give much.
On the other hand, the implementation of protection throughout the system makes it easier to avoid the lack of protection; e.g., for new functionalities (because the implementer forgot about the problem). Let’s get to the details.
The first method recommended by OWASP is the following: Synchronizer Token Pattern; i.e., using random tokens (strings) associated with the logged session (session tokens). When creating a logged user session, a string of characters is generated, which is forwarded to subsequent requests; e.g., in the following way:
The page that supports the form have to,in turn, check whether the passed token is actually the value that was generated by the application.
The attacker obviously does not know the token, so he cannot prepare GET requests accepted by the application (“packaged”; e.g., in the IMG tag) or POST (placed on another domain as an automatically sending form).
Note also that the leakage of such a token results in the possibility of bypassing CSRF protection. An example of a scenario that steals a token from a victim may be the use of XSS vulnerability. In this case, the CSRF carry out side implements in two steps:
- Downloading the token using XSS (using XMLHttpRequest and reading from the token response).
- Generating a request with an already embedded token.
Therefore, if we have XSS in our application, it will most likely be possible to bypass CSRF protection.
As an increase in the level of protection, OWASP also suggests creating tokens not per session but per request (so-called page tokens). So after sending the form, the old token expires and new tokens are generated on the result page (for places that can be reached from the page after sending the form). Such an action may have some unexpected effects when it comes to the functionality of the application (for example, the “back” button will not work—the tokens used on the previous page have already been annulled).
It would also be ideal to accept sensitive actions from the user only using the POST method (then there is no need to include tokens in GET requests. Remember that the GET request parameters are often saved in the WWW server logs or sent in the HTTP Referer header—potentially they may be uncontrolled leak).
In certain situations, it may be convenient to send tokens in Cookies (but on the whole, this method must be based on the previously described scheme: Synchronizer Token Pattern).
Let me remind you once again that the generation of anti-CSRF tokens alone does not solve the problem. It is also necessary to check their correctness. To report CSRF, some CMS authors susceptibility react like this:
We have anti-CSRF tokens, but somehow it turned out that we forgot to check their correctness on the server side.
Anyway, it happens even to giants like Facebook (for the finding of this CSRF, $5,000 was paid as part of the bug bounty program).
Double Submit Cookies
This method consists in sending by the user’s browser the same—randomly generated by the application values—using: HTTP request and cookie. The server checks whether the values stored in the cookie and sent in the request are the same. If they are not the same, an attempt to use CSRF is reported. The advantage of this method is that there is no need to save the previously generated value on the server side.
Use of prepared libraries
If the library/framework we use is protected by CSRF, let’s use it!
For example: django, spring, OWASP ESAPI library or various ways of dealing with ASP.NET.
CSRF is not usually a critical vulnerability, although indicating it on the OWASP Top Ten list definitely does not allow you to ignore the problem. Usually, to use the vulnerability, an additional action is required on the part of the victim (e.g., visiting a specially crafted page), which also reduces (but, of course, not to zero) the probability of a successful attack. We should also remember that without using additional precautions, most web applications are susceptible to CSRF.