This site is the archived OWASP Foundation Wiki and is no longer accepting Account Requests.
To view the new OWASP Foundation website, please visit https://owasp.org

Difference between revisions of "Cross-Site Request Forgery (CSRF) Prevention Cheat Sheet"

From OWASP
Jump to: navigation, search
(Protecting REST Services: Use of Custom Request Headers)
m (Point to the official site)
 
(77 intermediate revisions by 9 users not shown)
Line 2: Line 2:
 
<div style="width:100%;height:160px;border:0,margin:0;overflow: hidden;">[[File:Cheatsheets-header.jpg|link=]]</div>
 
<div style="width:100%;height:160px;border:0,margin:0;overflow: hidden;">[[File:Cheatsheets-header.jpg|link=]]</div>
  
{| style="padding: 0;margin:0;margin-top:10px;text-align:left;" |-
+
The Cheat Sheet Series project has been moved to [https://github.com/OWASP/CheatSheetSeries GitHub]!
| valign="top"  style="border-right: 1px dotted gray;padding-right:25px;" |
 
Last revision (mm/dd/yy): '''{{REVISIONMONTH}}/{{REVISIONDAY}}/{{REVISIONYEAR}}'''
 
= Introduction  =
 
__TOC__{{TOC hidden}}
 
  
[[Cross-Site Request Forgery (CSRF)]] is a type of attack that occurs when a malicious web site, email, blog, instant message, or program causes a user’s web browser to perform an unwanted action on a trusted site for which the user is currently authenticated. The impact of a successful CSRF attack is limited to the capabilities exposed by the vulnerable application. For example, this attack could result in a transfer of funds, changing a password, or purchasing an item in the user's context. In effect, CSRF attacks are used by an attacker to make a target system perform a function via the target's browser without knowledge of the target user, at least until the unauthorized transaction has been committed.
+
Please visit [https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html Cross-Site Request Forgery (CSRF) Prevention Cheat Sheet] to see the latest version of the cheat sheet.
 
 
Impacts of successful CSRF exploits vary greatly based on the role of the victim. When targeting a normal user, a successful CSRF attack can compromise end-user data and their associated functions. If the targeted end user is an administrator account, a CSRF attack can compromise the entire web application. The sites that are more likely to be attacked are community websites (social networking, email) or sites that have high dollar value accounts associated with them (banks, stock brokerages, bill pay services). This attack can happen even if the user is logged into a web site using strong encryption (HTTPS). Utilizing social engineering, an attacker will embed malicious HTML or JavaScript code into an email or website to request a specific 'task URL'. The task then executes with or without the user's knowledge, either directly or by utilizing a Cross-Site Scripting flaw (ex: Samy MySpace Worm).
 
 
 
For more information on CSRF, please see the OWASP [[Cross-Site Request Forgery (CSRF)]] page.
 
 
 
== Warning: No Cross-Site Scripting (XSS) Vulnerabilities ==
 
 
 
[[Cross-Site Scripting]] is not necessary for CSRF to work. However, any cross-site scripting vulnerability can be used to defeat token, Double-Submit cookie, referer and origin based CSRF defenses.  This is because an XSS payload can simply read any page on the site using a XMLHttpRequest and obtain the generated token from the response, and include that token with a forged request. This technique is exactly how the [http://en.wikipedia.org/wiki/Samy_(XSS) MySpace (Samy) worm] defeated MySpace's anti-CSRF defenses in 2005, which enabled the worm to propagate. XSS cannot defeat challenge-response defenses such as Captcha, re-authentication or one-time passwords. It is imperative that no XSS vulnerabilities are present to ensure that CSRF defenses can't be circumvented. Please see the OWASP [[XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet | XSS Prevention Cheat Sheet]] for detailed guidance on how to prevent XSS flaws.
 
 
 
= General Recommendation For Automated CSRF Defense =
 
 
 
We recommend two separate checks as your standard CSRF defense that does not require user intervention. This discussion ignores for the moment deliberately allowed cross origin requests (e.g., CORS). Your defenses will have to adjust for that if that is allowed.
 
 
 
# Check standard headers to verify the request is same origin
 
# AND Check CSRF token
 
 
 
Each of these is discussed next.
 
 
 
== Standard Header Checks ==
 
 
 
Almost all requests include one or both of:
 
 
 
* Origin Header
 
* Referer Header
 
 
 
Although it is trivial to spoof any header from your own browser, it is generally impossible to do so in a CSRF attack, except via an XSS vulnerability. That's why checking headers is a reasonable first step in your CSRF defense, but since they aren't always present, its generally not considered a sufficient defense on its own.
 
 
 
=== Checking The Origin Header ===
 
If the Origin header is present, verify its value matches the site's origin. The [https://wiki.mozilla.org/Security/Origin Origin HTTP Header] standard was introduced as a method of defending against CSRF and other Cross-Domain attacks. Unlike the referer, the origin header will be present in HTTP requests that originate from an HTTPS URL. If the origin header is present, then it should be checked to make sure it match's your site's origin.
 
 
 
This defense technique is specifically proposed in section 5.0 of [https://seclab.stanford.edu/websec/csrf/csrf.pdf Robust Defenses for Cross-Site Request Forgery]. This paper proposes the creation of the Origin header and its use as a CSRF defense mechanism.
 
 
 
=== Checking The Referer Header ===
 
If the Origin header is not present, verify the hostname in the Referer header matches the site's origin. Checking the referer is a commonly used method of preventing CSRF on embedded network devices because it does not require a per-user state.  This makes a referer a useful method of CSRF prevention when memory is scarce or server-side state doesn't exist.  This method of CSRF mitigation is also commonly used with unauthenticated requests, such as requests made prior to establishing a session state which is required to keep track of a synchronization token.
 
 
 
In both cases, just make sure your origin check is strong. For example, if your site is "site.com" make sure "site.com.attacker.com" doesn't pass your origin check.
 
 
 
If neither of these headers is present, which should be VERY rare, you can either accept or block the request. That's up to you. You might want to accept but log this situation for a while and if you basically never see it, start blocking such requests.
 
 
 
== CSRF Specific Defense ==
 
 
 
There are numerous ways you can specifically defend against CSRF. We recommend using one of the following:
 
 
 
1. Synchronizer (i.e.,CSRF) Tokens (requires session state)
 
 
 
Approaches that do require no server side state:
 
 
 
2. Double Cookie Defense<br />
 
3. Encrypted Token Pattern<br />
 
4. Custom Header - e.g., X-Requested-With: XMLHttpRequest
 
 
 
These are listed in order of strength of defense. So use the strongest defense that makes sense in your situation.
 
 
 
=== Synchronizer (CSRF) Tokens ===
 
 
 
* Any state changing operation requires a secure random token (e.g., CSRF token) to prevent CSRF attacks
 
* Characteristics of a CSRF Token
 
** Unique per user session
 
** Large random value
 
** Generated by a cryptographically secure random number generator
 
* The CSRF token is added as a hidden field for forms or within the URL if the state changing operation occurs via a GET
 
* The server rejects the requested action if the CSRF token fails validation
 
 
 
In order to facilitate a "transparent but visible" CSRF solution, developers are encouraged to adopt the Synchronizer Token Pattern (http://www.corej2eepatterns.com/Design/PresoDesign.htm). The synchronizer token pattern requires the generating of random "challenge" tokens that are associated with the user's current session. These challenge tokens are then inserted within the HTML forms and links associated with sensitive server-side operations. When the user wishes to invoke these sensitive operations, the HTTP request should include this challenge token. It is then the responsibility of the server application to verify the existence and correctness of this token. By including a challenge token with each request, the developer has a strong control to verify that the user actually intended to submit the desired requests. Inclusion of a required security token in HTTP requests associated with sensitive business functions helps mitigate CSRF attacks as successful exploitation assumes the attacker knows the randomly generated token for the target victim's session. This is analogous to the attacker being able to guess the target victim's session identifier. The following synopsis describes a general approach to incorporate challenge tokens within the request.
 
 
 
When a Web application formulates a request (by generating a link or form that causes a request when submitted or clicked by the user), the application should include a hidden input parameter with a common name such as "CSRFToken". The value of this token must be randomly generated such that it cannot be guessed by an attacker. Consider leveraging the java.security.SecureRandom class for Java applications to generate a sufficiently long random token. Alternative generation algorithms include the use of 256-bit BASE64 encoded hashes. Developers that choose this generation algorithm must make sure that there is randomness and uniqueness utilized in the data that is hashed to generate the random token.
 
 
 
  <form action="/transfer.do" method="post">
 
  <input type="hidden" name="CSRFToken"
 
  value="OWY4NmQwODE4ODRjN2Q2NTlhMmZlYWE...
 
  wYzU1YWQwMTVhM2JmNGYxYjJiMGI4MjJjZDE1ZDZ...
 
  MGYwMGEwOA==">
 
  …
 
  </form>
 
 
 
In general, developers need only generate this token once for the current session. After initial generation of this token, the value is stored in the session and is utilized for each subsequent request until the session expires. When a request is issued by the end-user, the server-side component must verify the existence and validity of the token in the request as compared to the token found in the session. If the token was not found within the request or the value provided does not match the value within the session, then the request should be aborted, token should be reset and the event logged as a potential CSRF attack in progress.
 
 
 
To further enhance the security of this proposed design, consider randomizing the CSRF token parameter name and/or value for each request. Implementing this approach results in the generation of per-request tokens as opposed to per-session tokens. Note, however, that this may result in usability concerns. For example, the "Back" button browser capability is often hindered as the previous page may contain a token that is no longer valid. Interaction with this previous page will result in a CSRF false positive security event at the server. Regardless of the approach taken, developers are encouraged to protect the CSRF token the same way they protect authenticated session identifiers, such as the use of TLS.
 
 
 
==== Existing Synchronizer Implementations ====
 
 
 
Synchronizer Token defenses have been built into many frameworks so we strongly recommend using them first when they are available. External components that add CSRF defenses to existing applications also exist and are recommended. OWASP has two:
 
 
 
# For Java: OWASP [[CSRF Guard]]
 
# For PHP and Apache: [[CSRFProtector Project]]
 
 
 
==== Disclosure of Token in URL ====
 
 
 
Many implementations of synchronizer tokens include the challenge token in GET (URL) requests as well as POST requests. This is often implemented as a result of sensitive server-side operations being invoked as a result of embedded links in the page or other general design patterns. These patterns are often implemented without knowledge of CSRF and an understanding of CSRF prevention design strategies. While this control does help mitigate the risk of CSRF attacks, the unique per-session token is being exposed for GET requests. CSRF tokens in GET requests are potentially leaked at several locations: browser history, HTTP log files, network appliances that make a point to log the first line of an HTTP request, and Referer headers if the protected site links to an external site.
 
 
 
In the latter case (leaked CSRF token due to the Referer header being parsed by a linked site), it is trivially easy for the linked site to launch a CSRF attack on the protected site, and they will be able to target this attack very effectively, since the Referer header tells them the site as well as the CSRF token. The attack could be run entirely from JavaScript, so that a simple addition of a script tag to the HTML of a site can launch an attack (whether on an originally malicious site or on a hacked site). Additionally, since HTTPS requests from HTTPS contexts will not strip the Referer header (as opposed to HTTPS to HTTP requests) CSRF token leaks via Referer can still happen on HTTPS Applications.
 
 
 
The ideal solution is to only include the CSRF token in POST requests and modify server-side actions that have state changing affect to only respond to POST requests. This is in fact what the [http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.1.1 RFC 2616] requires for GET requests. If sensitive server-side actions are guaranteed to only ever respond to POST requests, then there is no need to include the token in GET requests.
 
 
 
In most JavaEE web applications, however, HTTP method scoping is rarely ever utilized when retrieving HTTP parameters from a request. Calls to "HttpServletRequest.getParameter" will return a parameter value regardless if it was a GET or POST. This is not to say HTTP method scoping cannot be enforced. It can be achieved if a developer explicitly overrides doPost() in the HttpServlet class or leverages framework specific capabilities such as the AbstractFormController class in Spring.
 
 
 
For these cases, attempting to retrofit this pattern in existing applications requires significant development time and cost, and as a temporary measure it may be better to pass CSRF tokens in the URL. Once the application has been fixed to respond to HTTP GET and POST verbs correctly, CSRF tokens for GET requests should be turned off.
 
 
 
==== Viewstate (ASP.NET) ====
 
 
 
ASP.NET has an option to maintain your ViewState. The ViewState indicates the status of a page when submitted to the server. The status is defined through a hidden field placed on each page with a <form runat="server"> control. Viewstate can be used as a CSRF defense, as it is difficult for an attacker to forge a valid Viewstate. It is not impossible to forge a valid Viewstate since it is feasible that parameter values could be obtained or guessed by the attacker. However, if the current session ID is added to the ViewState, it then makes each Viewstate unique, and thus immune to CSRF.
 
 
 
To use the ViewStateUserKey property within the Viewstate to protect against spoofed post backs. Add the following in the OnInit virtual method of the Page-derived class (This property must be set in the Page.Init event)
 
 
 
  protected override OnInit(EventArgs e) {
 
      base.OnInit(e);
 
      if (User.Identity.IsAuthenticated)
 
        ViewStateUserKey = Session.SessionID; }
 
 
 
The following keys the Viewstate to an individual using a unique value of your choice.
 
 
 
    (Page.ViewStateUserKey)
 
 
 
This must be applied in Page_Init because the key has to be provided to ASP.NET before Viewstate is loaded. This option has been available since ASP.NET 1.1.
 
 
 
However, there are limitations on this mechanism.  Such as, ViewState MACs are only checked on POSTback, so any other application requests not using postbacks will happily allow CSRF.
 
 
 
=== Double Submit Cookie ===
 
 
 
If storing the CSRF token in session is problematic, an alternative defense is use of a double submit cookie. A double submit cookie is defined as sending a random value in both a cookie and as a request parameter, with the server verifying if the cookie value and request value match.
 
 
 
When a user authenticates to a site, the site should generate a (cryptographically strong) pseudorandom value and set it as a cookie on the user's machine separate from the session id. The site does not have to save this value in any way, thus avoiding server side state. The site then requires that every transaction request include this random value as a hidden form value (or other request parameter). A cross origin attacker cannot read any data sent from the server or modify cookie values, per the same-origin policy. This means that while an attacker can force a victim to send any value he wants with a malicious CSRF request, the attacker will be unable to modify or read the value stored in the cookie. Since the cookie value and the request parameter or form value must be the same, the attacker will be unable to successfully force the submission of a request with the random CSRF value.
 
 
 
As an example, the [http://directwebremoting.org Direct Web Remoting (DWR)] Java library version 2.0 has CSRF protection built in that implements the double cookie submission transparently.
 
 
 
=== Encrypted Token Pattern ===
 
 
 
The Encrypted Token Pattern leverages an encryption, rather than comparison, method of Token-validation. After successful authentication, the server generates a unique Token comprised of the user's ID, a timestamp value and a [http://en.wikipedia.org/wiki/Cryptographic_nonce nonce], using a unique key available only on the server. This Token is returned to the client and embedded in a hidden field. Subsequent AJAX requests include this Token in the request-header, in a similar manner to the Double-Submit pattern. Non-AJAX form-based requests will implicitly persist the Token in its hidden field. On receipt of this request, the server reads and decrypts the Token value with the same key used to create the Token. Inability to correctly decrypt suggest an intrusion attempt. Once decrypted, the UserId and timestamp contained within the token are validated to ensure validity; the UserId is compared against the currently logged in user, and the timestamp is compared against the current time.
 
 
 
On successful Token-decryption, the server has access to parsed values, ideally in the form of [http://en.wikipedia.org/wiki/Claims-based_identity claims]. These claims are processed by comparing the UserId claim to any potentially stored UserId (in a Cookie or Session variable, if the site already contains a means of authentication). The Timestamp is validated against the current time, preventing replay attacks.
 
Alternatively, in the case of a CSRF attack, the server will be unable to decrypt the poisoned Token, and can block and log the attack.
 
 
 
This pattern exists primarily to allow developers and architects protect against CSRF without session-dependency. It also addresses some of the shortfalls in other stateless approaches, such as the need to store data in a Cookie, circumnavigating the Cookie-subdomain and HTTPONLY issues.
 
 
 
=== Protecting REST Services: Use of Custom Request Headers ===
 
 
 
Adding CSRF tokens, a double submit cookie and value, encrypted token, or other defense that involves changing the UI can frequently be complex or otherwise problematic. An alternate defense which is particularly well suited for AJAX endpoints is the use of a custom request header. This defense relies on the [https://en.wikipedia.org/wiki/Same-origin_policy same-origin policy (SOP)] restriction that only JavaScript can be used to add a custom header, and only within its origin. By default, browsers don't allow JavaScript to make cross origin requests.
 
 
 
A particularly attractive custom header and value to use is:
 
* X-Requested-With: XMLHttpRequest
 
because most JavaScript libraries already add this header to requests they generate.
 
 
 
If this is the case for your system, you can simply verify the presence of this header and value on all your server side AJAX endpoints in order to protect against CSRF attacks. This approach has the double advantage of usually requiring no UI changes and not introducing any server side state, which is particularly attractive to REST services. You can always add your own custom header and value if that is preferred.
 
 
 
This defense technique is specifically discussed in section 4.3 of [https://seclab.stanford.edu/websec/csrf/csrf.pdf Robust Defenses for Cross-Site Request Forgery].
 
 
 
= Alternate CSRF Defense: Require User Interaction =
 
 
 
Sometimes its easier or more appropriate to involve the user in the transaction in order to prevent unauthorized transactions (forged or otherwise).
 
 
 
The following are some examples of challenge-response options:
 
 
 
*Re-Authentication (password or stronger)
 
*One-time Token
 
*CAPTCHA
 
 
 
While challenge-response is a very strong defense against CSRF (assuming proper implementation), it does impact user experience. For applications in need of high security, tokens (transparent) and challenge-response should be used on high risk functions.
 
 
 
An example of a transparent use of security tokens that doesn't impact the user experience is the use of transaction IDs. Imagine a user wants to initiate a transaction, like send money via PayPal.
 
 
 
* In Step 1: the user provides the email address and the amount of money they want to send.
 
** The server responds with a confirmation dialog that includes a unique transaction ID for this money transfer.
 
* In Step 2: the user confirms the proposed transaction.
 
** The confirmation request includes the transaction ID generated in step 1. If the server verifies the transaction ID as part of this step, this prevents CSRF against this transaction flow without using a CSRF specific defense token. The transaction ID as part of the confirm essentially serves as the CSRF defense if the attacker cannot predict this value, The transaction ID 'should' be random/unguessable. Ideally, not just the next transaction number in a growing by one list of transaction IDs.
 
 
 
This is just one example of site's behavior that might naturally protect certain state changing events against CSRF attacks.
 
 
 
= Prevention Measures That Do NOT Work =
 
 
 
A number of flawed ideas for defending against CSRF attacks have been developed over time. Here are a few that we recommend you avoid.
 
 
 
== 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 an attacker's Website with hidden values. This form can be triggered automatically by JavaScript or can be triggered by the victim who thinks the form will do something else.
 
 
 
== Multi-Step Transactions ==
 
 
 
Multi-Step transactions are not an adequate prevention of CSRF. As long as an attacker can predict or deduce each step of the completed transaction, then CSRF is possible.
 
 
 
== URL Rewriting ==
 
 
 
This might be seen as a useful CSRF prevention technique as the attacker cannot guess the victim's session ID. However, the user’s session ID is exposed in the URL. We don't recommend fixing one security flaw by introducing another.
 
 
 
= Personal Safety CSRF Tips for Users =
 
 
 
Since CSRF vulnerabilities are reportedly widespread, it is recommended to follow the following best practices to mitigate risk. These include:
 
 
 
* Logoff immediately after using a Web application
 
* Do not allow your browser to save username/passwords, and do not allow sites to “remember” your login
 
* Do not use the same browser to access sensitive applications and to surf the Internet freely (tabbed browsing).
 
* The use of plugins such as No-Script makes POST based CSRF vulnerabilities difficult to exploit.  This is because JavaScript is used to automatically submit the form when the exploit is loaded. Without JavaScript the attacker would have to trick the user into submitting the form manually.
 
 
 
Integrated HTML-enabled mail/browser and newsreader/browser environments pose additional risks since simply viewing a mail message or a news message might lead to the execution of an attack.
 
 
 
= Authors and Primary Editors  =
 
 
 
Dave Wichers - dave.wichers[at]owasp.org<br/>
 
Paul Petefish - https://www.linkedin.com/in/paulpetefish<br/>
 
Eric Sheridan - eric.sheridan[at]owasp.org<br/>
 
 
 
== Other Cheatsheets ==
 
 
 
{{Cheatsheet_Navigation_Body}}
 
 
 
|}
 
 
 
[[Category:Cheatsheets]][[Category:Popular]]
 

Latest revision as of 14:02, 15 July 2019

Cheatsheets-header.jpg

The Cheat Sheet Series project has been moved to GitHub!

Please visit Cross-Site Request Forgery (CSRF) Prevention Cheat Sheet to see the latest version of the cheat sheet.