Much attention has been focused in recent months on SQL injection attacks that have compromised the databases of...
major companies. However, this is not the only type of attack that hackers conduct: far from it.
This article will examine another common, but often overlooked attack, cross-site request forgery (CSRF), which exploits a website's assumption that all requests that originate from a user’s browser are in fact those of the user. It is a tactic that has been used in real-world attacks against Facebook, Gmail and the social networking site Digg, just to name a few.
Setting the scene
When you click on a link on a webpage, your browser sends a request to the Web server. Such requests can broadly be categorised into two types: GET and POST. A GET request is simply a request for a page, e.g. the first time you browse to www.google.com. A POST request is sent when you send data to the server, for example if you search for “security” on Google, this would be sent as a POST request.
But what if it were possible to send a request, be it a GET or a POST, from a user’s browser without the user's consent? It’s possible; it’s simple; and it’s called cross-site request forgery.
Objectives of CSRF attacks
Any application that allows a user to send or update data is a potential target for an attacker. The following is a list of potential uses for CSRF:
- Transfer money from one bank account to another.
- Use a content management system to add/delete content from a website.
- Change a user’s password.
- Add items to a user’s shopping basket.
- Change the delivery address of an order.
A CSRF attack example
Does your website allow users to login using their email addresses? Many websites have a “my account” page or other similar page that stores a user's information, and often allows a user to change his or her email address. This email address change could either be made as a POST request or as a GET request. It is possible for an attacker to forge this request once he or she knows the structure of it, and discovering the structure is simple, especially if users can register their own accounts.
In the CSRF attack example below, the data to be changed is contained in a parameter called “EmailAddress”. If the user can be tricked into visiting a website under the attacker’s control, the following code can be used to change the email address stored as a login credential on that site:
The page can be presented as anything: it could be blank, or it could be a replica of the website that’s under attack. All it needs is the code above, which displays an image; this image does not need to exist, and it only covers a 1x1 pixel area, so it does not arouse suspicion. As soon as the user's browser loads the page, the code will automatically submit the request to change the user’s email address. As long as the victim is logged into the website at the time, it will be processed exactly as if the victim had clicked the link.
Even if the website only allows updates via POST, it’s possible to change the email address in the same manner; it just requires some different code:
In both cases, once this is submitted, the email address is automatically changed. Then it’s as simple as using the built-in password-reset facility that most websites have: If this sends the password directly to the registered email address, the password will then be mailed to the attacker and the user account is compromised.
The caveat to mention here is that the user must be logged in to the legitimate website at the time he or she is tricked into visiting the malicious website. However, many sites have a “keep me logged in” facility, which provides a much larger timeframe for the attack.
How to defend against CSRF
There are two main methods for preventing CSRF on your website. The first is to verify the content of the “Referer” header. This is sent by the browser with each request and shows from which page it came. When a CSRF attack is conducted, the request does not contain a Referer header. By rejecting all requests that do not have the correct Referer header, it is possible to stop most CSRF attacks. However, a clever attacker can forge the content of the Referer header, thus circumventing this defence.
A better method is to send a unique identifier with each request, a tactic employed during application development. ASP.NET has an option called ViewState; using this option, along with a unique user "sessionID" added into it, is an effective defence against CSRF. The unique identifier can be sent either in the URL, or as a hidden field. This should be long and randomly generated. As it is impossible for the attacker to know the unique identifier of the victim, it will not be possible to write the HTML code needed to perform the attack. This defence technique is harder to implement, but is a more comprehensive and safer method.
Ideally, both these methods would be combined to defend against a CSRF attack.
CSRF attacks can be used on a wide-range of sites. Any site where data can be altered is a potential target. Implement the fixes detailed above, however, and your website will be much more secure against this attack.
About the author:
Rob Shapland is a penetration tester at First Base Technologies. He can be contacted via email at email@example.com, or on Twitter @rdshapland.