-
Notifications
You must be signed in to change notification settings - Fork 28
Description
There is an ask from government Issuers to provide a strong signal of which wallet the user selected during a .create() call.
The attack they are looking to mitigate assumes a user with a trusted browser and OS, but has installed a malicious wallet application. If the user selects this malicious wallet application it may able to forward the request to a wallet on an attacker controlled phone, where the digital credential would get provisioned. The Issuer can't easily detect this attack today. This is issue to look at API that maybe required to address this issue.
The attack would go as follows:
- User has a phone in a good state. Neither the browser or OS is compromised
- But they have installed a malicious wallet app
- The issuer website/app makes a DC create call offering to issue a credential. This request contains the pre-auth code.
- Malicious wallet is selected by the user and it gets the request.
- It forwards it to an attacker controlled phone (which could be rooted) where the request is injected into a legitimate wallet app, e.g Google Wallet etc.. This instance of the wallet app is full attacker controlled.
- The legitimate wallet creates the credential. All the attestations and such would be valid
- The Digital Credential is now available in a legitimate and issuer-approved wallet, but on the attacker controlled phone.
There are a number of ways we could solve this:
- The DC Create call could return the wallet that was selected by the user.
- The Issuer could provide an allow-list of acceptable wallet package name when making the create call
- The Issuer could provide a binding key when making the create call. Here the platform would pass the wallet hmac(binding_key, selected_wallet_identifier)
- Something where the Issuer could provide an allow-list of wallet attestations using some new to-be-standardized PKI
Of these option 3 or 4 are my preferred options.
Option 1 is awkward as the credential issuance flow is normally complete before the call returns. It also exposes the user's wallet app in every call and this has poor privacy properties. Doesn't really work cross-device.
Option 2 exposes OS internals to the web, requiring a web API to contain OS specific app package names. Also just don't much like sending allow lists of package names, as you could imagine an issuer allowing any certified wallet, without knowing the package names upfront. It could lead to a lot of fragmentation. If this is signed over it could work for hybrid though.
Option 3 the caller could add a binding_key param to the top level DC create() call. This can just be a random string of 64 bytes. This key will be kept secret from the wallet app. The user agent/OS will produce hmac(binding_key, selected_wallet_identifier) and send it to the wallet application along with the normal issuance request. The wallet can then pass this value to the Issuer servers as part of any validation steps. The issuer can now get a strong signal for which wallet was selected by the user. This doesn't really work for hybrid though.
Option 4 assumes that wallet apps hold a industry defined attestation, this could be a special type of Digital Credential issued to them by an certification org. In this option the issuer could provide a list of acceptable attestation credentials (like the get call) and the OS could challenge the wallet to prove it holds one before it appears in the selector to the user. This also has the benefit of the solving the problem of filtering out non-malicious wallets that may offer themselves up even though they would fail during the process if selected (as they are not approved by the issuer).
All of these add a decent amount of new complexity and will likely require a healthy amount of discussion.