Saturday, January 8, 2011

The Cross-Site Request Forgery (CSRF/XSRF) FAQ


This paper serves as a living document for Cross-Site Request Forgery issues. This document will serve as a repository of information from existing papers, talks, and mailing list postings and will be updated as new information is discovered.

What is Cross Site Request Forgery?

Cross Site Request Forgery (also known as XSRF, CSRF, and Cross Site Reference Forgery) works by exploiting the trust that a site has for the user. Site tasks are usually linked to specific urls (Example: http://site/stocks?buy=100&stock=ebay) allowing specific actions to be performed when requested. If a user is logged into the site and an attacker tricks their browser into making a request to one of these task urls, then the task is performed and logged as the logged in user. Typically an attacker will embed malicious HTML or JavaScript code into an email or website to request a specific 'task url' which executes without the users knowledge, either directly or by utilizing a Cross-site Scripting Flaw. Injection via light markup languages such as BBCode is also entirely possible. These sorts of attacks are fairly difficult to detect potentially leaving a user debating with the website/company as to whether or not the stocks bought the day before was initiated by the user after the price plummeted.

Who discovered CSRF?

In the 1988 Norm Hardy published a document explaining an application level trust issue he called a confused deputy. In 2000 a post to bugtraq explained howZOPE was affected by a confused-deputy web problem that we would define today as a CSRF vulnerability. Later in 2001 Peter Watkins posted an entry on the bugtraq mailing list coining the CSRF term in response to another thread titled The Dangers of Allowing Users to Post Images.

What can be done with CSRF?

Most of the functionality allowed by the website can be performed by an attacker utilizing CSRF. This could include posting content to a message board, subscribing to an online newsletter, performing stock trades, using an shopping cart, or even sending an e-card. CSRF can also be used as a vector to exploit existing Cross-site Scripting flaws in a given application. For example imagine an XSS issue on an online forum or blog, where an attacker could force the user through CSRF to post a copy of the next big website worm. An attacker could also utilize CSRF to relay an attack against a site of their choosing, as well as perform a Denial Of Service attack in the right circumstances.

Is CSRF and Cross-site Scripting the same thing?

Cross-Site Scripting exploits the trust that a client has for the website or application. Users generally trust that the content displayed in their browsers was intended to be displayed by the website being viewed. The website assumes that if an 'action request' was performed, that this is what the user wanted and happily performs it. CSRF exploits the trust that a site has for the user.

What are common ways to perform a CSRF attack?

The most popular ways to execute CSRF attacks is by using a HTML image tag, or JavaScript image object. Typically an attacker will embed these into an email or website so when the user loads the page or email, they perform a web request to any URL of the attackers liking.  Below is a list of the common ways that an attacker may try sending a request.
HTML Methods
  <img src="http://host/?command">
  <script src="http://host/?command">
  <iframe src="http://host/?command">
JavaScript Methods
'Image' Object
  var foo = new Image();
  foo.src = "http://host/?command";
'XMLHTTP' Object (See "Can applications using only POST be vulnerable?" for when this can be used)
  var post_data = 'name=value';
  var xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");"POST", 'http://url/path/file.ext', true);
  xmlhttp.onreadystatechange = function () { 
  if (xmlhttp.readyState == 4) 
  var post_data = 'name=value';
  var xmlhttp=new XMLHttpRequest();"POST", 'http://url/path/file.ext', true);
  xmlhttp.onreadystatechange = function () {
  if (xmlhttp.readyState == 4)
Many other ways exist in HTML/VBScript/JavaScript/ActionScript/JScript and other markup languages to make the users browser perform remote requests.

Is this vulnerability limited to browsers?

Absolutely not. An attacker could embed scripting into a word document, Flash File, Movie, RSS or Atom web feed, or other document format allowing scripting. Applications utilizing XML documents use XML parsers to quickly parse through data. Certain tags within an XML document may tell the XML parser to request additional documents from a URI. Browsers will be the dominant way to execute these attacks but aren't the only way.

Can applications using only POST be vulnerable?

Yes. An attacker could craft a web form on site A and using JavaScript auto submit the form to a target location of Site b. If the application containing the CSRF payload uses a browser component that runs in the local zone, then sending remote POST requests to any website is possible using XMLHTTP or similar objects.
There's another way to attack a website using purely POST based parameters, however this depends entirely on how the web application was developed. Popular web based libraries such as Perl's CGI.PM module allow a developer to fetch a parameter without caring if it came in through a GET or POST request. As is the case with certain usages of CGI.PM, POST requests can be converted to GET by the attacker and the application action will still be performed. Below is an example.

Perl's CGI.PM 
use CGI qw(:all);
$value = param('foo');
print "Content-type: text/html\n\n";
print "The 'foo' parameter value is $value\n\n\n";
This script allows either a GET or POST request to be sent the application. This is not limited to Perl and can affect any language depending on the library they are using, or way the application was developed. If you are using and want to prevent GET requests one way is to perform a request method check before executing the rest of your code using '$ENV{'REQUEST_METHOD'}'. Below are the most common ways to fetch a parameter by language, that allow for either GET or POST requests to be sent.
JSP Example
Commonly Used: request.getParameter("foo")
  Solution: Check the HTTP Request method and see if it is using POST before performing the requested action.
PHP Example
Commonly Used: $_REQUEST['foo']
   Solution: Use $_POST['foo'] instead to specify POST Only.
ASP.NET Example
Commonly Used: Request.Params["foo"];
   Solution: Use HTTPRequest.Form (Request.Form) which grabs POST only.
Converting actions to POST only is not a solution to CSRF, but should be implemented as a best practice. See "What can I do to protect my own applications?" for a more comprehensive solution.

How do I detect if a website is vulnerable?

If your website allows performing a site function using a static URL or POST request (i.e. one that doesn't change) then it is possible. If this command is performed through GET then it is a much higher risk. If the site is purely POST see "Can applications using only POST be vulnerable?" for use cases. A quick test would involve browsing the website through a proxy such as Paros and record the requests made. At a later time perform the same action and see if the requests are performed in an identical manner (your cookie will probably change). If you are able to perform the same function using the GET or POST request repeatedly then the site application may be vulnerable.

Can CSRF be prevented by implementing referrer checking?

No for two reasons.
First there are many ways that a Referer header can be blanked out or modified such as via web filtering software, parental control software, privacy software, proxies, or DOM trickery. This makes the referer header unreliable by nature.
Second Referer headers can be spoofed using XMLHTTP and by using flash as demonstrated by Amit Klein and rapid7. While these particular methods have been patched by the vendors, not every user visiting your website has applied these patches. Even if they did the first issue would still exist.

Has a vulnerability in a major site been discovered?

vulnerability in GMail was discovered in January 2007 which allowed a attacker to steal a GMail user's contact list. A different issue was discovered in Netflixwhich allowed an attacker to change the name and address on the account, as well as add movies to the rental queue etc...

What can I do to protect myself as a user?

Nothing. The fact is as long as you visit websites and don't have control of the inner architecture of these applications you can't do a thing.  The truth hurts doesn't it?   

What can I do to protect my own applications?

The most popular suggestion to preventing CSRF involves appending non predictable challenge tokens to each request. It is important to state that this challenge token MUST be associated with the user session, otherwise an attacker may be able to fetch a valid token on their own and utilize it in an attack. In addition to being tied to the user session it is important to limit the time period to which a token is valid. This method is documented in multiple documentshowever as pointed out in mailing list postings an attacker can utilize an existing browser vulnerability or XSS flaw to grab this session token.

By Robert Auger

References and Additional Reading

Wikipedia Confused Deputy Entry
Sending arbitrary HTTP requests with Flash 7/8 (+IE 6.0)
HTTP Header Injection Vulnerabilities in the Flash Player Plugin
Client-side Trojans  (or "Browsial Engineering"?)
Gmail Vulnerable to CSRF
First CSRF Post to Bugtraq
Wikipedia XMLHTTP Entry
Adobe Reader XML External Entity Attack
MSDN HttpRequest.Form Property
PHP Predefined Variables List
Myspace CSRF and XSS Worm (Samy)
Cross Site Reference Forgery, 2005
RFC 2616, "Hypertext Transfer Protocol -- HTTP/1.1"

No comments:

Post a Comment