Take the 2-minute tour ×
Information Security Stack Exchange is a question and answer site for Information security professionals. It's 100% free, no registration required.

http://tools.ietf.org/html/draft-ietf-oauth-v2-30#section-10.12 says:

The client MUST implement CSRF protection [...] typically accomplished by requiring any request sent to the redirection URI endpoint to include a value that binds the request to the user-agent's authenticated state (e.g. a hash of the session cookie [...]

It doesn't say much about the implementation, though. It only puts some light on how the CSRF works:

A CSRF attack against the client's redirection URI allows an attacker to inject their own authorization code or access token, which can result in the client using an access token associated with the attacker's protected resources rather than the victim's (e.g. save the victim's bank account information to a protected resource controlled by the attacker)

But use of the word "rather" rather makes the statement worthless.

I am thinking how to implement the "state" in GAE (using Webapp2). It would be easiest starting at how a hacker could use a CSRF against OAuth2. I found only one good article about the matter: http://blog.springsource.org/2011/11/30/10317/

Unfortunately, while this blog post is well written, there's not much info beyond OAuth2 process explained, examples don't work, and I don't know Spring. Still, I found one interesting recommendation there: server connecting to OAuth2 provider, should store "state" as a random session key (e.g. "this_is_the_random_state":"this_doesn't_matter"), not a value under static key (e.g. "state":"random_state_string")


My question is, what's the sane implementation of the "state".

  • Should the randomly generated state be hashed or can same value be stored and sent to OAuth2 provider?
  • Is there a difference here, if session back-end is secure-cookies or a server-side storage (in GAE Memcache or database)?
  • Should state be stored as a key as suggested?
  • Should state has validity period, or session (if there is one) lifetime is enough?
share|improve this question

2 Answers 2

up vote 3 down vote accepted
+50

I will simplify this problem. Cross-Site Request Forgery and Clikjacking attacks are useful because it can force a victim's browser into performing actions against the user's will.

The mention of 10.12. Cross-Site Request Forgery and 10.13. Clickjacking in the OAuth v2 RFC have fundamentally the same concern. If an attacker can force a victim's browser into authenticating, the it is a useful step in forcing the victim's browser into performing other actions.

   in a clickjacking attack, an attacker registers a legitimate client
   and then constructs a malicious site in which it loads the
   authorization server's authorization endpoint web page in a
   transparent iframe overlaid on top of a set of dummy buttons, which
   are carefully constructed to be placed directly under important
   buttons on the authorization page.  When an end-user clicks a
   misleading visible button, the end-user is actually clicking an
   invisible button on the authorization page (such as an "Authorize"
   button).  This allows an attacker to trick a resource owner into
   granting its client access without their knowledge.

Source:10.13. Clickjacking

For example, StackOverflow uses OAuth and is vulnerable to this attack. If you visit StackOverflow and you are currently logged into your OAuth provider you will be automatically logged in to StackOverflow. Therefor an attacker could automatically login a victim by loading stackoveflow within an iframe. If StackOverflow also had a CSRF vulnerability (and it has had them!). Then an attacker could automatically authenticate a victim's browser and carry out a CSRF (Session Riding) or Clickjacking or XSS attack against StackOverflow.com in a Chained Attack.

share|improve this answer
    
Thanks. I've done such XSRF (CSRF) attacks (e.g. I sent a link to my friend that made him delete a post on his forum), and I imagine an attack where someone gives you a login URL to a site, where you login as him (victim logs in on attacker's account). It's quite easy to protect against such attack (store state in session), but aren't there more complex hacking techniques than that? –  Markus von Broady Oct 2 '12 at 17:31
    
@Markus von Broady Clickjacking, Chaining and XSS is really as complex as attacks get for this RFC violation. There is really no other point in establishing a session for a victim unless you plan on riding on it with other attacks. If you had an XSS vulnerability in SO, this would be a pretty clean account hijack, which is nasty. –  Rook Oct 2 '12 at 17:56

Let's walk through how this attack works.

The Attack

  1. I visit some client's website and start the process of authorizing that client to access some service provider using OAuth

  2. The client asks the service provider for permission to request access on my behalf, which is granted

  3. I am redirected to the service provider's website, where I would normally enter my username/password in order to authorize access

  4. Instead, I trap/prevent this request and save its URL

  5. I somehow get you to visit that URL instead. If you are logged-in to the service provider with your own account, then your credentials will be used to issue an authorization code

  6. The authorization code is exchanged for an access token

  7. Now my account on the client is authorized to access your account on the service provider

So, how do we prevent this using the state parameter?

Prevention

  1. The client should create a value that is somehow based on the original user's account (a hash of the user's session key, for example). It doesn't matter what it is as long as it's unique and generated using some private information about the original user.

  2. This value is passed to the service provider in the redirect from step three above

  3. Now, I get you to visit the URL I saved (step five above)

  4. The authorization code is issued and sent back to the client in your session along with the state parameter

  5. The client generates a state value based on your session information and compares it to the state value that was sent back from the authorization request to the service provider. This value does not match the state parameter on the request, because that state value was generated based on my session information, so it is rejected.

Your Questions

  • Should the randomly generated state be hashed or can same value be stored and sent to OAuth2 provider?

The point is that the attacker should not be able to generate a state value that is specific to a given user. It should be unguessable.

  • Is there a difference here, if session back-end is secure-cookies or a server-side storage (in GAE Memcache or database)?

I don't think this matters (if I understand you correctly)

  • Should state be stored as a key as suggested?

I don't know what this means.

  • Should state has validity period, or session (if there is one) lifetime is enough?

Yes, state should have an expiration. It doesn't necessarily have to be tied to the session, but it could be.

share|improve this answer
    
From what I read, the state should be generated randomly. You suggest something opposite - to generate it from user data. I also don't understand why the hash should be unique - how do one enforce the uniqueness of a hash? –  Markus von Broady May 15 at 16:14
    
It depends on what you mean by random. The client must be able to generate the state for a user and then independently re-create that state later, so that it can compare the two. If it's just random, then how would you compare the them? Also, the reason to generate it from user data is that we're trying to identify a user. –  lwburk May 15 at 16:16
    
I don't recreate it, I store it on the server. –  Markus von Broady May 15 at 16:19
    
Why? What are you using the state for? It sounds like you don't even know why you're doing it. The scenario I'm describing requires that you re-create the state. That's the whole point. The client receives a state value that only it can create, so it creates it and then compares what it has created to what was passed in. If they match, then this must be the person for which the original state was generated. –  lwburk May 15 at 16:21
    
I actually use a framework, that saves the state, but I wondered if it's right, hence the question. I also have read some articles about state, and if I remember well, they all showed an implementation that saved state on server. If the state should be recreated on client and server side both, then the hashing algorithm would be known, so all a hacker would need to get is the data that is hashed. –  Markus von Broady May 15 at 16:37

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.