-
Notifications
You must be signed in to change notification settings - Fork 37
Description
Imported from AB/Connect bitbucket: https://bitbucket.org/openid/connect/issues/1777
Original Reporter: bifurcation
A credential is a statement that certain identity attributes correspond to the holder of the private key of a key pair. (Where the key pair is indicated by the credentialSubject URI.) If the subject of the attributes from the issuer’s perspective is not the same as the holder of the private key of the key pair, then the credential is false and should not be issued.
There are two types of false credential an attacker might obtain:
- A credential with the attacker’s key pair and the victim’s attributes
- A credential with the victim’s key pair and the attacker’s attributes
The former type is the usual case for maliciously issued credentials, e.g., the fraudulent X.509 certificates issued in the 2011 attack on DigiNotar. But the latter type can also be damaging, leading to attacks known as Unknown Key Share or Identity Misbinding attacks. Failure to prevent the issuance of such credentials leads to attacks on WebRTC and DANE. The ACME protocol for certificate issuance requires that the client requesting a certificate sign over the identifiers to be put in the certificate (“The CSR MUST indicate the exact same set of requested identifiers as the initial newOrder request“) precisely to prevent these attacks.
The current VC issuance specification is vulnerable to unknown key share attacks, i.e., to issuing false credentials of the second type above. The Proof of Possession JWT (the only PoP defined in the specification) does not have any binding to the OAuth client (the party whose information will go in the credential), so if an attacker can obtain a PoP JWT with a nonce that is valid for the Issuer, then the attacker can request a credential using that PoP JWT. The resulting credential will falsely associate the attacker’s attributes with the victim’s key pair.
Note that while this is in a sense a replay issue, it is not addressed by single-use nonces. From the perspective of the victim Issuer, the nonce in the PoP JWT may still be fresh when the attacker uses it (depending on how the attacker obtained the PoP JWT). Anti-replay defenses intended to ensure each signature is used only once do not address this attack.
Instead, what is needed is for the signature on the PoP JWT to bind it to the OAuth client making the credential request. This effectively creates a two-way consent – The OAuth client agrees that it is the same as the key pair holder by submitting the credential request containing the PoP JWT, and the key pair holder agrees that it is the same as the OAuth client by signing some identifier for the OAuth client.
A simple way to implement this solution would be to include a hash of the OAuth client’s access token in the PoP JWT, as with the “ath” claim in a DPoP JWT. The access token hash is a unique identifier for specific OAuth client session, and thus provides the desired binding. I have implemented this solution in https://bitbucket.org/openid/connect/pull-requests/360.