Stephen Sclafani

CSRF Vulnerability in OAuth 2.0 Client Implementations

April 6th, 2011

OAuth 2.0 is the next generation of the OAuth protocol. OAuth 2.0 has been designed to make implementation simpler for both service providers and clients. Unfortunately, this simplification has led to the implementations of the majority of client websites to be vulnerable to cross-site request forgery.

Facebook

Facebook is currently the largest service provider using OAuth 2.0. Facebook offers OAuth 2.0 as an authentication option for its API. When a client website that has implemented the Facebook API authenticates a user using OAuth 2.0 the website redirects the user to an authorization URL on Facebook:

https://graph.facebook.com/oauth/authorize?client_id=...&redirect_uri=http://www.example.com/oauth_callback

The user is prompted by Facebook to login and authorize the website. If authorization is granted the user is redirected to the callback URL in the redirect_uri parameter along with a code:

http://www.example.com/oauth_redirect_script?code=...

The website can then exchange the code for an OAuth access token and use the token to make API requests on behalf of the user.

Unlike with OAuth 1.x where a request token is passed through the entire flow, there is nothing that ties the request to authorize with the returned code. An attacker can generate a code for their own Facebook account for a target website and can then get a victim to load the code in the website’s callback URL. If the victim is logged in, the website will automatically use the code to link the victim’s account to the attacker’s Facebook account. If the website has implemented Facebook as a secondary login option the attacker can then login to the victims account using Facebook.

I tested this attack against The New York Times, Photobucket, TripAdvisor, StackOverflow, Digg and Formspring all of which were vulnerable.

Mitigation

The OAuth 2.0 spec defines an optional “state” parameter which clients can use to maintain state between the authorization request and the callback. Clients can use this parameter to protect themselves against this attack by passing a unique-to-user nonce as the value of the parameter when redirecting a user:

https://graph.facebook.com/oauth/authorize?client_id=...&redirect_uri=http://www.example.com/oauth_redirect&state=...

The nonce is included with the code in callback if authorization is granted:

http://www.example.com/oauth_redirect?code=...&state=...

A client can then check if the nonce is valid and that it belongs to the logged in user before taking action.

Disclosure

Facebook was notified of this issue in January. Since being notified they have taken the following actions:

  • Notified major developers of the issue.
  • Added a section detailing the issue and the use of the “state” parameter for mitigation to their authentication documentation.
  • Began updating their SDKs to use the “state” parameter.

Beyond Facebook

While Facebook is the largest service provider using OAuth 2.0 this is not a Facebook specific issue. Any website that implements a third party service that uses OAuth 2.0 for authentication can be vulnerable to this attack. In addition to Facebook, members of the OAuth community were notified of this issue and discussion to add details of the issue to the OAuth 2.0 spec is ongoing.