Wallet Presentation Response Mixup
After receiving a presentation, the verifier sends back a 200 response according to "8.2. Response Mode "direct_post"":
If the Response URI has successfully processed the Authorization Response or Authorization Error Response, it MUST respond with an HTTP status code of 200 with Content-Type of application/json and a JSON object in the response body.
Two remarks can be given at this position:
- Consider a wallet that has 2 protocol runs with the same verifier. The wallet (or browser, in the case of relayed requests) can use the same TLS session to communicate with the verifier for both requests. When the verifier returns a response (accepting or declining the authorization response) to any one of the requests, an attacker in control of the network can redirect it to or reuse it for any request using that same TLS session. A real-world example is the user choosing the wrong credential for the presentation, then returning to the credential selection page, and sending a second Authorization Response.
- Possible Mitigations: Introducing presentation tokens/nonces: freshly generated tokens/nonces are sent along with the (verifiable) presentation and must be returned by the verifier's response to the Authorization Response request. Adding session restrictions: add a requirement stating that the verifier may only accept one Authorization Response per session.
- (lesser important) The mention of a mandatory response, to confirm the receiving and successful validation of the (verifiable) presentation, is missing outside the scope of "Response mode: direct post"
When the verifier returns a response (accepting or declining the authorization response) to any one of the requests, an attacker in control of the network can redirect it to or reuse it for any request using that same TLS session.
It feels like there's some part of your thinking that you've not fully explained here, as that doesn't sound like a problem. An attacker in control of the network also could have redirected/reused that request even if there was only one request/response, and the key problem there is that the attacker is in control of the network?
A real-world example is the user choosing the wrong credential for the presentation, then returning to the credential selection page, and sending a second Authorization Response.
I'm struggling to follow this, there's not an attacker mentioned in that example, and a "this allows the attacker to achieve
In general: The credential request sent from the verifier to the wallet is considered single use and contains a nonce; the verifier needs to check the nonce corresponds to the user session it was trying to get a credential in and (at least for the higher security cases like HAIP) that the nonce is bound to the session the user is sent to by the wallet after the direct post completes.
The credential request sent from the verifier to the wallet is considered single use and contains a nonce; the verifier needs to check the nonce corresponds to the user session it was trying to get a credential in and (at least for the higher security cases like HAIP) that the nonce is bound to the session the user is sent to by the wallet after the direct post completes.
Yes, the verifier’s credential request is protected by a nonce, ensuring freshness and preventing an attacker from forging requests. The "vulnerability" comes from the response sent back to the wallet, once the verifier has approved or denied the authentication. The protocol only mandates that the verifier return a 200-Response, without specifying further protections.
I have slightly changed to example with some additional details: consider an end-user choosing the wrong credential for an authorization request by a verifier. After realizing their mistake, they return to a credential selection page and send a second Authorization Response with a different credential. The verifier may deny the first request but accept the second. If the wallet (or a relaying browser) uses the same TLS session for both requests, a network attacker could block the successful response while duplicating the response denying access. As a result, the wallet receives only denial responses, creating a mismatch between the wallet’s state and the verifier’s actual decision.
An attacker with that level of control of the network could always cause a state mismatch though?
creating a mismatch between the wallet’s state and the verifier’s actual decision.
The verifier's decision at this point is not fully formed though - the response here really only indicates "the response was correctly formed". Any returned credential hasn't been bound to the user session yet (at least if you're following HAIP and hence requiring a redirect from the wallet to the verifier as the next step), so the response to the direct post can't indicate if the credential is actually acceptable for the intended purpose or not, as in many cases the verifier won't know if someone is attempting a phishing attack until later in the flow.
Thank you for the reply. I have rechecked with the contents of oid4vp v1.0.
These are the following relevant passages:
If the Response URI has successfully processed the Authorization Response or Authorization Error Response, it MUST respond with an HTTP status code of 200 with Content-Type of application/json and a JSON object in the response body. [2. Response Mode "direct_post"]
redirect_uri:[...] It can be used by the Verifier to prevent session fixation (Section 14.2) attacks. The Response URI MAY return the redirect_uri parameter in response to successful Authorization Responses or for Error Responses. [2. Response Mode "direct_post"]
access_denied:The Wallet did not have the requested Credentials to satisfy the Authorization Request. The End-User did not give consent to share the requested Credentials with the Verifier. The Wallet failed to authenticate the End-User. [8.5. Error Response]
The wording "successfully processed" in the first excerpt can be interpreted both ways: either
- the verifier has received and verified the authorization, and the authorization response signifies permission or denial, or (my statement)
- the verifier notifies the wallet of the correct processing of the credentials. (your statement)
I can see both assumptions holding, given the context and some interpretation. To support (1), the verifier is not required (unless using HAIP) to return the redirect URI (see second excerpt). This means that without HAIP, the Authorization Response does equate to the verifier having finished processing and validating the (verifiable) presentation. This then opens the described session fixation attack, as well as the attack described above in this issue. Furthermore, the third excerpt poses an access denial response as a possibility. The counterargument would imply that if the request is successful (with code 200), then none of the error codes, including this denial, would be applicable.
An approach to resolving this misinterpretation would be to make the verifier's response transparent to the wallet. An example can be with codes such as 102 Processing or 202 Accepted if the final validation is outstanding, instead of a generic 200 OK.
the verifier notifies the wallet of the correct processing of the credentials. (your statement)
I didn't go that far - the 200 response from the verifier to the wallet just indicates the verifier received a well formed response and was able to do whatever it wanted to do with it. The verifier could sensibly just store the response and decide not to even decrypt the response till it has done the session fixation check - this might even be a likely result for encrypted requests as it makes getting hold of the decryption key easier if you delay I think.
But anyway, I also think some confusion has arisen.
https://openid.net/specs/openid-4-verifiable-presentations-1_0.html#section-8.2 doesn't really define any error response from the direct post endpoint, only a successful response.
The errors in https://openid.net/specs/openid-4-verifiable-presentations-1_0.html#section-8.5 are errors that are sent from the wallet to the verifier.
An approach to resolving this misinterpretation would be to make the verifier's response transparent to the wallet. An example can be with codes such as 102 Processing or 202 Accepted if the final validation is outstanding, instead of a generic 200 OK.
Unfortunately now that VP 1.0 is Final changing the HTTP Status Code would probably be considered a breaking change that we can't make. We probably can clarify the text around 'successfully processed' though, and perhaps we need to clarify section 8.5 to make clear those are errors sent from the wallet to the verifier.
Thank you for the clarification. A clarification would be helpful in this case.
I assume the attack scenario I described is an additional attack next to the session fixation. The attack scenario is less likely and has a lesser impact, since the wallet may not get confirmation. This, in turn, may lead to end-user confusion and likely multiple authentication attempts (assuming the verifier does not provide the redirect URL).