CORS redirect behavior proposal

Looking at the behavior of existing implementations, we don't seem to
have committed to how to handle redirects in CORS yet:

IE8 (XDomainRequest): Redirects are not supported

Firefox 3.5: If you start off same-origin, you can redirect
cross-origin once, and the Origin header gets added at that point.
Once you're making cross-origin requests, however, further redirects
are not allowed.

Safari 4 and Chrome 3: If you start off same-origin, cross-origin
redirects are blocked. If you start off cross-origin, you can redirect
on that origin, but you can't go to yet another origin. However, this
redirect behavior only works with synchronous requests; if you're
making an asynchronous request you can't do any redirects.

In summary, CORS redirects have not yet been implemented, except for
synchronous requests in Safari and Chrome. Furthermore, the Safari and
Chrome implementation doesn't yet handle the case where one foreign
origin redirects to another. We still have some choice as to what
behavior to specify in this case.

Goals

The first order of business is to make sure that the specification
fixes the DELETE request security issue that Tyler Close pointed out.
Additionally, it would be nice for the Origin header to be usable as a
CSRF defense (eliminating the need for a separate Sec-From header).

Proposal

Same-origin redirects are allowed. Redirects from same-origin to
cross-origin are also allowed. When processing a redirect from one
foreign origin to another, the browser replaces the Origin header with
"null". In this situation, the browser appends a Sec-Redirect-Chain
header that allows sophisticated sites to see the list of origins that
contributed to this request.

Example 1: Suppose a site1.com web page makes an XMLHttpRequest to
site2.com, which is redirected to site3.com. The requests to site2.com
has a site1.com Origin header, but the request to site3.com has an
Origin header of "null". When making a request to site3.com, the
browser adds a Sec-Redirect-Chain header of "http://site1.com,
http://site2.com".

Example 2: Suppose a site1.com web page makes an XMLHttpRequest to
site1.com, which is redirected to site2.com, which is redirected to
site3.com. The requests to site1.com and site2.com have a site1.com
Origin header, but the request to site3.com has an Origin header of
"null". When making a request to site3.com, the browser adds a
Sec-Redirect-Chain header of "http://site1.com, http://site2.com".

Discussion

This proposal defends against the DELETE attack that Tyler pointed
out: Suppose a goodsite.com web page makes a DELETE request to
attacker.com, which is redirected to victim.com. Previously, the
request to victim.com would carry the goodsite.com origin, potentially
confusing the victim site into deleting something. Under this
proposal, the Origin header would be null, so the victim site would
not be confused.

To defend itself against CSRF, a simple site just needs to make sure
the Origin header contains a whitelisted value. A sophisticated site
that uses redirects can look at the Sec-Redirect-Chain and ensure that
it trusts all the origins in the list.

The Sec-Redirect-Chain header is a tradeoff between complexity and
supporting more use cases. If we feel that the Sec-Redirect-Chain
header is too complicated, it could be dropped from this proposal.

Received on Tuesday, 22 September 2009 18:39:49 UTC