Cross-Site Request Forgery (CSRF)

Last revision (mm/dd/yy): //

Overview
CSRF is an attack which forces an end user to execute unwanted actions on a web application in which he/she is currently authenticated. With a little help of social engineering (like sending a link via email/chat), an attacker may trick the users of a web application into executing actions of the attacker's choosing. A successful CSRF exploit can compromise end user data and operation in case of normal user. If the targeted end user is the administrator account, this can compromise the entire web application.

How to Review Code for CSRF Vulnerabilities
See the OWASP Code Review Guide article on how to Reviewing code for CSRF Vulnerabilities.

How to Test for CSRF Vulnerabilities
See the OWASP Testing Guide article on how to Test for CSRF Vulnerabilities.

How to Prevent CSRF Vulnerabilities
See the OWASP CSRF Prevention Cheat Sheet for prevention measures.

Listen to the OWASP Top Ten CSRF Podcast.

John Melton also has an excellent blog post describing how to use the native anti-CSRF functionality of the OWASP ESAPI.

Description
Cross-Site Request Forgery (CSRF) is an attack that tricks the victim into loading a page that contains a malicious request. It is malicious in the sense that it inherits the identity and privileges of the victim to perform an undesired function on the victim's behalf, like change the victim's e-mail address, home address, or password, or purchase something. CSRF attacks generally target functions that cause a state change on the server but can also be used to access sensitive data.

For most sites, browsers will automatically include with such requests any credentials associated with the site, such as the user's session cookie, basic auth credentials, IP address, Windows domain credentials, etc. Therefore, if the user is currently authenticated to the site, the site will have no way to distinguish this from a legitimate user request.

In this way, the attacker can make the victim perform actions that they didn't intend to, such as logout, purchase item, change account information, retrieve account information, or any other function provided by the vulnerable website.

Sometimes, it is possible to store the CSRF attack on the vulnerable site itself. Such vulnerabilities are called Stored CSRF flaws. This can be accomplished by simply storing an IMG or IFRAME tag in a field that accepts HTML, or by a more complex cross-site scripting attack. If the attack can store a CSRF attack in the site, the severity of the attack is amplified. In particular, the likelihood is increased because the victim is more likely to view the page containing the attack than some random page on the Internet. The likelihood is also increased because the victim is sure to be authenticated to the site already.

Synonyms: CSRF attacks are also known by a number of other names, including XSRF, "Sea Surf", Session Riding, Cross-Site Reference Forgery, Hostile Linking. Microsoft refers to this type of attack as a One-Click attack in their threat modeling process and many places in their online documentation.

Prevention measures that do NOT work

 * Using a secret cookie
 * Remember that all cookies, even the secret ones, will be submitted with every request. All authentication tokens will be submitted regardless of whether or not the end-user was tricked into submitting the request. Furthermore, session identifiers are simply used by the application container to associate the request with a specific session object. The session identifier does not verify that the end-user intended to submit the request.


 * Only accepting POST requests
 * Applications can be developed to only accept POST requests for the execution of business logic. The misconception is that since the attacker cannot construct a malicious link, a CSRF attack cannot be executed. Unfortunately, this logic is incorrect. There are numerous methods in which an attacker can trick a victim into submitting a forged POST request, such as a simple form hosted in attacker's website with hidden values. This form can be triggered automatically by JavaScript or can be triggered by the victim who thinks form will do something else.

How does the attack work?
There are numerous ways in which an end-user can be tricked into loading information from or submitting information to a web application. In order to execute an attack, we must first understand how to generate a malicious request for our victim to execute. Let us consider the following example: Alice wishes to transfer $100 to Bob using bank.com web application that is vulnerable to CSRF. Maria, an attacker, wants to trick Alice to send the money to her instead. The attack will comprise of the following steps:


 * building an exploit URL or script,
 * tricking Alice into executing it with Social Engineering

GET scenario
If the application was designed to primarily use GET requrests to transfer parameters and execute actions, the money transfer operation might be reduced to such request:

GET http://bank.com/transfer.do?acct=BOB&amount=100 HTTP/1.1

Maria now decides to exploit this web application vulnerability using Alice as her victim. Maria first constructs the following exploit URL which will transfer $100,000 from Alice's account to her account. She takes the original command URL and replaces the beneficiary name with herself, raising the transfer amount significantly at the same time:

http://bank.com/transfer.do?acct=MARIA&amount=100000

The Social Engineering part of the attack will be now to trick Alice to load this URL when she's logged into the bank. This is usually done with one of the following techniques:


 * sending an unsolicited email with HTML content
 * planting exploit URL or script on pages that are likely to be visited by the victim.

The exploit URL can be disguised either as ordinary link, encouraging the victim to click it:

View my Pictures!

Or by a 1x1 fake image:



If this image tag were included in the email, Alice would only see a little box indicating that the browser could not render the image. However, the browser will still submit the request to bank.com without any visual indication that the transfer has taken place.

A real life example of CSRF attack on application using GET was uTorrent exploit from 2008 that was used on mass scale to download malware.

POST scenario
The only difference when POST requests are being is how the attack is being executed by the victim. Let's assume the bank now uses POST and the vulnerable request looks like this:

POST http://bank.com/transfer.do HTTP/1.1 acct=BOB&amount=100

Such request cannot be delivered using standard A or IMG tags, but can be delivered using FORM tag:

   

This form will require user clicking the submit button, but this can be also executed automatically using JavaScript:

 <form...

Other HTTP methods
Modern web application APIs are frequently using other HTTP methods such as PUT or DELETE. Let's assume the vulnerable bank uses PUT method that takes JSON block as an argument:

PUT http://bank.com/transfer.do HTTP/1.1 {"acct":"BOB", "amount":100}

Such requests can be executed with JavaScript embedded into an exploit page:

function put { var x = new XMLHttpRequest; x.open("PUT","http://bank.com/transfer.do",true); x.setRequestHeader("Content-Type", "application/json"); x.send(JSON.stringify('{"acct":"BOB", "amount":100}')); } 

Fortunately, this request will be not executed by modern web browsers thanks to Single Origin Policy restrictions. This restriction will be however enabled only if the target web site does not explicitly open up their CORS with the following header:

Access-Control-Allow-Origin: *

Related Attacks

 * Cross-site Scripting (XSS)
 * Cross Site History Manipulation (XSHM)

Related Controls

 * Add a per-request nonce to URL and all forms in addition to the standard session. This is also referred to as "form keys". Many frameworks (ex, Drupal.org 4.7.4+) either have or are starting to include this type of protection "built-in" to every form so the programmer does not need to code this protection manually.
 * TBD: Add a per-session nonce to URL and all forms
 * TBD: Add a hash(session id, function name, server-side secret) to URL and all forms
 * TBD: .NET - add session identifier to ViewState with MAC
 * Checking the referrer in the client's HTTP request will prevent CSRF attacks. By ensuring the HTTP request have come from the original site means that the attacks from other sites will not function.  It is very common to see referrer checks used on embedded network hardware due to memory limitations.  XSS can be used to bypass both referrer and token based checks simultaneously.  For instance the Sammy Worm used an XHR to obtain the CSRF token to forge requests.
 * "Although cross-site request forgery is fundamentally a problem with the web application, not the user, users can help protect their accounts at poorly designed sites by logging off the site before visiting another, or clearing their browser's cookies at the end of each browser session." -http://en.wikipedia.org/wiki/Cross-site_request_forgery#_note-1
 * Tokenizing