Cross-Site Request Forgery (CSRF) in Plain English
By- August 14, 2014
Welcome back to my weekly series where I explain different types of website attacks in plain English. So far, I’ve tackled two of the most common vulnerabilities on the web today: SQL injection and Cross-Site Scripting. Today, I’d like to talk about another common vulnerability that the Tinfoil scanner finds all too often: Cross-Site Request Forgery.
Cross-Site Request Forgery (CSRF or XSRF) is another example of how the security industry is unmatched in its ability to come up with scary names. The attack itself is quite simple. A CSRF vulnerability allows an attacker to force a logged-in user to perform an important action without their consent or knowledge. It is the digital equivalent of an attacker forging the signature of a victim on an important document. Furthermore, the attack leaves no evidence behind, since a forged request contains all of the information and comes from the same IP address as a real request from a victim.
The most important actions that one can perform on a website also tend to be the ones that require one to log in to the website. Banks need to be able to identify a user to know the bank account from which to withdraw. E-commerce sites need a user’s identity so she can be associated with a credit card number, billing address, and shopping cart. Video-sharing sites need to be able to associate unique upvotes with users. Using CSRF, an attacker could force a victim to send the attacker some money, or buy something from them, or upvote their videos.
As an example, my banking website, example.com, does not protect itself against CSRF. You, an unsuspecting example.com user, also happened to be logged in to example.com. Now, malicious user Mallory sends you (and millions of other example.com users, of course) an HTML e-mail including the following tag.
If you have a webmail client that loads images automatically, the transfer request will be made from your browser using your IP address and your example.com session cookies, exactly as if you made the request yourself. My bank website, therefore, treats this like a legitimate request and sends $1000 from your account to Mallory’s account. All evidence suggests you legitimately made this transaction from your logged-in browser.
If all actions on my site are vulnerable to CSRF, this could even lead to further damage. If the attacker can forge a password reset request, or an e-mail change request, the attacker could subsequently gain full control of the victim’s account. If the victim is an administrative user, the entire website would be under the attacker’s control.
There are many ways to protect your website from CSRF, but in this post I will only discuss the most common and most effective solution. It is the solution used by many popular web frameworks, including Ruby on Rails. It’s called the Synchronizer Token Pattern.
For each user session, logged-in or otherwise, the Ruby on Rails server generates a unique token and stores that in the session cookie, which is additionally digitally signed server-side to detect tampering. The server then places this token as a hidden field into every form on every page that it renders. If a user submits the form normally, say, by clicking the “Submit” button, the token will be sent to the server as a form parameter, as well as in the cookie. The server then checks to see that the token in the cookie matches the token in the form parameter. If they don’t match, the request is assumed to be forged, the action is not performed, and the user is forcibly logged out. This only works on POST requests, so it is also up to you to ensure that all of the important actions that can be performed on your site are POST requests.
<img src="https://www.example.com/transfer?amount=1000&destination=mallory" onload="...">
Using an onload handler, the attacker can dynamically create a form and submit it via POST. However, this runs into our main CSRF protection. Because the attacker does not know the secret token that needs to be sent with the request, the request will fail. Unless the website is vulnerable to other kinds of attacks, such as Cross-Site Scripting, the attacker has no way to obtain the secret token, and CSRF is prevented.
As always, if you have any questions about CSRF or other vulnerabilities on your website, feel free to get in touch with us. If you are looking for an automated way to detect CSRF vulnerabilities on your website, check out Tinfoil Security. Tinfoil provides the best web application security solution on the market, and it detects CSRF vulnerabilities on your website along with many other types of web vulnerabilities.