Cross-Site Request Forgery (CSRF), most commonly known as XSRF or “Sea-Surf” is one of the most unbridled and notorious online attack on web applications. Essentially, CSRF is a is a web security vulnerability or an attack in which an attacker can maliciously force an end user to perform unwanted actions on a web application to which they are currently authenticated. Conducting a CSRF attack is simple-An attacker may use social engineering (sending a malicious link via email) to trick a user into executing code that would perform certain actions of the attacker’s choosing. The impact of CSRF attack can vary depending on user roles. If the victim is a normal user, a successful CSRF attack can cause the victim to perform state changing operations like changing their email address or transferring funds from their bank account. The impact would be much more devasting if the user holds administrative privileges, as that would lead to the entire web application being compromised. CSRF uses the common logic of circumventing the same origin policy-a critical security mechanism which restricts websites from interfering with each other.
Breaking Down the Exploit Technique:
In essence, following three conditions must be in place to exploit an application using a CSRF attack:
- An Action: There has to be an action within the application that an attacker can induce, such as altering user’s data like email or password or modifying a user’s permissions (in case of an admin account).
- All parameters should be predictable: The requests mentioned in the above step should not have parameters that can NOT be determined by the attacker. For instance, a function in the application where the attacker must know the value of the current password in advance, is not vulnerable.
Exploitation in Action:
Let’s now consider an example to see the above three points in action. Let’s say there’s an application which has a functionality of letting the users change their email IDs. When this action is performed by a user, the HTTP request may look as follows:
POST /email/change HTTP/1.1
The above request meets all the necessary conditions required for a successful CSRF attack:
- Here, the action which the attacker would like to perform is changing the user’s email address, there by triggering a password reset to take total control of the user’s account.
- You can see that the application uses a session cookie as a mechanism to identify the user issuing the request. which user issued the request.
- Finally, with the email parameter in the request, the attacker can clearly determine the value he has to perform the “action” on.
Now with the three mandatory conditions for CSRF in place, the attacker can form a webpage containing the malicious HTML as follows:
form action="https://exploitable-website.com/email/change" method="POST"
input type="hidden" name="email" value="firstname.lastname@example.org" /
You will notice that the above code attempts to replace the victim’s genuine email address with the attacker’s email address. If the victim happens to land on this malicious web page, the following events will occur:
- The attacker's page will trigger an HTTP request to the vulnerable web-site.
- If the victim is currently logged in to the vulnerable web-site and provided that same site cookies are not being used, the browser will automatically include the session cookie in the request
- The vulnerable site will now treat the attacker’s request as if it’s a request sent by the victim himself. Since the web-site isn’t able to figure out that the request hasn’t been made by a genuine user, it’ll go ahead and change the email address of the user.
Is GET safer or POST?
The answer is: NEITHER! To understand the attack from the attacker’s perspective, let’s consider another scenario. Let’s say Sandra wants to transfer an amount of $100 to her friend Alexa through Bank.com, which is vulnerable to CSRF. Jason, an attacker wants to trick Sandra into sending this amount to his bank account instead. To attempt this attack, Jason would take two steps:
- Craft a malicious script/url.
- Cause Alex to unintentionally execute the action using social engineering techniques.
Exploiting GET Requests:
Let’s consider the scenario where the application relies on GET requests to execute actions such as fund transfers. This operation would look like the following:
GET http://bank.com/transfer.do?acct=Alexaamount=100 HTTP/1.1
Analyze the above request from an attacker’s perspective. The beneficiary name (Alexa) and the amount being transferred can be clearly seen in the request so Jason would just have to replace the beneficiary name with his name instead. In fact, Jason can even modify the amount parameter and cause Sandra to send him more money! The malicious request would look like the following:
GET http://bank.com/transfer.do?acct=Jasonamount=1000 HTTP/1.1
Now you’d wonder how social engineering would come into play here. For Sandra to be completely unaware and unable to detect this malicious transaction, Jason could send her an exploit URL disguised as a benign link:
a href="http://bank.com/transfer.do?acct=Jsonamount=1000"View my Pictures!/a
As Sandra would click on this link hoping to view some pictures, the link would instead cause her to transfer $1000 to the attacker.
The attacker could even send Sandra a 0X0 fake image like:
img src="http://bank.com/transfer.do?acct=Jasonamount=1000" width="0" height="0" border="0"
If Sandra receives an email with this image tag, she would not see anything but her browser would still load and submit the hidden fund transfer request to bank.com and a fund transfer would take place without her even knowing.
Exploiting POST Requests:
Let’s assume now that bank.com relies on POST requests instead and the request looks like follows:
POST http://bank.com/transfer.do HTTP/1.1
Now, this request cannot be delivered using an image tag or an a tag as seen in case of GET requests. However, the attacker can still use the Form tags for exploitation:
form action="http://bank.com/transfer.do" method="POST"
input type="hidden" name="acct" value="Jason"/
input type="hidden" name="amount" value="1000"/
input type="submit" value="View my pictures"/
Developers often employ security techniques to harden the application but do not take into account that these mechanisms are not preventing their applications against CSRF. Following are the two techniques that are often thought of as mechanisms to prevent CSRF:
- SSL Certificates: An SSL certificate does not solve everything for you! While SSL has its importance but HTTPS does not offer any protection to your application from being exploited by CSRF (and other vulnerabilities)
- POST requests: As seen earlier in this is article, causing your application to use POST requests instead of get doesn’t offer protection against CSRF. The attacker will still be able to craft a POST request similar to the application and modify the data in it to fit his attack needs, ultimately compromising the application.
- Implementing CORS: CORS is a relaxation of the same-origin-policy. It enables resource sharing between applications hosted on different domains. It’s not a mechanism to prevent CSRF. A CSRF attack via a simple request will either fail or succeed CORS policies implementation.
- Implement Same-Origin-Policy. Note that SOP does not protect against CSRF but work towards limiting its impact. SOP prevents reading of data served from a different origin This means that the attacker’s request will be sent to a site but the result returned by this site cannot be seen by the attacker; thus, making CSRF write-only. In this case, the attacker can exploit CSRF vulnerability in a site implementing SOP but can’t use it by itself to exfiltrate sensitive data from the site.
- Disable CORS.
- Use Same-Site Cookies. It’s a cookie that can be sent only if the requests are being made from the same origin as the cookie.
- Check Referrer Headers. You can block all the requests that don’t have the referrer headers from your own site.
- Don’t click on links present in suspicious emails, avoid visiting shady sites.
- Don’t perform social network communications while logged in to your banking site or use different browsers-one for banking and the other for social network communications, log out of the application after the session.
- Disable scripting in the browser that you’re using. Firefox comes with a plug-in which solves this purpose.
- Make sure you don’t store login credentials to critical applications in your browser.
- Make sure that your anti-virus is up to date.
CSRF is a very serious and stealthy attack which is often not taken seriously. The impact of a successful CSRF attack varies based on user privileges. Since cookies are automatically sent with every request, an attacker can construct malicious request that would lead to CSRF. Even though the attacker won’t have access to the cookie itself or the response body, they can still perform malicious actions with the user’s elevated privileges. It’s therefore recommended to use Same-Site Cookies. Other than the defense mechanisms mentioned here, it’s important that you audit your website or run an automated web scan on a regular bases to detect any vulnerabilities.