Cross-site request forgery defense proposal

Scott Malabarba / IBM [email protected]

Version Date Comment 0.1 03/04/10 Initial draft 0.2 03/24/10 Corrected to reflect the use of JSONP in the spec Background Cross-site request forgery (CSRF) is a class of attack in which malicious code executed within the browser, such as JavaScript, exploits the user's trust in the browser's security controls. There are several varieties of CSRF. In the type that concerns CMIS, the attacker tricks the victim into visiting a hostile web site while still logged in to the target web site. A malicious script then makes requests to the target site using the victim's active, authenticated session. On a CMIS repository, the attacker could corrupt or delete content and metadata.

Scope Theoretically, a CSRF attack can target any server: GET, POST, PUT or DELETE, form-based or not. However, in reality, the attack relies on the user's trust in the browser. A browser-based application is unlikely to use the web services or Atom CMIS bindings when the browser binding is available. A standalone client application is not likely to authenticate users in a way that makes it vulnerable to CSRF.

Malicious script code using CSRF could potentially make a GET request for confidential data such as document content or metadata and the server would reply. In general, browser controls either disallow cross-site GETs completely or allow them but do not allow the script to inspect the response. Therefore, the attacker cannot breach confidentiality. In using JSON, however, the browser binding opens all GET requests to CSRF attacks as well.

There are several common defenses, of varying effectiveness, against CSRF attacks. Two of these, the secret token and custom header, require code on both client and server. It is these defenses that the browser binding specification must provide for. Other defenses, such as Referer or Domain header verification, are outside the scope of this document.

The proposal is intended to provide developers and administrators with several relatively lightweight options for securing their applications against CSRF attacks. Some actions outside of the specification will be required. For example, here is one path based on the capabilities described below:  Server requires the secret token on all GET and POST requests  JSONP-based client can make all requests across domains except for the secret token  JSONP-based client relies on a proxy service to get the secret token from its own domain  Script originating on a hostile host cannot get the secret token from either the server or client (proxy) domains  All requests from the hostile script lack a valid token and are rejected

Capabilities The server must advertise to clients which CSRF defenses are in use. This proposal introduces a new category of capabilities:

CSRF capabilities: capabilitySecretToken (enumCapabilitySecretToken) Indicates that a secret token is required to authorize all form POST requests. ▪ requiredOnPost: a secret token provided by the server must accompany all form POST requests ▪ requiredOnAll: a secret token provided by the server must accompany all GET and POST requests ▪ none: secret tokens are not required. capabilityCustomHeader (enumCapabilityCustomHeader) Indicates that a custom header, “X-Cmis-Request”, must accompany all form POST requests.  requiredOnPost: “X-Cmis-Request” is required on all form POSTs  requiredOnAll: “X-Cmis-Request” is required on all GET and POST requests  none: the header is not required

TODO: do we need more granularity?

Custom Header Defense The custom header defense relies on the fact that XHttpRequest libraries do not allow client code to send custom headers across domains. It is not ironclad: for instance, Flash does allow scripts to send custom headers across domains. However, it can provide a supplement to the secret token defense, or be applied in cases where the secret token cannot be implemented. The mere presence of the custom header on a request is enough for the server to verify the request's origin; the name and content of the header are irrelevant. If the server reports the capabilityCustomHeader capability, then it SHOULD verify that every incoming form POST and/or GET request, depending on the capability value, has the “X-Cmis- Request” header set. If the server enforces this rule and finds an incoming request that is missing the header, the server MUST return HTTP status code 401 and SHOULD include a meaningful error message in the response body. If the server reports the capabilityCustomHeader capability, then a client MUST send a custom header “X-Cmis-Request” along with all POST and/or GET requests, as indicated by the capability value. Note that plain HTML forms and GET requests triggered by