[webauthn] Must assertions with attestation include attested credential data? (#1792)

emlun has just created a new issue for https://github.com/w3c/webauthn:

== Must assertions with attestation include attested credential data? ==
In PR #1663, we're about to add the capability to return attestation statements with assertions. It is currently not explicit whether _authenticatorData_ should contain attested credential data or not when there's an attestation statement with the assertion. This is likely significant for the security of the attestation, so I think it's worth documenting the decision and rationale somewhere more visible than PR review comments.

I believe that if assertions with attestation do not include [attested credential data](https://w3c.github.io/webauthn/#attested-credential-data) in _authenticatorData_, then attestation statements can be forged by transplanting the attestation signature onto a different key. Please verify my reasoning below.

## Setup

Let's assume that assertions with attestation do not include [attested credential data](https://w3c.github.io/webauthn/#attested-credential-data) in _authenticatorData_.

[`packed`](https://w3c.github.io/webauthn/#sctn-packed-attestation) attestations sign over `authData || hash`, so if the public key isn't in `authData`, then there is no signature chain from the attestation key to the credential key. Both keys will have signed the same data, and the RP already knows the credential public key.

Let's assume that an attacker has a credential registered with some RP. The credential was registered without attestation, and with a signature count of zero.

## Forging a `packed` attestation

In practice, the client has control of all parts of `authData || hash` except the signature counter. An attacker can forge an attestation statement as follows:

1. Invoke makeCredential on a compliant authenticator to obtain a credential ID. Discard any other results.
2. Invoke getAssertion on the authenticator with that credential ID, and request `packed` attestation in the assertion. The authenticator will sign over `rpIdHash || flags || signCount || hash` with its attestation key. The client controls `rpIdHash` and `hash`, and `flags` is essentially a constant. `flags` and `signCount` are also echoed back to the attacker with the assertion.
3. Generate an assertion over the same `rpIdHash || flags || signCount || hash`.
4. Append the attestation statement from the authenticator.

The attacker has now generated an assertion
- whose [`signature`](https://pr-preview.s3.amazonaws.com/w3c/webauthn/pull/1663.html#dom-authenticatorassertionresponse-signature) has signed over `rpIdHash || flags || signCount || hash`
- whose [`attestationObject`](https://pr-preview.s3.amazonaws.com/w3c/webauthn/pull/1663.html#dom-authenticatorassertionresponse-attestationobject) contains a `sig` that has signed over `rpIdHash || flags || signCount || hash`
- whose credential private key is not the same as the credential private key that was created by the authenticator.

Thus the attacker has successfully transplanted the attestation statement onto a key outside the authenticator's control, allowing the attacker to spoof any compliant authenticator.

## Conclusion
_authenticatorData_ must include attested credential data when the assertion includes an attestation statement. Otherwise, `packed` attestations can be forged.

Please view or discuss this issue at https://github.com/w3c/webauthn/issues/1792 using your GitHub account


-- 
Sent via github-notify-ml as configured in https://github.com/w3c/github-notify-ml-config

Received on Thursday, 1 September 2022 14:14:29 UTC