4

Please find here described an OAuth2 session fixation attack. Is the attack possible? And am I understanding correctly how it can be stopped?

The attack

Mallory starts logging in at client.example.com via a certain OpenAuth2 provider, but just after the provider has sent the authorization response (https://www.rfc-editor.org/rfc/rfc6749#section-4.1.2) Mallory closes the browser and thus stops the OAuth2 login flow. However before closing the browser he remembers the Location value in the status 302 Found response from the provider:

HTTP/1.1 302 Found
Location: https://client.example.com/oauth-callback?code=12345&state=xyzw

Now Mallory configures an evil web server to reply status 302 Found with the above Location header. He sends an email to Alice and says: "Hi look at this cool page at Client.Example.Com" with a link to his evil web server. Alice follows the link and is redirected to client.example.com with Mallory's OAuth2 code (i.e. 12345). client.example.com continues the authentication flow: it sends the OAuth2 code to the OAuth2 provider and gets back an access token.

The result is that Alice is logged in to an account that Mallory controls. Alice doesn't realize this though, and she makes a purchase via Client.Example.Com. Client.Example.Com remembers her credit card number, which Mallory gets access to later by logging in to the account and checking the account history.

Preventing the attack

OAuth2 doesn't allow reusing the same authorization code (12345) more than once (see the RFC linked above), but since Mallory closed the browser in the middle of the login flow, the auth code isn't used more than once.

In section 10.12 in the RFC it's mentioned that CSRF attacks can be stopped via the OAuth2 state param (xyzw in this example). However, Mallory copies the state param too, so it's likely to be a valid state, if the state is e.g. just a randomly generated nounce. And when Alice follows Mallory's evil link, client.example.com hasn't seen anyone use that particular state before, so client.exampel.com is likely to accept it.

The RFC says that the state should be "e.g. a hash of the session cookie used to authenticate the user-agent". Is that the key to how to prevent this type of attack? Alice would have a session cookie at client.example.com, and the state would be required to be hashWithSha1(the-session-cookie-value)? Mallory's state=xyzw would then be incompatible with Alice's session cookie, hence client.example.com would realize that something was amiss with the redirection from Mallory's evil server?

(Exactly what would you suggest as state? Would simply hashWithSha1(the-session-cookie-value) be safe?)

KajMagnus
  • 687
  • 1
  • 5
  • 10

2 Answers2

2

Reading https://www.rfc-editor.org/rfc/rfc6749#section-4.1.1, this is what I interpret:

The client (in this case, the server with an account that Mallory is fixating) directs the user-agent to an OAuth request. state has been determined by the client, and is passed with the request, and will be passed back when the user-agent is sent to redirect_uri with an authorization decision. What the recommendation you quote is assuming is that each user-agent has a session tied to it, and that the state can either be calculated from that session identifier (hashWithSha1(the-session-cookie-value)), or is stored in a way that is keyed to that session identifier (for example, a session[:oauth_request_state] value on a Ruby On Rails server, that might be set to some nonce). Mallory, with her own session, will cause a different state value to be passed than Alice's interaction with the client will expect, and this will cause the auth to fail.

Please insert here all the usual caveats about believing people on the internet, and may anyone swiftly correct me if I am wrong.

A. Wilson
  • 121
  • 6
1

SHA(auth-session-cookie) is only useful if the underlying value of auth-session-cookie is itself sufficiently large and random.

Also auth-session-cookie should be short lived (eg. 2 minutes), so state isn't valid indefinitely to reduce the risk of replay attacks.