[BIS] Clarify attacker model (PKCE method and CSRF protection)

Issue #220 resolved
Nat Sakimura created an issue

Opening another ticket for #175 to close the original issue while #175 can talk about app2app security models, etc.

The Read-Only profile of the FAPI requires the use of PKCE (Section 5.2.2, Number 7 of Draft-05). While there are two code challenge methods defined in PKCE (either "plain" or "S256"), the FAPI requires the use of "S256", where the underlying assumption is that the authorization request leaks due to "leaking http log information in the OS" (Pre-Condition 4b of RFC 7636).

Does the FAPI aim to protect against authorization request leaks?

If yes, then how is the leakage of the state value contained in the authorization request mitigated? As described in OAuth (Section 4.1.1 of RFC 6749), the state value should be used for preventing CSRF attacks.

In Section 5.2.3 of the Read-Only profile of the FAPI, the client is required to "implement an effective CSRF protection". How can this be achieved in a way suitable for all configurations, e.g., also for native app clients, when assuming that the authorization request leaks?

If no (i.e., PKCE is only used for code-injection protection), then why is the more complex S256 chosen, where the plain method would work fine?

Comments (20)

  1. Nat Sakimura reporter

    Just starting with the genesis of PKCE being in the RO spec.

    The primary case we had in mind was the case where the client is an app on a smartphone and where the AS is on the Web. The attack we had in mind is the access token capturing by a malicious app on the same smartphone. That's the original use-case for PKCE.

  2. Nat Sakimura reporter

    Why FAPI RO Spec uses S256? Because RFC7636 says "The "plain" method SHOULD NOT be used in new implementations, unless they cannot support "S256" for some technical reason." in section 7.2 of RFC7636. So, it is not really FAPI that made the decision but it was just following RFC7636.

    The attacker model behind S256 code_challenge method is written in the Introduction. In particular, what is pertinent to the question here is bullet point

    4. Either one of the following condition is met:
    
          4a. The attacker (via the installed application) is able to
              observe only the responses from the authorization endpoint.
              When "code_challenge_method" value is "plain", only this
              attack is mitigated.
    
         4b. A more sophisticated attack scenario allows the attacker to
              observe requests (in addition to responses) to the
              authorization endpoint.  The attacker is, however, not able to
              act as a man in the middle.  This was caused by leaking http
              log information in the OS.  To mitigate this,
              "code_challenge_method" value must be set either to "S256" or
              a value defined by a cryptographically secure
              "code_challenge_method" extension.
    

    So, it assumes that the attacker cannot rewrite the request nor the response, of which the later is the pre-requisite for the code injection attack.

    NOTE: RW spec assumes that the attacker can tamper the request and the response: i.e., it assumes a stronger attacker.

  3. Nat Sakimura reporter

    Re: CSRF protection.

    To be honest, the CSRF protection and the choice of S256 in PKCE was an independent decision, the former one just following what RFC6749 requires and the later one merely following what RFC7636 requires.

    Having said that, let us consider for a moment what could we do as a CSRF protection when the CSRF token leaks when the attacker is as modelled in RFC7636, i.e., can observe but not man-in-the-middle.

    Attack scenario is such that the attacker forges a link to the redirect_uri with a CRSF token that he has observed elsewhere and sends it to potential victims. Then, one of the victims clicks on the link and initiates a call to the request_uri.

    Case 1: The victim is not the original sender

    The attack does not succeed as the CSRF token that the client expects does not match the received CSRF token value.

    Case 2: The victim is the original sender

    Since the attacker is not a man-in-the-middle, he cannot replay the authorization response to the honest client as that would constitute a man-in-the-middle.

    So, it appears that to launch a successful CSRF attack using the observed CSRF token, the attacker has to be stronger and has to be a man-in-the-middle, which is to be dealt with the R+W spec.

  4. Nat Sakimura reporter

    Now, Part 1 5.2.2-20 says

    shall require redirect URIs to use the https scheme;
    

    This implies that the custom scheme is banned and only claimed https url can be used. Is PKCE relevant then?

    The answer is yes. The claimed https url is vetted at the app stores in the respective operating system but there have been successful attacks against it to circumvent the check. So, the implied attacker capability here is that the attacker can circumvent the app store checks on the claimed https url.

  5. Joseph Heenan

    The claimed https url is vetted at the app stores in the respective operating system

    I'm not sure how this works on Android, but on iOS I believe that's not quite true - the claimed url validation is done on device, with the devices fetching the site associations from the website being claimed (e.g. http://itison.com/.well-known/apple-app-site-association ), and that file must list the id of the app that is trying to claim. I'm not sure if the App Store does additional checks.

  6. Nat Sakimura reporter

    You are right. Not so good to write these things 3 AM in the morning. I thought an incident like that happened before but I probably am confusing with something else.

  7. Dave Tonge

    From my understanding this attack is about "session swapping" and I think that with the assumption that either the auth request or response leaks, there is a vulnerability.

    This paper describes the attack: https://arxiv.org/pdf/1901.11520.pdf

    This is a sequence diagram showing the attack:

    Screenshot 2019-03-29 at 06.17.56.png

    While PKCE may protect a malicious app from getting an access token for an honest user, it does not prevent an attacker tricking an end-user into obtaining an access token for an attacker.

    This is also called "Session Spying" in the Device Flow.

    The authors of the paper say that OAUTB prevents the attack, but any other mitigation would be much harder.

    There are some things we could do to make the attack much less likely:

    mandate that state values are one-time use

    draft-ietf-oauth-security-topics says: Clients MUST prevent CSRF and ensure that each authorization response is only accepted once. One-time use CSRF tokens carried in the "state" parameter, which are securely bound to the user agent, SHOULD be used for that purpose.

    This means that an attacker who observes an auth response is unlikely to be able to mount the attack.

  8. Dave Tonge

    We have this line in FAPI1 for Clients:
    shall implement an effective CSRF protection

    I suggest that we expand on this to say something similar to OAuth Security Topics, e.g.

    shall prevent CSRF and ensure that each authorization response is only accepted once. One-time use CSRF tokens carried in the "state" parameter, which are securely bound to the user agent, shall be used for that purpose.

    I don’t think we should put a requirement in the AS to enforce this, I think it should just be for the Client.

    The testing suite could try and load the same auth response multiple times?

    Should we refer to OAuth Security Topics here (or maybe just refer to it in the introduction).

  9. Dave Tonge

    Opening another ticket for #175 to close the original issue while #175 can talk about app2app security models, etc.

    The Read-Only profile of the FAPI requires the use of PKCE (Section 5.2.2, Number 7 of Draft-05). While there are two code challenge methods defined in PKCE (either "plain" or "S256"), the FAPI requires the use of "S256", where the underlying assumption is that the authorization request leaks due to "leaking http log information in the OS" (Pre-Condition 4b of RFC 7636).

    Does the FAPI aim to protect against authorization request leaks?

    If yes, then how is the leakage of the state value contained in the authorization request mitigated? As described in OAuth (Section 4.1.1 of RFC 6749), the state value should be used for preventing CSRF attacks.

    In Section 5.2.3 of the Read-Only profile of the FAPI, the client is required to "implement an effective CSRF protection". How can this be achieved in a way suitable for all configurations, e.g., also for native app clients, when assuming that the authorization request leaks?

    If no (i.e., PKCE is only used for code-injection protection), then why is the more complex S256 chosen, where the plain method would work fine?

  10. gffletch

    Not sure the state of this issue but it appears open:)

    For me, the CSRF token should be an encrypted value written into the browser by the client. The value in the state parameter should be a function of a value in the encrypted CSRF token.

    Using this mechanism would defeat the attack described because the Attack would not be able to encrypt the CSRF token without first compromising the Client’s private key.

    The client could also maintain state for the CSRF value so that it doesn’t rely on just a cookie value which could be injected by the attacker. If the client hasn’t issued the CSRF token, then it isn’t valid.

    Are there specific use cases where the above doesn’t work? Should there be best practice guidance on CSRF protections with OIDC/OAuth2?

  11. Log in to comment