Authorization Request Leaks lead to CSRF

Issue #534 resolved
Daniel Fett created an issue

My take on this:

  • This kind of CSRF can happen in all redirect-based flows unless there would be browser features used that guarantee source and destination of redirects.

    • Solutions with postMessage are conceivable, but complicated and AFAIK not used anywhere
    • Token binding would have been another solution.
  • We should document and explain the attack

  • For the analysis: Accept that if authorization request leaks, session integrity is broken.
  • Also: Breaking session integrity is usually not the worst kind of attacks - but it depends on the use case. If a user uploads documents into the wrong account, or sends money into the wrong account, the results can be bad.

Comments (17)

  1. Pieter Kasselman

    In addition to explaining the attack (with examples - the document upload scenario helps make the attack’s impact real), we should provide guidance on the mitigations (e.g. if DPoP with fresh nonces on every transaction would prevent this, the system owner may consider it and trade it against the latency and performance impacts).

  2. Daniel Fett reporter

    There are unfortunately no practical mitigations right now. As I mentioned above, some postMessage shenanigans could help in theory, but would require major changes in the authz request plus some iframes or similar (risk of being blocked by tracking preventions).

  3. Tom Jones

    I don't understand the problem at all. OAuth2 Authz request state is designed to block xrss. Why not now? You might need to explain that the state variable would need to contain an encrypted value that would block this attack, but that’s what most of us do already.

  4. Brian Campbell

    I could be misunderstanding (as usual) but it seems like there’s maybe an important distinction between reading the authz request due to some leakage and fully intercepting it. Seems like this attack wouldn’t work when the authz request only leaks to an attacker but still continues for the legit user because the request_uri value from PAR is supposed to be one-time use. Looking again at PAR, I see that one-time use is a SHOULD rather than MUST. So that’s not 100%. But other one-time things like code would come into play too.

    I dunno, I do agree that the risk is acceptable on this one. But I feel like it’s more subtle than “if authorization request leaks, session integrity is broken.” and maybe any documenting and explaining the attack that’s done could/should also capture the subtleties, especially for situations when it’s even less severe.

  5. Dave Tonge

    suggested text

    Authorization Request Leaks lead to CSRF

    An attacker of type A3a (see [@attackermodel]) can intercept an authorization request, log in at the Authorization Server, receive an authorization code and redirect the honest user via a CSRF attack to the honest client but with the attacker’s authorization code. This results in the user accessing the attackers resources, thus breaking session integrity.

    Possible mitigations for this are:

    1. Requiring the Authorization Server to only accept a request_uri once. This will prevent attacks where the attacker was able to read the authorization request, but not block the honest user’s flow.
    2. Requiring the Client to only submit a PKCE code_verifier once. This will prevent attacks where the attacker was unable to block the honest user’s flow.
    3. Reducing the lifetime of the authorization code - this will reduce the window in which the CSRF attack has to be performed.

    It is important to note that all redirect based flows are susceptible to this attack, however it requires a strong attacker who can read authorization requests, block the honest user flow and perform a CSRF attack in a short time window.

  6. Joseph Heenan

    As per discussions on today’s call, suggest rewording ‘2' to something along the lines of 'the client must only make one token endpoint call for each authorization endpoint calls’ (which leaves open various other mechanisms for achieving it than PKCE).

  7. Tim Würtele

    Quoting Daniel here:

    For the analysis: Accept that if authorization request leaks, session integrity is broken.

    This would require us to either:

    1. change the model such that authorization requests do not leak (at least to prove session integrity, but it seems very odd to use slightly different models to prove different security properties), or
    2. formulate the session integrity property such that it excludes cases in which the corresponding authorization request leaked (still requires a slight change to the model as we currently assume that all authZ requests leak).

    I would prefer option 2 as it makes this exclusion very explicit (albeit making the property harder to formally define) and allows us to prove other properties even if the authorization request leaks.

  8. Nat Sakimura

    The protocol, as it is presented now, violates BCM Principles.

    P1  Positional tagging. Cryptographic message components should contain information that uniquely identifies their origin. In particular, the information should identify the protocol, the protocol variant, the message number, and the particular position within the message from which the component was sent.

    P2 Inclusion of identities and their roles. Each cryptographic message component should include information about the identities of all the agents involved in the protocol run and their roles unless there is a compelling reason to do otherwise.

    Paraphrased, a message in a cryptographic authentication protocol should have:

    1. Unique Source Identifier (that is verifiable);
    2. Protocol + version + message identifier;
    3. Full list of actors (and their roles)

    in it.

    In the current protocol, the browser, which is one of the main actors, is not fully identified and it is not listed in the protocol message whether directly or indirectly. Back in the beginning of FAPI 1.0, we were looking forward to having TB for this purpose, but history has taken an unexpected turn, and we lost it, unfortunately.

    Now several questions to browser experts:

    Q1. If I am not mistaken, there is no fundamentally easy way to identify a browser right now, or is there one? If there is, the attack can be prevented.

    Q2. Is there a way for a browser to tell if the redirect was initiated by the honest authorization server or if the redirect was a result of clicking on a link in an email or some other site. If there is a way to tell that the “redirect” is not the result of visiting the honest authorization server, we can make the “CSRF” red arrow in the figure fail.

    Q3. Is there a way for an honest browser to find out if there was an interaction at the honest authorization server?

    Q4. Would it be possible to include the user identifier in the initial PAR request? If so, the Attacker’s authentication attempt would fail as the attacker does not have a corresponding credential. (NOTE: it could be a random value submitted by the user (user interaction ticket) as well. Then, the user is asked to input the value at the user authentication time.)

    Q5. Would a decoupled authentication could help?

  9. Daniel Fett reporter

    For Q1 to Q3, this cannot be easily done with a redirect:

    • There is of course the referer header with its infamous typo, which however is often blocked for privacy reasons.
    • Then there is the origin header which in most contexts is not sent to the redirection target for regular redirects. Browser support is not always given. Both headers also exclude most forms of JavaScript-based redirections. There is a newer set of headers, the sec-fetch- family, but these headers don’t expose the redirection origin.
    • The (now-dead) TLS Token Binding provided features for identying the source of a redirect reliably, but, alas, is dead now.
    • I think the postMessage mechanism (cross-document messaging) comes somewhat close, it allows for idenfication of the sender and receiver of a message (as long as the browser is not compromised). The drawback is, however, that postMessage requires two documents open at the same time, one from the AS and one from the client, for example using an iframe or a pop-up window. This would require a different user flow for many implementers. It would be interesting to spec this out to see if it can work, but I don’t see it as something we could recommend or even mandate right now.

    Q4: Certainly doable, but attackers might trick users into typing certain numbers or similar.

    Q5: I don’t think so, decoupled flows have the same problem.

  10. Log in to comment