Code phishing attack on OAuth 2.0 [RFC6749]

Code phishing attack is the attack that the adversary obtains the code and client credentials from the legitimate client and uses them against the honest token endpoint to obtain tokens thereby accessing the protected resources illegitimately.

Assumptions

There are not much assumptions needed for this attack.

  1. The client and the server uses OAuth 2.0 [RFC6749].
  2. The client developer is naive enough to be fooled by emails etc. (Compromised developer documentation.)

Attack Flow

There are several ways to achieve it but the simplest way to do it is to deceive the client developer and have them change the token endpoint to the one prepared by the adversary.

A sample attack would go like this in the case of unmodified RFC6749.

  1. The adversary send an email from spoofed legitimate address saying something like:Dear valued customer:
    We are proud to announce that we have cut over the new token endpoint with better security and features. We are going to deprecate the existing token endpoint in 6 months time. During the transition period, the old endpoint continue working, but we urge you to move to the new endpoint https://example.com/v2.0/token at the earliest convenience
  2. Believing the mail, the client developer changes the token endpoint to the bogus one.
  3. Since the authorization endpoint has not changed, it continues to work normally and returns code.
  4. The client sends the client credential and the obtained code to the “new” endpoint.
  5. The adversary now has the client credential and the code so that he can use it against the honest token endpoint to obtain tokens. The ATTACK SUCEEDS.

Mitigations

There can be a couple of mitigation strategies

  1. Make it illegal to use different authority for the Authorization endpoint and the Token endpoint. If they are different, the client MUST err. This does not involve wire protocol change.
  2. Tell the client where the code can be used authoritatively.  [OAuth Meta] Draft-sakimura-oauth-meta, which has been there since 20121 achieves it. Also, using the issuer returned in draft jones-oauth-mix-up, which came out Jan 2016 2 to discover the token endpoint would also work. Note, just comparing the issuer does not do the job. See below.

Mitigation by OAuth Meta

OAuth Meta is a simple spec. The primary design of it is to return the metadata associated with the response together with the response, e.g, return the endpoint uris as query parameter in the case of authorization response, and link header in the case of token response. Although it was not specifically designed to address this code phishing attack, it actually works.

  1. The adversary send an email from spoofed legitimate address saying something like:
    Dear valued customer:
    We are proud to announce that we have cut over the new token endpoint with better security and features. We are going to deprecate the existing token endpoint in 6 months time. During the transition period, the old endpoint continue working, but we urge you to move to the new endpoint https://example.com/v2.0/token at the earliest convenience
  2. Believing the mail, the client developer changes the token endpoint to the bogus one.
  3. Since the authorization endpoint has not changed, it continues to work normally and returns the code but with token endpoint uri, turi to the redirection uri. where the code is supposed to be sent.
  4. The client sends the client credential and the obtained code to turi.
  5. The ATTACK FAILS.

Why just comparing the issuer does not work?

This is a solution proposed by the participants of the Darmstadt seminar held in December 2016.

  1. The adversary send an email from spoofed legitimate address saying something like:
    Dear valued customer:
    We are proud to announce that we have cut over the new token endpoint with better security and features. We are going to deprecate the existing token endpoint in 6 months time. During the transition period, the old endpoint continue working, but we urge you to move to the new endpoint https://example.com/v2.0/token at the earliest convenience
  2. Believing the mail, the client developer changes the token endpoint to the bogus one.
  3. Since the authorization endpoint has not changed, it continues to work normally and returns code to the redirection uri. It returns the OAuth issuer string, which is the location of the discovery file truncated before .wellknown, and the client_id.
  4. The client checks the issuer string is the same as what it knew, and the client_id is the same as its client_id. They are the same, so the test passes. (Section 4.)
  5. The client sends the client credential, code, state, and redirect url to the “new” endpoint.
  6. The adversary now sends the obtained client credential, code, state, and redirect url to the honest token endpoint to obtain tokens. The ATTACK SUCEEDS. 

For this approach to work as a mitigation, you have to actually fetch the content of the discovery document and use the value included in it instead. If it were to be done every time, in case of Google, this approach requires over 1060 bytes. (The oauth-meta’s over head was only 61 bytes.) Also, it adds an extra round trip adding latency. Thus, it has to cache the payload of the discovery file.

Footnotes

  1. https://tools.ietf.org/html/draft-sakimura-oauth-meta-05
  2. http://tools.ietf.org/html/draft-jones-oauth-mix-up-mitigation-01

9 Replies to “Code phishing attack on OAuth 2.0 [RFC6749]”

  1. So, I learnt a new thing today. In many implementations, the AS does not know the list of token or resource endpoints.

    Apparently, there is a separation of logical resources represented by a scope and physical endpoints. A bearer token for a scope is good for use in any of those physical endpoints. If a new physical endpoint/service in a different internet domain pops up, it will be valid without the AS knowing it and the client can reuse it.

    This will make the oauth-meta like approach hard because the AS does not know where it can be used at.

    I actually doubt if this is true for token endpoints as well, but this is what I heard today. If that is the case, there is no hope in controlling the code or token phishing. Even by introducing the concept of issuer and discovery, the client is going to send it to wherever it wants, including the adversary. So, it does not help. What we can say in this case then perhaps is:
    – A client should not use multiple ASs;
    – If it does, use OpenID Connect with the flow that returns ID Token in the front channel.

    OTOH, if it is possible to write possible token endpoints in the discovery document, then the code phishing can be prevented by checking against the list before sending the code. However, this also means it can be done with OAuth-meta, which can be very dynamic unlike the discovery document which tends to be large.

    So, fundamentally, there is not much difference between the discovery document way and oauth-meta as long as IdP Mix-up attack is concerned.

    It is just that oauth-meta will potentially give more features such as privacy sensitive service discovery and the use of a specific token endpoint depending on the outcome of the authentication/authorization.

    1. That’s why I proposed what is now OAuth JAR/request object back in June 2010. Also, I have designed ID Token that acts as a detached signature to the code.

      In a way, OpenID Connect is a crypto layer over OAuth 2.0. I found a lengthy blog post in Japanese by a person who implemented full OpenID Connect and OAuth 2.0. He characterized OpenID Connect as not as compatible as you may think with OAuth 2.0, that one should think of it as OAuth 3.0.

  2. Another mitigation, for confidential clients, is to use JWT assertion authentication instead of basic (as permitted in OIDC). That way the credential would be bound to the bogus token endpoint, so the attacker cannot reuse it with the legitimate one. Being unable to authenticate to the legitimate token endpoint, the code becomes useless to the attacker.

    This should also work for the case where the AS doesn’t have a list of the token or RS endpoints.

    1. Yup.

      Actually, I was kind of expecting this kind of attack from the very beginning. That’s why I was proposing request and response signing through the use of request object and what is now ID Token back in 2010.

        1. And, I did not believe it 😉

          That’s why I proposed what is now OAuth JAR/request object back in June 2010. Also, I have designed ID Token that acts as a detached signature to the code.

          In a way, OpenID Connect is a crypto layer over OAuth 2.0. I found a lengthy blog post in Japanese by a person who implemented full OpenID Connect and OAuth 2.0. He characterized OpenID Connect as not as compatible as you may think with OAuth 2.0, that one should think of it as OAuth 3.0.

  3. Hi Nat! I’m doing a research of OpenID Connect for my Carreer Final Project and I have 2 ideas: The first is to add more functionality to OpenID by implementing a Two way authentication system, do you think it is possible? The another idea is to develop an OpenID version for other services that are not web, like SSH, FTP or another. I will apreciate your opinion. Thank you!

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.