Comments (10)
Not sure how this really offers protection against phishing. If a bad actor can present a phishing site with a dialog into which a user supplies their password, then the bad actor can use that password against the legitimate site later.
from webauthn.
Thanks for the thoughtful reply!
the same password would result in the same credential ID for different users
I wonder if you did not misunderstand the credential ID construction; the password is not part of it at all. Rather, most of the credential ID is just a randomly generated salt, so with 32 randomly generated bytes, I would indeed expect all credential IDs to be different.
Since the public key (that the server stores) is only derived from the salt, RPID and password, however, a malicious server could certainly bruteforce the user's password over time, but I believe this is intrinsic to any possible authentication protocol based on passwords alone (if a system can validate a password for login, then of course it can also bruteforce it). I don't think a third party would be able to do that, however.
So any way you twist it, the problem is that there just isn't enough entropy in most human-chosen passwords
Naturally, this is the problem of any authentication scheme involving passwords only. My main point is that there are many situations where it is impractical to use any other factor than a password alone, and specifically in such situations, for the reasons I started out with, WebAuthn would significantly alleviate (even if certainly not eliminate) many of the problems of password-only authentication.
As for hash_to_field
, thank you very much for the link. I had tried finding prior art for deriving EC keys from passwords, but was unable to find any. However, while I haven't read and understood RFC 9380 fully yet, it does not necessarily sound as though it generates an ECDSA private key. It's not immediately obvious to me what the output of hash_to_field
is when applied to the right parameters, but the abstract talks about generating points on an elliptic curve (and the u outputs being vectors seems to reinforce that, though I'm not sure what m would be in this case), whereas a private ECDSA key is just a scalar. I'll continue reading it, though.
I'm not sure I fully understand the user interaction model here
The expectation would certainly be your first case. At the risk of repeating myself, the whole point of the proposal is for cases where a second factor is impractical. If the password is just to be imported into a browser, then I feel one might just use properly random keys instead.
from webauthn.
You could also brute-force a
(credential-ID, signature)
pair
Yes, I also realized that last night, along with the fact that an attacker could choose the salt for a victim, and have precomputed dictionaries for that salt. And most damning of all, that actually makes phishing attacks attractive for an attacker. That realization dampened my enthusiasm for the whole thing a fair bit.
But perhaps some PAKE-based approach
My intention was to cram something almost as good as a PAKE into the existing framework that WebAuthn provides, but given the above, it is clear to me that it isn't almost as good as a PAKE, so yes, I agree.
Thanks for humoring me!
from webauthn.
If a bad actor can present a phishing site with a dialog into which a user supplies their password
In my experience, most current WebAuthn user-agent implementations use a dialog that a site can't really spoof since it's partly outside the page viewport.
Sure, I guess a naïve user could be fooled into entering their password into a non-standard dialog, but having that distinction I would think makes a big difference, at least.
from webauthn.
Interesting idea, but like @sbweeden I'm skeptical of this.
First, some surface-level thoughts:
hash_to_field
(RFC 9380) can be used to derive an EC private key with minimal distribution bias.- I'd say the
UV
should probably be set to 0 most, or maybe all, of the time. WebAuthn keys are normally assumed to be primarily possession factors, and the UV bit represents use of also a second factor. But a password-derived key inherently is primarily a knowledge factor, so setting the UV bit would misrepresent these credentials as multi-factor credentials when they are in fact always single-factor credentials. - Similarly, these credentials should always set
BE=1
because a password-derived credential is always trivially exportable, no matter how you store it.
On a deeper level, I'm not sure I fully understand the user interaction model here. Is the expectation that (1) the user would enter the password during each registration/authentication ceremony? Or (2) does the user import the password once (possibly in a browser settings UI) and then only authorize its use as (key derivation material for) a credential?
I agree with @sbweeden that (1) seems too dangerous because it would be fairly easy to trick many users into entering that password into a malicious site, which could then of course follow the spec to perform the key derivation and impersonate the user. Yes, dedicated browser UI would make this detectable for the most observant users, but this would likely succeed against most people as they may not know to look out for this.
(2) would be a bit less dangerous, but still open for abuse as malicious actors can still ask victims to enter their master password, or direct them on how to open their browser settings to retrieve the master password and enter it on the site. This would probably have a far lower success rate than (1), but I still think it would work in too many cases.
But whatever the UI, there's an even bigger problem with this: there isn't really any meaningful brute-force protection, and the same password would result in the same credential ID for different users. High iteration counts help, but only for nontrivial passwords and almost not at all against dictionary attacks. Many people would continue to reuse a single password everywhere, perhaps with minor variations, and many would use a very simple one that would be cracked almost immediately by any offline attack. "Salting" the KDF with a username would help a little bit to differentiate hashes between users, but again this is only really meaningful for fairly complex passwords. And once you crack an RPID-username-password combination, you can still easily try that same username-password combination on other RPIDs. Salting with any cryptographically random value would invalidate the point of deriving everything from a password alone.
So any way you twist it, the problem is that there just isn't enough entropy in most human-chosen passwords, so we end up back at still needing a password manager anyway - be it to embed more entropy in the password itself, or to store and manage auxiliary salts or keys to mix in with a low-entropy password. At that point, why wouldn't you just use a cryptographically random passkey stored in that password manager?
from webauthn.
I wonder if you did not misunderstand the credential ID construction; [...] most of the credential ID is just a randomly generated salt
Ah, thanks, I did indeed miss that part. That certainly does at least limit the scalability of a brute force attack as you'd need to crack each credential ID individually rather than all at once.
I don't think it helps all that much, though: since this salt is stored on the server (in the credential ID), it must be sent to the user before the user can derive their key from it. Since this is intended to be the only authentication step, as I understand the proposal, anyone can query the server for a user's credential IDs without needing to authenticate first - so the attacker doesn't need to compromise the server-side database to get at the credential IDs, they can just request them via the server's public API. From there, any low-entropy password will be easy to crack since the attacker has the salt. Granted, the individual salts means they can't attack all users' credential IDs at once, but they don't really affect the difficulty of a targeted attack.
The expectation would certainly be your first case.
Which is:
(1) the user would enter the password during each registration/authentication ceremony
Ok. Like I said, I think this seems a bit too susceptible to tricking users into entering their password into a malicious webpage rather than the browser UI.
Off-topic hash_to_field discussion
> it does not necessarily sound as though [hash_to_field] generates an ECDSA private key. [...] (and the _u_ outputs being vectors seems to reinforce that, though I'm not sure what _m_ would be in this case)
It is a bit obtuse, but the field to hash to is a free parameter of the function. The primary objective of the RFC is the hash_to_curve function, which uses hash_to_field to hash to the coordinate field of an elliptic curve, but you can also use hash_to_field to hash to the scalar field instead:
The hash_to_field function is also suitable for securely hashing to scalars. For example, when hashing to the scalar field for an elliptic curve (sub)group with prime order r, it suffices to instantiate hash_to_field with target field GF(r).
The u vector just holds count results, but you can set count=1. m is 1 when hashing to a prime order field F (because F has order q = p^m, and q = p for a prime order field). So for hashing to an EC private key you'd set m = 1 and p = n where n is the order of the curve generator (AKA base point) (i.e., the order of the prime order subgroup of the curve (which is the only (or any, depending on how you see it) subgroup of a prime order curve like P-256)).
from webauthn.
I think you still misunderstand, as you shouldn't be able to crack a credential ID at all, given that the password has no part in constructing it. You would be able to brute-force a (credential-ID, public-key)
pair, but that would at least require the server-side data getting leaked. The credential ID only contains parameters for the KDF, not any results of it.
For example, when hashing to the scalar field for an elliptic curve (sub)group with prime order r, it suffices to instantiate hash_to_field with target field GF(r).
Ah, nice. I hadn't read that part, but in that case, it certainly seems only suitable to reuse it.
from webauthn.
Ah, I see now. I think I assumed the MAC would involve the password, but indeed it does not. Here's how I understand the proposal in pseudocode:
password = input()
salt = random()
n = config.n
cred_id_tail = "pbkdf2-sha256" | 0x00 | encode(n, salt)
cred_id = LEFT(8, SHA256("pwkey" | cred_id_tail)) | cred_id_tail
prk = PBKDF2(SHA-256, SHA-256(RPID) | password, salt, 1 << n, 32)
pri_key = hash_to_field(prk, ...)
pub_key = pri_key * P256.G
So ok, the credential ID alone isn't enough to mount an offline brute-force attack since there's nothing to verify attempts against. An online brute-force attack is still possible, but then of course the target server can deploy rate-limiting restrictions or the like to make the attack far less scalable.
You would be able to brute-force a
(credential-ID, public-key)
pair, but that would at least require the server-side data getting leaked.
Yeah. You could also brute-force a (credential-ID, signature)
pair, as that gives the attacker something to test a public key guess against. That would require the attacker to passively eavesdrop on a registration or login ceremony. As far as I can tell the difficulty of both of those attacks is equivalent to breaching a password database or passively eavesdropping on a password entry. So yeah, this proposed approach seems to not introduce any new vulnerabilities compared to traditional password authentication.
On that note, though: I'm not convinced we want to lower the bar for WebAuthn to just "not worse than a password". At least in my opinion, WebAuthn is supposed to be better than passwords, not just equivalent, and I'm not convinced this approach is enough of an improvement over traditional password authentication.
You wrote in the initial comment that:
- Password authentication would stand to benefit a lot from the strong anti-phishing protections that WebAuthn offers.
But I question if it actually would. The inescapable problem with passwords is that they can be entered into a malicious input field, whereas a WebAuthn credential cannot. The strength of WebAuthn is not that it is possible to use it securely, but that it is very difficult to use it insecurely. Any password-based system inherently struggles to achieve the latter since a password can always be entered anywhere.
I applaud your effort to come up with a fairly good design within the design restrictions, but I don't think WebAuthn is the right home for it. But perhaps some PAKE-based approach could be a candidate for a new credential type in the Credential Management API (which WebAuthn itself is an extension of)?
from webauthn.
PAKEs would indeed be better. It doesn't take long looking at past technologies like kerberos to see how simplying using a KDF is open to attacks.
from webauthn.
Thank you for the discussion!
2024-07-17 WG call: discussion seems to be finished, closing.
from webauthn.
Related Issues (20)
- [[Create]] should not access the global object directly HOT 1
- Define `TypeError` behavior during `.get()` HOT 3
- Return more nuanced errors HOT 3
- Does Related Origins introduce a need for "Related RP IDs" support in `.get()`? HOT 1
- UTF-8 decode should not be required for response.clientDataJSON and cData HOT 2
- CollectedClientData fields are not ordered correctly and crossOrigin should be required HOT 3
- Add `topOrigin` to the limited verification algorithm HOT 2
- Use URI instead of URL for related origins HOT 2
- Add `publicKey` and `publicKeyAlgorithm` to `AuthenticatorAssertionResponseJSON` HOT 3
- Make `AuthenticatorAttestationResponseJSON.publicKeyAlgorithm` optional HOT 2
- Rename PublicKeyCredentialHints to PublicKeyCredentialHint? HOT 1
- CollectedClientData.crossOrigin not referenced in RP ops HOT 1
- Cross-window `Virtual Authenticator Database` HOT 2
- Make `Credential.id` a `DOMString` HOT 2
- Remove `RegistrationResponseJSON.id` and `AuthenticationResponseJSON.id` HOT 10
- Remove rp.name HOT 3
- `options.mediation` should be called something else in step 14 of Registering a New Credential HOT 2
- Add `mediation` to `PublicKeyCredentialJSON` HOT 2
- Add links where non-members can make patent licensing committments to `CONTRIBUTING.md` HOT 1
- Review privacy concerns around error conditions HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from webauthn.