Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Split RP ops "Registering a new credential" into one with and one without attestation #1710

Open
emlun opened this issue Mar 23, 2022 · 8 comments
Assignees
Labels
@Risk Items that are at risk for L3 type:editorial

Comments

@emlun
Copy link
Member

emlun commented Mar 23, 2022

Motivated by #1709. Many RPs will not need attestation, and the default attestationConveyance is "none". It is of little use to these RPs to implement all the complexity around verifying attestation statements. We could split §7.1. Registering a New Credential into two variants: the current one, which includes all the details around attestation verification, and a greatly simplified one without most of the steps concerned with attestation. Or, alternatively, extract attestation processing into a subsection and refer to it as an optional sub-procedure. The new section(s) should briefly explain the security and user experience implications of choosing to ignore, require, or simply request and store attestations.

@emlun emlun self-assigned this Mar 23, 2022
@dagnelies
Copy link

dagnelies commented Mar 29, 2022

As far as I understand, when registering credentials, the signature is concealed somewhere deep in this authenticator-specific attStmt object.

So, without attestation means without signature and the client can freely tamper with all the data anyway (very easely). In the end, in the absence of attestation/signature, you can simply send the public key over since none of the data can be trusted anyway.

Or did I miss something?

@MasterKale
Copy link
Contributor

MasterKale commented Mar 29, 2022

In the end, in the absence of attestation/signature, you can simply send the public key over since none of the data can be trusted anyway.

@dagnelies i think you'll be interested in issue #1698 where I ask that very question. @emlun provides a very nice answer that doesn't try to dance around the fact that "none" attestation doesn't get you a signature over authenticator data.

And in fact @emlun if you do go ahead with this effort you should pull out content from your answer above, I think more people should read it.

@dagnelies
Copy link

dagnelies commented Mar 29, 2022

Actually, as a newcomer, I have issues wrapping my head around the whole thing. The puzzle is slowly coming together. The verification process is very long, including attestations, however I fail to see how it prevents tampering at all.

Basically, because of the generated challenge, you can associate it to the corresponding "receiver". However, the content, with attestation or not, is taken in good faith. It would be trivial to write a bot that requests a challenge, produces a key pair, and produce arbitrary registration payloads, whether signed/attested or not ...so in that context a signature does not matter at all and incoming flags/infos should be considered purely informational anyway. Right?

...so, again a dumb question but: is it worth verifying anything? After all, a malicious script, whether browser based or not, can just build arbitrary registration payloads. If you get your hands on the challenge, you can register whatever you want for it without even calling webauthn. There is nothing you can really proove besides that it is the right challenge.

Am I missing something or is there a way to prevent a script from building arbitrary registrations?

If these assumptions hold, all that's really needed for a registration is credential.id and credential.response.getPublicKey(), and associate it with the person receiving the challenge. All other stuff being optional informative metadata that could have been tampered with invented key pairs. Sorry again if I speak nonsense. As I said, I have difficulties assimilating this spec.

@MasterKale
Copy link
Contributor

Basically, because of the generated challenge, you can associate it to the corresponding "receiver". However, the content, with attestation or not, is taken in good faith. It would be trivial to write a bot that requests a challenge, produces a key pair, and produce arbitrary registration payloads, whether signed/attested or not ...so in that context a signature does not matter at all and incoming flags/infos should be considered purely informational anyway. Right?

If knowing that only legitimate authenticators can be registered for use with your site then you want to request an attestation statement. Responses are only really taken "in good faith" when you don't request one because, as you mention, there's no signature over anything.

What requesting an attestation statement gets you is:

  • A signature over authenticator data and client data
  • A chain of certificates that links back to known root certificates owned by the various hardware vendors

It's that last one that can't be faked by software. No one other than the owner of the root cert private key can sign any connection to any generated intermediate certificates. Since it's the leaf cert that's ultimately used to validate the attestation statement's signature, faked responses wouldn't ever pass legitimate response verification because the faked leaf certificate couldn't ever be linked back to a valid root cert.

@dagnelies
Copy link

dagnelies commented Mar 29, 2022

Ah, that's what I have been missing I guess. I wrongly assumed the signature included in the attStmt object would be using the generated public/private key pair, but instead it signs the content using the authenticator's certificate... that makes sense. That was the big puzzle piece I missed. Thanks for enlightning me. I really praise those implementing a validation library like yours, it is really a tough task.

@emlun
Copy link
Member Author

emlun commented Mar 29, 2022

Yeah, the critical piece to realize is that all WebAuthn credentials are "trust on first use" (TOFU) keys. Even with attestation, it is indeed possible for a malicious script to replace the public key and attestation statement during registration, and thus have the attacker's key registered instead of the victim's key. We touch on this in 13.4.4. Attestation Limitations in the Security Considerations section.

What attestation does is provide a way for the authenticator to prove to the RP what kind of authenticator it is. That proof could eliminate the possibility of software-generated malicious keys, but a malicious script could still in theory call out to a remote server to generate an attestation statement using a genuine authenticator on the RP's allow list. At best the RP could display a name and/or image of the authenticator as identified by the attestation statement, which could allow attentive users to notice if there's a discrepancy. But even then the attacker's remote server could have an array of authenticators of different brands and models to account for that too. And of course, self attestation is always susceptible to tampering since by definition there's no way to link the attestation key to any established root of trust.

So yeah, the registration ceremony is a leap of faith, with or without attestation. But assuming one was completed securely, any subsequent authentication ceremonies are highly resistant to tampering since at that point there is an established trust relationship with a particular credential public key. You cannot know with certainty who the public key came from during registration, but you can know with certainty that an authentication signature came from the same key pair as was registered.

@emlun
Copy link
Member Author

emlun commented Sep 1, 2022

When PR #1663 is merged, the attestation verification during assertion should be included in this as well. See: #1663 (comment)

@nadalin nadalin added the @Risk Items that are at risk for L3 label Jun 27, 2023
@plehegar plehegar modified the milestones: L3-WD-01, L3-WD-02 Oct 4, 2023
@dannyniu
Copy link

dannyniu commented Mar 1, 2024

Most of the discussion here seem to revolve around TOFU of pubkey during registeration. If registration is to be simplified, then origin verification will not be possible during registration.

And the beginning of this section, which expressed:

"When registering a credential ... the Relying Party MUST validate the origin"

will need to be adapted accordingly, unless there's something critical with verifying the origin during registration. I think there can't be anything critical, as registering a duplicate public key is not too much different from reusing passwords on different websites, and without an attestation trust anchor, no meaningful valid information can be established.

Probably say "When registering an attested credential", because that's the only way all the credential and client/auth-data can be reliably verified.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
@Risk Items that are at risk for L3 type:editorial
Projects
None yet
Development

No branches or pull requests

6 participants