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?)