Tuesday, April 05, 2011

A SHOULD is as good as a MUST to a fined AS

Recently, the IETG OAuth WG has spent MUCH time discussing whether a particular endpoint in the authorization dance SHOULD be SSL, or instead MUST be SSL. (where the SHOULD and MUST are interpreted as in RFC 2119).

The endpoint in question is that hosted by the OAuth Client, to which the Authorization Server (AS) redirects the user's browser after obtaining their consent for that Client accessing the services hosted by a Resource Server (RS). Typically, the Client would have previously provided the AS the appropriate endpoint when registering with that AS. Notwithstanding that, a Client may also supply a value for this endpoint when it send the user's browser to the AS asking for authorization - it serves as an additional check that the entity sending the authorization request is indeed a valid registered Client.

Importantly, is is by sending the browser to this client URL that the AS communicates an 'authorization code' to the Client - this code effectively a pointer to the more fundamental 'access token' that the Client ultimately desires - as it is the access token that the Client will include on its API calls to the RS. Once the Client obtains the authorization code - it sends it back to the AS in exchange for that desired access token.

The flow is shown below - the infamous endpoint is hilited. The exchange of the authorization code is shown in steps (D) and (E).

If this endpoint is not protected by SSL, then an attacker will be able to grab an authorization code issued for one user, and fool a good (in the 'not overtly evil' sense, no endorsement is intended) Client to exchange the stolen authorization code for an access token. The attacker ends up able to access the user's resources at the RS 'through' the good Client.
One version of the full attack looks like
  1. Evil Brian starts dance at good Client & good AS
  2. AS redirects Brian's browser to (non-SSL protected Http) Client redirect endpoint, contains an authz code
  3. Brian stops the (HTTP) redirect containing his authz code
  4. Brian waits for unsuspecting Good Paul to walk into Starbucks
  5. Good Paul starts dance at good Client & good AS (the same ones as for Brian)
  6. Brian intercepts the (non-SSL protected Http) redirect containing Paul's authz code
  7. Brian takes Paul's authz code from #6 and inserts it in URI from #3
  8. Brian sends his browser to new redirect URI from #7
  9. Client extracts substituted authz code and exchanges it for access token with AS
  10. Client associates access token with evil Brian's account but AS associated it with Paul's
  11. Brian can access Paul's stuff through Client
If the Client endpoint is protected by SSL, then Evil Brian (I do like the sound of that) can't do his evil magic of substituting Paul's authz code for his own - and the attack is prevented.

Everybody in the OAuth WG seems to agree on the reality of the attack and that SSL mitigates it.

Consequently, were the OAuth specification to mandate that Client implementations and deployments MUST protect this endpoint with SSL - then the attack is prevented. There are some in the OAuth WG who advocate this - arguing that the specification has a duty to turn up the security knobs and prevent clearly recognized attacks against the protocol.

Others in the WG, (generally the major social providers), looking at the reality of the Clients that will be interacting with the ASs they will host, argue that, while MUST may be desirable, it is impractical for their  Clients (for which setting up SSL is claimed to be either too onerous, too expensive, or both). Consequently, they argue that making SSL protection a MUST will serve to only cause them to break compliance with the specification. As they don't want to be out of compliance with the spec (but they are willing to do so if necessary), these WG members argue that making SSL protection a SHOULD, along with appropriate text about risks of not using SSL, is the right choice - because it achieves the same security protection (namely that those Clients who will use SSL will indeed use it, while those who wont wont) without forcing the latter group out of compliance.

Notwithstanding new twists (like rants along the lines of 'you new kids are wrecking the game!!!!' ), this MUST/SHOULD SSL issue reflects the familiar tension between security & deployment realities that security standards always face - dialing the knobs up to 11 would be nice, but many folk's amps stop at 10 (or lower).

The Facebooks et al have indicated that, regardless of what the spec stipulates, they won't enforce a MUST, ie they will happily (well perhaps not happily, but they'll do it nonetheless) send the browser to an HTTP redirect endpoint at a Client (nor would they reject an HTTP endpoint at Client registration time). Ultimately, this is the Facebook AS making a security policy decision for the Facebook RSs - measuring the risk of the attack and making the call that to not mandate SSL is acceptable. The position is arguably defensible given the nature of the data and services currently sitting behind facebook RSs (e.g. cute bunny photos etc).

Facebook's position can be summed up as:

Make it MUST in the spec if you really need to, but we are going to interpret it as a SHOULD

The flip side to this model is likely going to be more relevant for an enterprise running an OAuth AS for its RS APIs. This 'enterprise-centric' flip side is:

Make it SHOULD in the spec if you really need to, but we are going to interpret it as a MUST

In other words, even if the OAuth specification doesnt mandate that the client endpoint be protected with SSL (ie the spec has a SHOULD), an AS is still completely free to reject Client endpoints that arent protected by SSL - either at registration time or by refusing to send the browser to such an endpoint. Just as the Facebooks of the consumer world can make their own policy decision regarding how they want their Client endpoint's secured (SSL or not), an AS hosted by an enterprise can make its own decision - in the direction of greater overall security by interpreting the spec's SHOULD as a MUST.

It's likely that an Enterprise would somehow and eventually pay a financial cost for a breach to their API security (e.g. perhaps they would be 'fined' were this to happen). The moral of this essay can therefore be summarized as follows:

A SHOULD is as good as a MUST to a fined AS.

Sorry about that.


Unknown said...

This is webserver flow not native mobile app as client myapp://state=bored&code=icannotbearit

Paul Madsen said...

Axel, sure. With a custom scheme like that, the fact that you are bored to tears with the current discussion need not leak

Anonymous said...

Great Post. Facebook's position is something seriously to worry about though. What good is a spec if one is free to interpret widely accepted notion of "MUST" as "SHOULD".

Is this a message for vendors to implement the way they want and still call it "OAuth".

As for specific client's incapability to add SSL and chances of EvilBrian appearing in that environment are zero, why not create a separate profile ? Aren't profiles meant for this so that there are no interop issues.