Please find here described an OAuth2 session fixation attack. Is the attack possible? And am I understanding correctly how it can be stopped?
Mallory starts logging in at
client.example.com via a certain OpenAuth2 provider, but just after the provider has sent the authorization response (https://tools.ietf.org/html/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.
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
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?)