Subject: New header for "Fragment-Scope"?

From: Mark Nottingham <[email-masked]>
Date: Fri, 9 Jan 2015 14:56:22 -0500

Brad Hill brought up an interesting proposal on the repo (I closed the issue as it was in the wrong place).

—8<---

A recurring weakness with OAuth and related capability URL usages (http://www.w3.org/TR/capability-urls/) is the reapplication of URL fragments on redirects:

http://tools.ietf.org/html/rfc7231#section-9.5

This behavior is frequently abused in combination with resources that act as open redirectors to leak sensitive information in a fragment.

I would like to suggest an additional header, 'Fragment-Scope' that could be sent with a Location header on a 3xx to control the disposition of a fragment after a redirect. Values would be 'no-redirect' which would instruct the user agent to discard the fragment on any subsequent redirect, or 'same-origin' which would discard the fragment after any non-same-origin redirect. The scope rule, once set, would remain until the user agent terminates following redirects. (so a 'same-origin' policy could not be stripped by redirecting to a second open-redirector in the same origin, and then off-origin from there).

—>8—

What do people think?

--
Mark Nottingham   http://www.mnot.net/

---

From: "Roy T. Fielding" <[email-masked]>
Date: Fri, 9 Jan 2015 12:33:49 -0800

> I would like to suggest an additional header, 'Fragment-Scope' that could be sent with a Location header on a 3xx to control the disposition of a fragment after a redirect. Values would be 'no-redi…

I think it has nothing to do with HTTP.  The request invocation engine
(e.g., browser) is responsible for determining whether the original
fragment applies after the request, regardless of zero or more redirects.
What they should do is tell the fetch algorithm to discard the fragment
prior to performing retrieval, or at least prior to following a redirect.
That is an internal implementation concern.

Regardless, adding more bits for new clients won't fix the leak of 
"sensitive" information on deployed clients. I don't think adding more
hacks to an already hacked notion of capability URLs is a worthwhile effort.

....Roy

---

From: Julian Reschke <[email-masked]>
Date: Sat, 10 Jan 2015 11:46:05 +0100

> I would like to suggest an additional header, 'Fragment-Scope' that could be sent with a Location header on a 3xx to control the disposition of a fragment after a redirect. Values would be 'no-redi…

I'd like to see a better explanation of the problem. An example would 
help as well.

Best regards, Julian

---

From: Mark Nottingham <[email-masked]>
Date: Sat, 10 Jan 2015 12:44:54 -0500

Hi Roy,

Trying to clarify…

> On 9 Jan 2015, at 3:33 pm, Roy T. Fielding <[email-masked]> wrote:
> 
> I think it has nothing to do with HTTP.  

Are you saying that this shouldn’t be a header? “It doesn’t have anything to do with HTTP” could be applied to many, many current headers.

> The request invocation engine

Are you saying that it’s inconceivable that the semantics of fragment combination might be usefully hinted from the server?

> hacks to an already hacked notion of capability URLs is a worthwhile effort.

I’d be interested in feedback from the security community about this.

Cheers,

---

From: Mark Nottingham <[email-masked]>
Date: Sat, 10 Jan 2015 13:09:19 -0500

> On 10 Jan 2015, at 1:07 pm, Roy T. Fielding <[email-masked]> wrote:
> 
> I mean that fragments are defined by media types and the type or script that is providing the fragment can tell the UA not to reuse it on redirects.

… or the media type definition could defer to a HTTP header to determine what to do.

> Fragments have no role in HTTP.
> 
> ....Roy
> 
> 
>> On Jan 10, 2015, at 9:44 AM, Mark Nottingham <[email-masked]> wrote:
>> 
>> Hi Roy,
>> 
>> Trying to clarify…
>>

---

From: "Roy T. Fielding" <[email-masked]>
Date: Sat, 10 Jan 2015 10:07:42 -0800

I mean that fragments are defined by media types and the type or script that is providing the fragment can tell the UA not to reuse it on redirects. Fragments have no role in HTTP.

....Roy

---

From: "Roy T. Fielding" <[email-masked]>
Date: Sat, 10 Jan 2015 10:46:33 -0800

> … or the media type definition could defer to a HTTP header to determine what to do.

That would be ass-backwards.  The server has no idea that a fragment exists
or why it might have been referenced.  The UA already knows both.  So,
rather than extend HTTP to communicate something about an element that
it knows nothing about, just extend OAUTH to instruct the UA to discard the
fragment when it is no longer needed.  That can be fixed within the UA
implementation without any further bits on the wire.

....Roy

---

From: Brad Hill <[email-masked]>
Date: Sat, 10 Jan 2015 22:22:14 +0000

Here's an example that I hope will clarify:

http://tools.ietf.org/html/rfc6749#section-4.2

In OAuth, an Access Token Request looks like the following:

GET 
/authorize?response_type=token&client_id=s6BhdRkqt3&state=xyz&redirect_uri=
https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb HTTP/1.1
Host: server.example.com

If the authorization server is willing to process this request, it
responds like so:

     HTTP/1.1 302 Found
     Location: 
https://client.example.com/cb#access_token=2YotnFZFEjr1zCsicMWpAA&state=xyz
&token_type=example&expires_in=3600

The fragment containing the access token is not sent with the subsequent
HTTP request to client.example.com, but if client.example.com responds
with text/html content, the user agent applies the fragment, which can be
read by e.g. script in the DOM.

The nature of OAuth and similar protocols is that the redirect location is
passed in with the request (in this example, the redirect_uri paremeter).
If that redirect_uri is maliciously modified, the server might send
credentials to an incorrect host.  The common mitigation to this is to
whitelist the set of uris that server.example.com is willing to redirect
to.

But even if server.example.com is only ever willing to redirect to
https://client.example.com/cb, what if there exists unknown processing
logic at that endpoint (the attacker may add query string parameters not
part of the whitelist, exploit additional client state like cookies,
exploit differences in url parsing between client, sever and browser,
etc., or perhaps the whitelist is only at the granularity of a server)
such that additional redirects are triggered from client.example.com to
evil.com?, 

The UA issues a request for https://client.example.com/cb, and in this
case gets a new 302 response with a redirect to evil.com, requests that,
and then applies the fragment to the resulting text/html resource.
Evil.com now has the access token.

What Andrey and I are suggesting is that the initial 302 being sent by the
OAuth authorization server could look like:

HTTP/1.1 302 Found
Location: 
https://client.example.com/cb#access_token=2YotnFZFEjr1zCsicMWpAA&state=xyz
&token_type=example&expires_in=3600
Fragment-Scope: same-origin

This would instruct the UA that the fragment is only intended for
client.example.com, and should be discarded if client.example.com replies
with another redirect to a different origin.

Note that server.example.com here is not returning a resource or
constructing a DOM, so there is no opportunity to apply parameters in the
fetch algorithm, nor to rely on media-type specific handling of fragments.
 There isn't really even an OAuth "protocol" here to fix - it's riding
entirely on top of HTTP semantics at this point.

For Facebook and other large OAuth providers, "client.example.com" is
really thousands or tens of thousands of different endpoints. These have
all kinds of various and sundry peculiarities, but one of the most common
is redirect behavior like this.  We would like to be able, in the role of
authorization server, enlist the assistance of the user agent to mitigate
many these vulnerabilities by providing additional information about how
to dispose of a sensitive fragment when chaining 3xx responses.

Brad Hill

---

From: Amos Jeffries <[email-masked]>
Date: Sun, 11 Jan 2015 15:26:03 +1300

> HTTP/1.1 302 Found Location: 

Bug 1) The use of Bearer / access_token in #fragment does not comply
with RFC 6750.

Only use as a query parameter is defined, and because of exactly this
type of security scoping problem. There are enough security problems
added just using them in query parameters (which *are* tied to the
client.example.com origin) without allowing the arbitrary un-tied use
that #fragment implies.

> 
> The fragment containing the access token is not sent with the
> subsequent HTTP request to client.example.com, but if
> client.example.com responds with text/html content, the user agent
> applies the fragment, which can be read by e.g. script in the DOM.

Which is explicitly the property difference between fragment and query
parameters.

Fragment is a form of URL-based cookie which persists between request
implictly and affects folowing traffic. Use of this type of storage
for OAuth tokens is explicitly forbidden by RFC 6750 section 5.3.

"Safeguard bearer tokens:  Client implementations MUST ensure that
      bearer tokens are not leaked to unintended parties, as they will
      be able to use them to gain access to protected resources.  This
      is the primary security consideration when using bearer tokens and
      underlies all the more specific recommendations that follow.
"
and

"Don't pass bearer tokens in page URLs:  Bearer tokens SHOULD NOT be
      passed in page URLs
"

What is the point of violating the OAuth Bearer specification by using
#fragment at all if you dont want its semantic properties?

> 
> The nature of OAuth and similar protocols is that the redirect
> location is passed in with the request (in this example, the
> redirect_uri paremeter). If that redirect_uri is maliciously
> modified, the server might send credentials to an incorrect host.
> The common mitigation to this is to whitelist the set of uris that
> server.example.com is willing to redirect to.
> 
> https://client.example.com/cb, what if there exists unknown
> processing logic at that endpoint (the attacker may add query
> string parameters not part of the whitelist, exploit additional
> client state like cookies, exploit differences in url parsing
> between client, sever and browser, etc., or perhaps the whitelist
> is only at the granularity of a server) such that additional
> redirects are triggered from client.example.com to evil.com?,

The use of #fragment explicitly opens the system to all of the top 3
security threats called out by OAuth Bearer spec:
 http://tools.ietf.org/html/rfc6750#section-5.1

OAuth (2.0 at least) is built on the assumption that there is *no*
malicious or intermediary processing interactions. If there are the
security of an entire OAuth Bearer system becomes null and void. This
is a well known property which has caused numerous long and bitter
arguments in the OAuth 2.0 WG.
(Please lets not go into all that in here, we have enough long threads
of our own and Erans' arguments about holes in the client processing
stacks are in the OAuth archive).

> 
> The UA issues a request for https://client.example.com/cb, and in
> this case gets a new 302 response with a redirect to evil.com,
> requests that, and then applies the fragment to the resulting
> text/html resource. Evil.com now has the access token.

Which is the behaviour explicitly imposed by the server when it opted
to use a custom #fragment style of transfer instead of the RFC 6750
defined ?query or the better options.

> 
> What Andrey and I are suggesting is that the initial 302 being sent
> by the OAuth authorization server could look like:
> 
> HTTP/1.1 302 Found Location: 
> client.example.com, and should be discarded if client.example.com
> replies with another redirect to a different origin.
> 

Whereas the OAuth 2.0 WG defined that it shall be:

 HTTP/1.1 302 Found
 Location:
 https://client.example.com/cb?access_token=2YotnFZFEjr1zCsicMWpAA&state=xyz
 &token_type=example&expires_in=3600

(sorry about the wrap)

Which explicitly
A) binds the access_token to the domain client.example.com, AND
B) ensures that no portion of it be stored and re-used by naive UA
process stacks on unrelated URLs even within the client.example.com
domain URL space.
C) only OAuth processing stack component(s) are explicitly coded to
persist the token between requests when implemented as per the OAuth spec.

> constructing a DOM, so there is no opportunity to apply parameters
> in the fetch algorithm, nor to rely on media-type specific handling
> of fragments. There isn't really even an OAuth "protocol" here to
> fix - it's riding entirely on top of HTTP semantics at this point.

FUD. A great many tools that use URI query parameters having nothing
to do with DOM in them. Lack of a DOM at either endpoint is no
justification for using #fragment over ?query. Quite the opposite,
lack of DOM makes it *easier* to use query parameters, as those
endpoints API often have direct access to the original URL string.

I recall that this was the explicit reason why query parameters were
left defined in RFC 6750 despite their known security impact. The
headers were not always avaiable to such tools even when the raw URL
string was.

> 
> For Facebook and other large OAuth providers, "client.example.com"
> is really thousands or tens of thousands of different endpoints.
> These have all kinds of various and sundry peculiarities, but one
> of the most common is redirect behavior like this.  We would like
> to be able, in the role of authorization server, enlist the
> assistance of the user agent to mitigate many these vulnerabilities
> by providing additional information about how to dispose of a
> sensitive fragment when chaining 3xx responses.

You would be able to mitigate many, many more of the security issues
by actually following the RFC 6750 specification behaviour.

That includes resolving or mitigating security issues interacting with
software which is not implementing your custom Fragment-Scope header.

Amos

---

From: Brad Hill <[email-masked]>
Date: Mon, 12 Jan 2015 18:56:01 +0000

Here's another attack using this same method used to compromise Weibo on
the way to attacking a bitcoin exchange this weekend:

http://sakurity.com/blog/2015/01/10/hacking-bitcoin-exchanger.html

---

From: Brad Hill <[email-masked]>
Date: Mon, 12 Jan 2015 18:55:20 +0000

Well, here's another attack, against Weibo and used to compromise a
Bitcoin exchange, that happened in the wild just this weekend: