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 "Anti CSRF Tokens ASP.NET"

From OWASP
Jump to: navigation, search
(ViewState + Token)
(Promoted to production)
 
(7 intermediate revisions by one other user not shown)
Line 1: Line 1:
= DRAFT DOCUMENT - WORK IN PROGRESS =
+
=Description=
 
 
==Description==
 
  
 
In short, CSRF abuses the '''trust''' relationship between '''browser and server'''. This means that anything that a server uses in order to establish trust with a browser (e.g., cookies, but also HTTP/Windows Authentication) is exactly what allows CSRF to take place - but this only the first piece for a successful CSRF attack.
 
In short, CSRF abuses the '''trust''' relationship between '''browser and server'''. This means that anything that a server uses in order to establish trust with a browser (e.g., cookies, but also HTTP/Windows Authentication) is exactly what allows CSRF to take place - but this only the first piece for a successful CSRF attack.
Line 9: Line 7:
 
In order to prevent CSRF in ASP.NET, anti-forgery tokens (also known as request verification tokens) must be utilized.
 
In order to prevent CSRF in ASP.NET, anti-forgery tokens (also known as request verification tokens) must be utilized.
  
These tokens are simply randomly-generated values included in any form/request that warrants protection. Note that, ideally, this value should be unique for every actual form/request, not just for every type of form/request. This guarantees that every form/request is unique and, therefore, protected from CSRF.
+
These tokens are simply randomly-generated values included in any form/request that warrants protection. Note that this value should be unique for every individual session. This guarantees that every form/request is tied to the authenticated user and, therefore, protected from CSRF.
  
 +
'''Important''': non-[https://www.wordnik.com/words/idempotent idempotent] GET requests represent an anti-pattern where CSRF protection is concerned. Always use POST requests with anti-CSRF tokens for proper protection.
  
==Mitigation Examples==
+
 
 +
=Mitigation Examples=
  
 
Please note that the following examples may not entail a complete anti-CSRF solution for any given Web application. Specific requirements may call for adjustments and/or combinations of different strategies.
 
Please note that the following examples may not entail a complete anti-CSRF solution for any given Web application. Specific requirements may call for adjustments and/or combinations of different strategies.
  
===Solutions NOT considered secure===
+
==Solutions NOT considered secure==
 +
 
 +
- All of the solutions provided in this article are not designed to work with GET requests that change the server state (e.g., /example/delete.aspx?id=1). GET requests should be [https://www.wordnik.com/words/idempotent idempotent] so that CSRF cannot take place.
  
 
- Assuming that SSL/TLS will thwart CSRF attacks just because the cookie is marked "Secure" and/or "HTTPOnly". The problem lies in the trust between legitimate browser and server. Therefore, the browser will just send its current cookies when the forged request is triggered. The attacker never has to touch any cookies.
 
- Assuming that SSL/TLS will thwart CSRF attacks just because the cookie is marked "Secure" and/or "HTTPOnly". The problem lies in the trust between legitimate browser and server. Therefore, the browser will just send its current cookies when the forged request is triggered. The attacker never has to touch any cookies.
Line 26: Line 28:
 
- Any CSRF protection is null and void given the presence of XSS, for several reasons. The main and obvious reason is that, through XSS, the attacker can hijack the session and spoof the user, not even having to worry about performing CSRF.
 
- Any CSRF protection is null and void given the presence of XSS, for several reasons. The main and obvious reason is that, through XSS, the attacker can hijack the session and spoof the user, not even having to worry about performing CSRF.
  
===Anti-CSRF Token===
+
==ASP.NET MVC and Web API: Anti-CSRF Token==
  
 
ASP.NET has the capability to generate anti-CSRF security tokens for consumption by your application, as such:
 
ASP.NET has the capability to generate anti-CSRF security tokens for consumption by your application, as such:
Line 39: Line 41:
  
 
For implementation details, see:<br>
 
For implementation details, see:<br>
[http://www.asp.net/mvc/overview/security/xsrfcsrf-prevention-in-aspnet-mvc-and-web-pages CSRF Prevention (official ASP.NET blog)]<br>
+
[http://www.asp.net/mvc/overview/security/xsrfcsrf-prevention-in-aspnet-mvc-and-web-pages MVC CSRF Prevention (official ASP.NET blog)]<br>
[http://www.asp.net/web-api/overview/security/preventing-cross-site-request-forgery-%28csrf%29-attacks Preventing CSRF Attacks (official ASP.NET blog)]<br>
+
[http://www.asp.net/web-api/overview/security/preventing-cross-site-request-forgery-%28csrf%29-attacks Web API CSRF Prevention (official ASP.NET blog)]<br>
  
You may consider making a new security token for every new request, rather than session:<br>
+
The standard frequency of token generation is '''per-session''', so make sure your sessions have a reasonable/configurable '''time-out'''.
 +
It is possible to issue new tokens on a per-request basis. However, the added protection may be insignificant, if this approach even fits your application. See the link below for a discussion on the matter:<br>
 
[http://security.stackexchange.com/questions/22903/why-refresh-csrf-token-per-form-request Why refresh CSRF token per form request?]<br>
 
[http://security.stackexchange.com/questions/22903/why-refresh-csrf-token-per-form-request Why refresh CSRF token per form request?]<br>
  
===ViewState===
+
==WebForms: ViewState==
  
 
'''Requirement:'''<br>
 
'''Requirement:'''<br>
 
[https://msdn.microsoft.com/en-us/library/ms972969.aspx#securitybarriers_topic5 EnableViewStateMac] must be set.<br>
 
[https://msdn.microsoft.com/en-us/library/ms972969.aspx#securitybarriers_topic5 EnableViewStateMac] must be set.<br>
 +
In fact, the ViewState MAC can no longer be disabled for versions since September 2014.
  
The ASP.NET ViewState contains a property, [https://msdn.microsoft.com/en-us/library/ms972969.aspx#securitybarriers_topic2 ViewStateUserKey], which can offer protection against CSRF.
+
The ASP.NET ViewState contains a property, [https://msdn.microsoft.com/en-us/library/ms972969.aspx#securitybarriers_topic2 ViewStateUserKey], which offers protection against CSRF by adding uniqueness to the ViewState MAC as long as you set it to a new value for every session.
  
When enabling CSRF protection through the ViewState, the aim is to make the ViewState always unique per user session, serving as a kind of CSRF token. That's where MAC and the ViewStateUserKey come together.
+
Note that ViewStateUserKey will not actually add a new value to the ViewState, but rather simply influence the MAC process so as to make every MAC unique per user session. Therefore, setting ViewStateUserKey to the current Session ID is acceptable.
  
EnableViewStateMac, when off, obviously performs no checks. When enabled, it will only perform tampering checks. Therefore, an attacker could obtain a valid (but unchanging) ViewState and still perform CSRF.
+
Since Visual Studio 2012, the anti-CSRF mechanism has been improved.
  
The ViewStateUserKey can add uniqueness to the equation if you set it to a new value for every session.
+
The new strategy still uses the ViewState as the main entity for CSRF protection but also makes use of tokens (which you can generate as GUIDs) so that you can set the ViewStateUserKey to the token rather than the Session ID, and then validate it against the cookie.
  
Setting ViewStateUserKey to the current Session ID is acceptable (again, when EnableViewStateMac is on).
+
Here's a [http://software-security.sans.org/developer-how-to/developer-guide-csrf blog post by Eric Johnson and James Jardine] with an example of this implementation.
  
For implementation details, see:<br>
+
For more implementation details, see:<br>
 
[http://msdn.microsoft.com/en-us/library/ms178199%28v=vs.85%29.aspx MSDN - Securing ViewState]<br>
 
[http://msdn.microsoft.com/en-us/library/ms178199%28v=vs.85%29.aspx MSDN - Securing ViewState]<br>
 
[http://msdn.microsoft.com/en-us/library/ms972969.aspx#securitybarriers_topic2 MSDN - ViewStateUserKey]<br>
 
[http://msdn.microsoft.com/en-us/library/ms972969.aspx#securitybarriers_topic2 MSDN - ViewStateUserKey]<br>
  
For an extra secure approach when using ViewState, see the section below.
+
==Considerations for AJAX==
 
 
===ViewState + Token===
 
 
 
The Token approach and the ViewState approach are not mutually exclusive.
 
 
 
This hybrid strategy still uses the ViewState as the main entity for CSRF protection. Keep in mind, however, that you're not constrained to setting [http://msdn.microsoft.com/en-us/library/ms972969.aspx#securitybarriers_topic2 ViewStateUserKey] to the current Session ID.
 
  
By generating and validating tokens with [http://msdn.microsoft.com/en-us/library/dd470175%28v=vs.100%29.aspx HtmlHelper.AntiForgeryToken] and [http://msdn.microsoft.com/en-us/library/system.web.mvc.validateantiforgerytokenattribute%28v=vs.100%29.aspx ValidateAntiForgeryTokenAttribute] (see [http://www.asp.net/mvc/overview/security/xsrfcsrf-prevention-in-aspnet-mvc-and-web-pages CSRF Prevention]), you can set the ViewStateUserKey to the token rather than the Session ID.
+
Depending on your application, you'll likely have to choose between using HTTP Headers or POST data to carry your anti-CSRF tokens.
  
This gives you the flexibility to choose whether to refresh tokens per request or per session while adding additional defensive layers to your strategy.
+
Whatever you choose, the optimal validation method is indeed through tokens.
 +
This means you can follow the token strategy while creating either a '''custom''' header to hold the token value or just sending the token with the rest of the POST data.
  
===AJAX===
+
For more guidance, see the '''answers''' given to the following questions:<br>
 +
[http://stackoverflow.com/questions/8253396/anti-csrf-cookie Anti-CSRF Cookie]<br>
 +
[http://security.stackexchange.com/questions/23371/csrf-protection-with-custom-headers-and-without-validating-token CSRF Protection With Custom Headers]<br>
  
==Related [[Attacks]]==
+
=Related [[Attacks]]=
  
 
[https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF) CSRF (Attack)]<br>
 
[https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF) CSRF (Attack)]<br>
Line 85: Line 86:
  
  
==Related [[Vulnerabilities]]==
+
=Related [[Vulnerabilities]]=
  
 
[https://www.owasp.org/index.php/Cross_Site_Scripting_Flaw XSS]<br>
 
[https://www.owasp.org/index.php/Cross_Site_Scripting_Flaw XSS]<br>
Line 93: Line 94:
  
  
==Related [[Controls]]==
+
=Related [[Controls]]=
 
[https://www.owasp.org/index.php/.Net_CSRF_Guard .NET CSRF Guard]
 
[https://www.owasp.org/index.php/.Net_CSRF_Guard .NET CSRF Guard]
  
  
==Related [[Technical Impacts]]==
+
=Related [[Technical Impacts]]=
 
[https://www.owasp.org/index.php/Loss_of_accountability Accountability]<br>
 
[https://www.owasp.org/index.php/Loss_of_accountability Accountability]<br>
 
[https://www.owasp.org/index.php/Loss_of_confidentiality Confidentiality]
 
[https://www.owasp.org/index.php/Loss_of_confidentiality Confidentiality]
  
  
==References==
+
=References=
 
[http://security.stackexchange.com/questions/22903/why-refresh-csrf-token-per-form-request Why refresh CSRF token per form request?]<br>
 
[http://security.stackexchange.com/questions/22903/why-refresh-csrf-token-per-form-request Why refresh CSRF token per form request?]<br>
 
[http://www.asp.net/mvc/overview/security/xsrfcsrf-prevention-in-aspnet-mvc-and-web-pages CSRF Prevention (official ASP.NET blog)]<br>
 
[http://www.asp.net/mvc/overview/security/xsrfcsrf-prevention-in-aspnet-mvc-and-web-pages CSRF Prevention (official ASP.NET blog)]<br>
Line 110: Line 111:
 
[http://security.stackexchange.com/questions/19152/how-does-viewstate-protect-against-csrf How does ViewState protect against CSRF?]<br>
 
[http://security.stackexchange.com/questions/19152/how-does-viewstate-protect-against-csrf How does ViewState protect against CSRF?]<br>
 
[http://software-security.sans.org/developer-how-to/developer-guide-csrf How To Fix CSRF using Microsoft .Net ViewStateUserKey and Double Submit Cookie, by Eric Johnson and James Jardine]<br>
 
[http://software-security.sans.org/developer-how-to/developer-guide-csrf How To Fix CSRF using Microsoft .Net ViewStateUserKey and Double Submit Cookie, by Eric Johnson and James Jardine]<br>
 +
[http://security.stackexchange.com/questions/23371/csrf-protection-with-custom-headers-and-without-validating-token CSRF Protection With Custom Headers (focus on the answer, not the question)]<br>
 
[http://msdn.microsoft.com/en-us/library/ms178199%28v=vs.85%29.aspx MSDN - Securing ViewState]<br>
 
[http://msdn.microsoft.com/en-us/library/ms178199%28v=vs.85%29.aspx MSDN - Securing ViewState]<br>
 
[http://msdn.microsoft.com/en-us/library/ms972969.aspx#securitybarriers_topic2 MSDN - ViewStateUserKey]<br>
 
[http://msdn.microsoft.com/en-us/library/ms972969.aspx#securitybarriers_topic2 MSDN - ViewStateUserKey]<br>
Line 115: Line 117:
 
[http://msdn.microsoft.com/en-us/library/system.web.mvc.validateantiforgerytokenattribute%28v=vs.100%29.aspx MSDN - ValidateAntiForgeryTokenAttribute]<br>
 
[http://msdn.microsoft.com/en-us/library/system.web.mvc.validateantiforgerytokenattribute%28v=vs.100%29.aspx MSDN - ValidateAntiForgeryTokenAttribute]<br>
  
[[Category:OWASP .NET Project]][[Category:Stub]]
+
[[Category:OWASP .NET Project]]

Latest revision as of 15:47, 16 February 2015

Description

In short, CSRF abuses the trust relationship between browser and server. This means that anything that a server uses in order to establish trust with a browser (e.g., cookies, but also HTTP/Windows Authentication) is exactly what allows CSRF to take place - but this only the first piece for a successful CSRF attack.

The second piece is a web form or request which contains parameters predictable enough that an attacker could craft his own malicious form/request which, in turn, would be successfully accepted by the target service. Then, usually through social engineering or XSS, the victim would trigger that malicious form/request submission while authenticated to the legitimate service. This is where the browser/server trust is exploited.

In order to prevent CSRF in ASP.NET, anti-forgery tokens (also known as request verification tokens) must be utilized.

These tokens are simply randomly-generated values included in any form/request that warrants protection. Note that this value should be unique for every individual session. This guarantees that every form/request is tied to the authenticated user and, therefore, protected from CSRF.

Important: non-idempotent GET requests represent an anti-pattern where CSRF protection is concerned. Always use POST requests with anti-CSRF tokens for proper protection.


Mitigation Examples

Please note that the following examples may not entail a complete anti-CSRF solution for any given Web application. Specific requirements may call for adjustments and/or combinations of different strategies.

Solutions NOT considered secure

- All of the solutions provided in this article are not designed to work with GET requests that change the server state (e.g., /example/delete.aspx?id=1). GET requests should be idempotent so that CSRF cannot take place.

- Assuming that SSL/TLS will thwart CSRF attacks just because the cookie is marked "Secure" and/or "HTTPOnly". The problem lies in the trust between legitimate browser and server. Therefore, the browser will just send its current cookies when the forged request is triggered. The attacker never has to touch any cookies.

- Referer header verification as the only protection. This can be easily manipulated.

- Cookie double-submission when the cookie utilized is the session cookie. This exposes the session cookie to JavaScript. Always mark the session cookie "HTTPOnly" so that it cannot be accessed with JavaScript.

- Any CSRF protection is null and void given the presence of XSS, for several reasons. The main and obvious reason is that, through XSS, the attacker can hijack the session and spoof the user, not even having to worry about performing CSRF.

ASP.NET MVC and Web API: Anti-CSRF Token

ASP.NET has the capability to generate anti-CSRF security tokens for consumption by your application, as such:

1) Authenticated user (has session which is managed by the framework) requests a page which contains form(s) that changes the server state (e.g., user options, account transfer, file upload, admin functions, etc.)

2) Generate the security token (or grab it from the session state) and send the token as a session cookie (again, managed in the session state, unique per session) as well as within a hidden value in each form.

3) Once the user submits the form, validate the token stored in the session state against the token included in the submitted form value. On failure, disregard form.

Effectively, this is the cookie double-submission approach done right, since the security token is submitted both as a cookie (managed in the framework session state) and within a hidden form value at the same time.

For implementation details, see:
MVC CSRF Prevention (official ASP.NET blog)
Web API CSRF Prevention (official ASP.NET blog)

The standard frequency of token generation is per-session, so make sure your sessions have a reasonable/configurable time-out. It is possible to issue new tokens on a per-request basis. However, the added protection may be insignificant, if this approach even fits your application. See the link below for a discussion on the matter:
Why refresh CSRF token per form request?

WebForms: ViewState

Requirement:
EnableViewStateMac must be set.
In fact, the ViewState MAC can no longer be disabled for versions since September 2014.

The ASP.NET ViewState contains a property, ViewStateUserKey, which offers protection against CSRF by adding uniqueness to the ViewState MAC as long as you set it to a new value for every session.

Note that ViewStateUserKey will not actually add a new value to the ViewState, but rather simply influence the MAC process so as to make every MAC unique per user session. Therefore, setting ViewStateUserKey to the current Session ID is acceptable.

Since Visual Studio 2012, the anti-CSRF mechanism has been improved.

The new strategy still uses the ViewState as the main entity for CSRF protection but also makes use of tokens (which you can generate as GUIDs) so that you can set the ViewStateUserKey to the token rather than the Session ID, and then validate it against the cookie.

Here's a blog post by Eric Johnson and James Jardine with an example of this implementation.

For more implementation details, see:
MSDN - Securing ViewState
MSDN - ViewStateUserKey

Considerations for AJAX

Depending on your application, you'll likely have to choose between using HTTP Headers or POST data to carry your anti-CSRF tokens.

Whatever you choose, the optimal validation method is indeed through tokens. This means you can follow the token strategy while creating either a custom header to hold the token value or just sending the token with the rest of the POST data.

For more guidance, see the answers given to the following questions:
Anti-CSRF Cookie
CSRF Protection With Custom Headers

Related Attacks

CSRF (Attack)
CSRF (Full Wikipedia Article)
XSS (Attack)


Related Vulnerabilities

XSS
Insecure Randomness
Insecure Third-Party Domain Access
Non-Cryptographic Pseudo-Random Number Generator


Related Controls

.NET CSRF Guard


Related Technical Impacts

Accountability
Confidentiality


References

Why refresh CSRF token per form request?
CSRF Prevention (official ASP.NET blog)
Preventing CSRF Attacks (official ASP.NET blog)
Anti-CSRF and Cookies
How to protect against CSRF by default in ASP.NET MVC 4?
How does ViewState protect against CSRF?
How To Fix CSRF using Microsoft .Net ViewStateUserKey and Double Submit Cookie, by Eric Johnson and James Jardine
CSRF Protection With Custom Headers (focus on the answer, not the question)
MSDN - Securing ViewState
MSDN - ViewStateUserKey
MSDN - HtmlHelper.AntiForgeryToken
MSDN - ValidateAntiForgeryTokenAttribute