Re: Origin enables XSS to escalate to XSRF (was: security issue with XMLHttpRequest API compatibility)

On Sun, Jun 7, 2009 at 12:12 PM, Adam Barth <w3c@adambarth.com> wrote:

> Hi Mark,
>
> Thanks for your feedback.  At a high level, you seem concerned about
> very advanced sites (e.g., ones use object-capability mashups).


While I clearly am concerned about object-capability mashups, from your
response, and from some private responses I've received, I have clearly
created some confusion by leading with this example. The point I am making
does not depend on the existence of any JavaScript sanitizing technology,
Caja-like or otherwise. In this first response to your message, after the
following two paragraphs, I will leave aside any JavaScript sanitizing
technology.

I do wish to take issue with your "very advanced" comment. While Caja-like
systems are complex to *implement* on current browsers, they are much
simpler to use safely and successfully than is the current incoherent mess
of the current so-called "browser security model", about which more below.
Anyone *safely* doing anything even moderately ambitious using the current
browser security model is much more "advanced" than is safe use of Caja-like
systems.

Even with the complexity needed to use and deploy JavaScript sanitizing
technology today, between Facebook and Yahoo Application Platform, they are
already widely deployed (> 120M users) and deserve to be taken seriously.
With the immanent arrival of EcmaScript 5, Caja-like systems will become
trivial to build, be safer while accommodating an extended threat model, and
will be faster and smaller than is possible today.



> The Origin-header-as-CSRF-defense is aimed at making CSRF defense easier
> for simple sites.  Just like you need to do complex gymnastics to
> avoid XSS when running untrusted JavaScript in your security origin,
> you'll also have to use one of the more complex CSRF defenses, such as
> secret tokens, in these cases (just as you need to do for all sites
> today).
>
[...]

> For better or worse, that's the security model we've got.  Worrying
> about this for the Origin-header-as-CSRF-defense is a bit like horse
> is gone (to borrow a cliche).  Almost all browser security features
> have this behavior.  For example, cookies, the Origin-header-for-CORS,
> postMessage, localStorage, window.open, the password database, etc.
>

Currently, prior to the Origin header, as you say, sites use secret tokens
for CSRF defenses. The presentation of secret tokens as authorizing
information is a good practice that we should encourage. It is the explicit
inclusion of authorizing information directly in the payload of the message.
This is a designated authority pattern that leads away from confused deputy
hazards. The increasing prevalence of this pattern -- driven by necessity
since "the security model we've got" failed to provide security -- means
there are still some horses remaining in the barn.

To make progress, we should seek to lower the expertise needed to use this
good pattern safely, so that it can come to be used by less "advanced"
sites. Instead, your rationale for the Origin header would have sites use
identified Origins *instead* of secret tokens to make access control
decisions. This is quite explicit in the cors recommendations for server
behavior.

Getting the security right for mashups that run untrusted script in a
> trusted security origin is really tricky, as I'm sure you're quite
> aware.  Fortunately, the vast, vast majority of web sites don't have
> to worry about these issues.  These web sites, however, do have to
> worry about CSRF.  The goal of the Origin-header-as-CSRF-defense is to
> provide low-cost way for sites to mitigate CSRF vulnerabilities.  A
> site that's doing some complicated Caja-style mashup has already
> bitten the complexity bullet and will need to use a complex CSRF
> defense.
>

(See above re "complicated".)

You're assuming that origin A is using a complex Caja-style mashup.
> We're not after that use case.  The Origin-header-as-CSRF-defense
> doesn't make A or B's job any harder.  It just makes life easier in
> the common case.
>

Ok, let's worry here only about XSRFs on websites that use no JavaScript
sanitizing technology. I have privately heard comments along the lines of
"Even without Origin, XSSs already enable XSRFs, so how does the
introduction of Origin enable any new attacks?" It sounds like you are
posing a similar question.

* If servers don't pay any attention to the Origin header and continue to
rely on secret tokens, then the Origin header does not enable new attacks.
But in this case Origin would be useless.

* If servers change from requiring secret tokens to requiring secret tokens
*and* appropriate Origin headers, then this is strictly less permissive and
so does not enable new attacks. But this more restrictive behavior is also
too restrictive; it would reject some requests that should be allowed. In
this case, Origin would be worse than useless.

* If a server in origin B operates according to the cors recommendation and
allows some access based *only* on the presentation of an origin it "trusts"
say "Origin: A", then a successful XSS on a page at origin A escalates into
an XSRF against the server at B. By contrast, if the server at B required a
secret token, as it must now, then A has some protection against such
escalation. The XSS attacker, in order to gain more access to B than it
could have from a page from its own origin, must use its ability to run "as
A" to obtain the secret token it needs to present to the server at B. If
servers at A don't freely hand out such tokens in response to guessable GET
requests, then the secret token prevents XSS-at-A-attacker's XSRF against B
from abusing the authority that B associates with A. If servers obey the
cors recommendations and instead allow such access without a secret token,
then they become open to new attacks. In this case, the use of an identified
Origin would be harmful.



> > Three proposals I've seen in these threads, if combined and extended,
> > point towards a solution.
>
> [Snip long proposal to introduce a XMLHttpRequest3 that always sends
> an null Origin header.]
>
> This proposal is compatible with the Origin-header-as-CSRF-defense.  I
> drafted the requirements to allow for this kind of future innovation.
> In particular, the user agent is always allowed to send Origin: null
> if the UA thinks that's a good idea.
>


I am glad you ended on that note. As I mentioned at the beginning of this
thread, I was glad to see in your IETF proposal that user agents are allowed
to send "Origin: null". I am distressed by the absence of similar language
in cors. Worse, what I have not yet seen in any proposal is a way for
JavaScript code to say to the browser "please send all these requests with
no credentials, and with an 'Origin: null' header."

I do like the idea of staging the roll out of features. However, I am
confused by your sense of the order in which these "innovation" should be
rolled out. If we roll out "Origin: null" first, then we do not encourage
websites to stop using secret tokens to protect against XSRF. We do not
entrench any dangerous habits that would make better security features
harder to roll out later. With the staging you recommend, we would kill the
few horses remaining in that barn before we take the steps that could have
protected them.

Switching metaphors and quoting again your

For better or worse, that's the security model we've got.


As someone once said, if you find that you've dug yourself into a deep hole,
the first thing you should do is stop digging.

-- 
   Cheers,
   --MarkM

Received on Sunday, 7 June 2009 21:53:41 UTC