CSRF Protection
From MemberWiki
The RequesterOrigin header: CSRF protection and beyond (Draft Proposal)
0. Authors
- Sumeer Bhola (sbhola@us.ibm.com)
- Michael Steiner (msteiner@us.ibm.com)
1. Problem
CSRF protection is necessary for current sites due to cross-site submission of credentials by the browser. This includes basic auth and digest auth credentials, and credentials represented in cookies. Adding CSRF protection to a web site is overly complicated and brittle because of dealing with multiple issues (1) rewriting static URIs generated on the server to include a CSRF-protection credential, (2) dealing with expired CSRF-protection credentials in server-side rewriting, (3) explicitly including CSRF-protection credentials for dynamically generated requests and links by the client, (4) preventing leakage of CSRF-protection credentials included in URIs in subsequent referer headers. Item (4) also implies that current CSRF-protection techniques are typically not very secure.
A trustworthy referer header would easily solve the CSRF protection problem since it identifies the browser window making the request. However, the referer header is not viewed as trustworthy for multiple reasons (1) vulnerabilities in the past which allowed malicious web pages to fake the referer header, (2) browser users or intermediaries (like internet security products) modifying the referer header to protect user privacy.
2. Goals
The goal of this proposal is a simple and secure approach to CSRF protection, by extending the HTTP protocol. The approach must satisfy the following additional requirements:
- Credentials: Encompass all types of credentials that are automatically submitted by current browsers, and future additions to these credentials.
- Privacy: Address user privacy concerns.
- Server-side Enforcement: Enforcement of CSRF-protection should continue to be at the server-side.
- Generalizable: It should allow generalization of CSRF-protection to allow cross-site requests from trusted sites.
- Legacy: It should deal with legacy issues, both legacy browsers and legacy web sites.
3. Description
HTTP requests contain an optional new header, RequesterOrigin. The RequesterOrigin header contains the scheme, domain and optionally the port (if the port is not the default port for the scheme) of the browser window from which the request originated (also called the requester).
The header does not suffer from the privacy issues that plague the referer header as it is disabled by default. Enabling it is an explicit decision, made at the time that the browser window (requester) that is making the request was loaded. The requester has to decide to reveal its identity, and has fine-grained control on whom to reveal it to. By making this decision explicit, the approach protects user privacy as well as is possible (the requester can always reveal itself by including its identity in the request URI).
3.1 Trustworthiness
The RequesterOrigin header is trustworthy in browsers that support it (called new browsers henceforth). By trustworthy we mean that if the header is present, the header value is accurate for requests originating from a browser. Absence of the header implies no knowledge of the requester, and so the request should be treated with the appropriate level of suspicion by the receiving server.
For legacy browsers, the RequestOrigin header is usually trustworthy. There are 2 cases where it is not trustworthy (1) same-site XMLHttpRequest (XHR), and (2) cross-site XHR defined in the W3C access-control proposal. These can be simply dealt with, as described in section 4.
Browser extensions, like Flash, can also prevent it from being trustworthy. For instance, this is an issue when allowing cross-site accesses with Flash, and we discuss multiple ways of dealing with this in section 5. However, in general, non-standard ways of accessing content from browsers is not in scope for this proposal.
Requests originating from a server can obviously forge the RequesterOrigin header. We assume the user making the request is also authenticated, either using channel authentication or the request includes some token identifying the user. Since CSRF-protection is about detecting misuse of user authentication credentials from a browser, accesses originating from a server which the user controls (or explicitly decided to give its credentials to) are not an issue, and therefore not in scope.
Related to the issue of trustworthiness is the name 'RequesterOrigin'. The proposal is name-agnostic. In section 5 we discuss alternative names, including reusing/repurposing existing header names.
3.2 Syntax and Protocol
As mentioned earlier, the RequesterOrigin header contains the scheme, domain and optionally the port (if the port is not the default port for the scheme) of the browser window from which the request originated. The syntax of the value is identical to the Access-Control-Origin header in the W3C proposal for cross-site requests (http://www.w3.org/TR/access-control/#access-control-origin). However, there are key differences wrt the Access-Control-Origin header:
- The RequesterOrigin header is optional, and off by default, and hence offers user-privacy protection.
- The absence of the RequesterOrigin header does not imply a same-site request. The absence of the header should be treated with suspicion (a legacy browser or a requester that is not revealing its identity). In contrast the absence of the Access-Control-Origin header signifies same-site XHR.
- The RequesterOrigin header is not limited to XHR.
- The RequesterOrigin header is used for server-side access control enforcement at the point when the request is received. There is no additional client-side enforcement on the response path.
For the RequesterOrigin header to be enabled, the requesting window has to explicitly enable it. This is done in the HTTP response that loaded the requesting window. That HTTP response contains a header EnableRequesterOrigin that describes the set of domains (optionally scheme and port) to which the RequesterOrigin header should be sent. Wild-cards are permissible in describing scheme, domain and port patterns. The syntax of the value is identical to the syntax of the value of the Access-Control HTTP response header in the W3C proposal for cross-site requests (http://www.w3.org/TR/access-control/#access-control0). The semantics are different since the header does not describe access permission, and instead describes the set of other sites to which this browser window's identity can be sent in the RequesterOrigin header.
4. Server-side enforcement
4.1 Non-legacy
Here we consider the ideal non-legacy future, with only new browsers, which implies a trustworthy RequesterOrigin header, and servers that know about the existence of this header.
For accesses that require CSRF-protection, the server (1) verifies the user credentials submitted (basic auth, digest auth, cookies), and (2) checks that the requester identified in RequesterOrigin is trusted to not misuse the user credentials for this access. Note that RequesterOrigin may be used to grant access not just to the same domain, but also sub-domains or other domains. In the absence of the RequesterOrigin header, only public accesses (these require no user credentials and can be accessed by any domain) are granted.
4.2 Legacy
4.2.1 Cases
Here we consider all the legacy cases that deal with incremental adoption of the RequesterOrigin proposal. We classify these cases based on both browsers and sites:
- Browsers: Browsers are totally ordered and labeled according to the features they support.
- B0: No cross-site XHR support and no support for Microsoft's XDR (cross-domain request).
- B1: Support cross-site XHR and Microsoft XDR, but no support for the RequesterOrigin header.
- B2: Also supports the RequesterOrigin header.
- Note that in this total ordering, only additional features are being added, and no features removed. We will refer to browsers B0, B1 as legacy browsers.
- Sites/servers: For sites, classification is along two categories: (1) which browsers they are aware of, and (2) which browsers they choose to support. The former is a total ordering with the numbers identical to browsers: A site labeled Si is aware of browser features in Bi and prior browsers. Regarding which browsers a site may choose to support, we use a label Si-j to imply that the site is only supporting browsers Bj and later (i>=j, since a browser cannot support Bj and later if it is not aware of Bj). To illustrate, a site labeled S2-1 is aware of browsers B0, B1, B2 (due to the label S2), and is willing to support browsers B1 and later. We do not assume that the site can identify the browser label of the browser making the request.
4.2.2 Enforcement
4.2.2.1 Sites supporting legacy browsers (S0-0, S1-0, S2-0, S1-1, S2-1)
Since legacy browsers do not support the RequesterOrigin header, the site has to invest in current CSRF-protection techniques (to allow browsers to make non-public accesses), and use these techniques regardless of browser label. The site's CSRF-protection is unaffected by the presence of an additional RequesterOrigin header.
4.2.2.2 Sites not supporting legacy browsers (S2-2)
In this case the site performs enforcement as described in section 4.1.
However, we would like to ensure that legacy browsers cannot circumvent the protection described in section 4.1. By ensuring this, we prevent users of legacy browsers from being subject to CSRF attacks if they happen to authenticate to this site.
We consider the ways in which a request can be made from legacy browsers (B0, B1):
- Following a link in an HTML document: The RequesterOrigin header will be absent, implying an unknown requester.
- Including scripts, images etc. in an HTML document using tags: The RequesterOrigin header will be absent, implying an unknown requester.
- XHR and its variants:
- same-site XHR: The requestor can forge the RequesterOrigin header. However it can make a request only to its own site, due to the same-origin policy. We assume the server trusts requesters from its own site to not misuse the user credentials, so forging the RequesterOrigin header is of no value.
- cross-site XHR (browser B1): Unfortunately the cross-site XHR specification from the W3C allows forging of the RequesterOrigin header, and also submits user credentials. However it does include a mandatory Access-Control-Origin header with the same meaning as a trustworthy RequesterOrigin header. The server should first check whether the Access-Control-Origin header is present, and if so, use that value as the requester instead of the RequesterOrigin header.
<recommendation> Before officially releasing support for cross-site XHR, browser vendors should mark as reserved an agreed upon prefix of HTTP request headers. This will not impact legacy code, since it does not use cross-site XHR, and will allow this proposal or one like this to be more easily realized in the future (by renaming RequesterOrigin to be in the reserved prefix). </recommendation>
- XDR (Browser B1): Since XDR does not allow the requester to set any headers, the RequesterOrigin header will be absent. This implies an unknown requester, so only public accesses are granted.
5. Misc Issues
5.1 XDR+: Extending Microsoft's XDR to send credentials
With the RequesterOrigin header, it is reasonable to extend Microsoft's XDR (cross-domain request) to allow the browser to include credentials in the request (user credentials, including those in cookies, are not submitted in the current XDR). The requester is not allowed to set the Access-Control-Origin header or the RequesterOrigin header (as in the current XDR, which does not allow the requester to set any headers). The browser sets the RequesterOrigin header if enabled by the requester.
To analyze server-side enforcement with XDR+, we enhance the browser and site labels described in section 4.2.1 as follows:
- Browser label B3: browser supports XDR+.
- Server label S3: The server is aware of XDR+.
5.1.1 Non-legacy enforcement (S3-2, S3-3, S2-2)
As in section 4.2.2.2, these are sites not supporting browsers B0, B1, and therefore perform the simple enforcement described in section 4.1.
The analysis in section 4.2.2.2 applies in this case too.
5.1.2 Legacy enforcement - not aware of XDR (S0-0)
As discussed in section 4.2.2.1, this site uses current CSRF-protection techniques to allow browsers to make non-public accesses.
We define U as the universal set containing all possible accesses to non-public resources at this site. The set U consists of two sets:
- CSRF-protected-accesses
- CSRF-allowed-accesses
For an access, acc, that belongs to the set CSRF-protected-accesses, the XDR+ access will be denied. This is because acc looks like any other CSRF access made using other means, such as a script tag or form post. For an access, acc, that belongs to the set CSRF-allowed-accesses, the XDR+ access will be allowed on the server. The response will not contain the XDomainRequestAllowed: 1 header. If acc did not modify server-side state, this is harmless as the response is dropped by the browser. This is identical to what happens currently with sites that support CSRF-protection only for accesses that modify server state. If acc modifies server-side state, the response will also be dropped by the browser, but the damage may already be done. However, this site is vulnerable to the same attack using other CSRF techniques, like a script tag or a form post, so there is no increase in vulnerability.
5.1.3 Legacy enforcement - aware of XDR (S1-0, S2-0, S3-0, S1-1, S2-1, S3-1)
The server may do enforcement identical to section 5.1.2. However, there is a possibility that it uses its awareness of XDR to do some special-case checking for requests containing an XDomainRequest: 1 header.
We consider the following options for special-case checking:
- Deny all XDR: It denies all requests containing an XDomainRequest: 1 header. The XDR+ access will also be denied.
- Allow XDR only for public accesses: This is unaffected by XDR+.
- Allow XDR for some non-public accesses: In this case the server should be doing CSRF-protection, and the analysis in section 5.1.2 applies to this case.
5.2 Flash
Flash allows cross-domain requests that submit browser credentials, if they are enabled using a cross-domain policy file hosted by the server. We recommend not using this feature as the RequesterOrigin header will be untrustworthy. This case has some resemblance to the cross-site XHR case discussed in section 4.2.2.2, however cross-site XHR supports a trustworthy Access-Control-Origin header while Flash does not have anything that offers similar functionality. The referer header is also untrustworthy, even ignoring any privacy concerns, in some versions of Flash (http://www.webappsec.org/lists/websecurity/archive/2006-07/msg00069.html).
5.3 Naming
The name RequesterOrigin is not important for the proposal described above. Ideally, we would like to use a header name that can never be forged by JavaScript code running in legacy browsers. This would simplify the enforcement and analysis discussed in sections 4, 5.1, 5.2: specifically it would simplify dealing with cross-site XHR (section 4.2), XDR+ (section 5.1), Flash cross-domain requests (section 5.2).
However, choosing an appropriate name that satisfies this ideal is non-trivial for the following reasons:
- HTTP has not set aside a reserved header namespace for future protocol extensions.
- The referer name is reserved (except for past Flash vulnerabilities discussed in section 5.2), but is not appropriate since using it would need a change in semantics. Changing the semantics may break legacy servers.
- The Access-Control-Origin header for cross-site XHR has the same syntax as the RequesterOrigin header and we could use that name instead of RequesterOrigin. However, this would require broadening the scope of the W3C access-control proposal (http://www.w3.org/TR/access-control). For instance, that proposal would need to be expanded to address non-XHR accesses, and clarify that the absence of Access-Control-Origin does not imply same-origin access.
- Flash reserves the WWW-Authenticate header in requests. This is surprising since the WWW-Authenticate header has defined semantics only as a response header. However it would be reasonable to use the name WWW-Authenticate.
Based on the above the following names may be a better engineering choice than RequesterOrigin:
- Use the name WWW-Authenticate, and reserve this header even for cross-site XHR.
- Use the name Access-Control-Origin, and broaden the scope of the W3C access control proposal.
6. Comparison to SameRefererOnly proposal
There is a proposal to add a SameRefererOnly marker to cookies. The comparison here is based only on the short description contained in http://getahead.org/blog/joe/2007/08/07/fixing_browser_security_samerefereronly.html.
As specified in the proposal "Any cookie marked SameRefererOnly MUST only be sent to servers when the domain of the cookie matches the referring domain".
Unlike the RequesterOrigin proposal, the SameRefererOnly proposal applies only to (1) credentials contained in cookies, (2) same-site requests, (3) does not seem to deal with legacy issues.
