keepassxreboot / keepassxc-browser

KeePassXC Browser Extension
GNU General Public License v3.0
1.74k stars 182 forks source link

Passkey man-in-the-middle attack #2122

Closed DigitallyRefined closed 6 months ago

DigitallyRefined commented 7 months ago

Expected Behavior

Passkeys should not be sent or saved when the websites TLS/SSL certificate is invalid.

Current Behavior

Passkeys are sent and saved when the websites TLS/SSL certificate is invalid.

For example, if the user connects to an untrusted network which resolves the DNS to an attackers server (with an invalid TLS certificate) and they accept the warning and continue, they can still use their passkey to login and the attacker would then have access to their account by replaying the users passkey challenge to the original server.

When KeePassXC is closed, KeePassXC Browser falls back to Chrome/Chromium's built in passkey system, which throws a WebAuthn JavaScript exception with an invalid TLS error.

Possible Solution

The KeePassXC Browser extension should validate that the website is secure (over HTTPS) and has a valid TLS certificate before sending or saving passkeys (only localhost is allowed to use insecure HTTP for development).

Steps to Reproduce (for bugs)

  1. Setup KeePassXC and KeePassXC Browser to allow Passkey storage
  2. Visit a website with an invalid certificate that allows logging in via Passkeys
  3. Accept the invalid certificate warning and continue
  4. Login or register

Screencast from 2024-02-19 19-32-37.webm

Debug info

KeePassXC - 2.8.0-snapshot KeePassXC-Browser - 1.8.12 Operating system: Linux x86_64 Browser: Chrome/Chromium 121.0.0.0

droidmonkey commented 7 months ago

I find it interesting that it is so trivial to bypass the built-in Chrome/ium safeguards (in this case inadvertantly). We override the passkey handling function, which apparently does this check when not overridden. We have to override it because no browser supports thirdparty passkey authenticators. Well looks like they need to move more stuff outside that function.

https://lists.w3.org/Archives/Public/public-webauthn/2022Nov/0135.html

varjolintu commented 7 months ago

For Firefox this can be achieved by using: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/webRequest/getSecurityInfo

phoerious commented 7 months ago

For reference, this seems to be Mozilla's native implementation:

phoerious commented 7 months ago

TBH, I'm quite ambivalent on this. Yes, it's probably safer to refuse to provide credentials when the certificate is invalid. On the other hand, you have consented to this kind of MITM when you accepted the security exception for this certificate. In the end, accepting an invalid certificate means you checked its validity yourself, hence the connection is indeed secure, despite what the red padlock says.

varjolintu commented 7 months ago

And just to note: KeePassXC side already ignores a requests that are made without a HTTPS scheme.

DigitallyRefined commented 7 months ago

TBH, I'm quite ambivalent on this. Yes, it's probably safer to refuse to provide credentials when the certificate is invalid. On the other hand, you have consented to this kind of MITM when you accepted the security exception for this certificate. In the end, accepting an invalid certificate means you checked its validity yourself, hence the connection is indeed secure, despite what the red padlock says.

That's true, but users being users might just click past the warnings without understanding the consequences (especially if they've encountered the TLS error/warning before). But I suppose if they've installed KeePassXC and the browser extension and turned on Passkeys, then then perhaps they should know better than just to skip past the certificate error warning messages!

I did test this out of curiosity on Firefox 122 and Safari 17.3.1 (without KeePassXC) and both of them allow you to login and register Passkeys even when the TLS certificate is invalid, surprisingly. It seems that only Chrome/Chromium 121 throws a Uncaught (in promise) NotAllowedError: WebAuthn is not supported on sites with TLS certificate errors. but that could be the @simplewebauthn/browser NPM module I'm using.

droidmonkey commented 7 months ago

Not to mention, you would break the ability to use passkeys for dev and local hosted services (like a NAS, for example) unless you also set up a CA and other bits to make them legit certs. Overall, any enterprise worth their salt is disabling the users' ability to bypass invalid certs.

phoerious commented 7 months ago

Modern browsers make it hard enough to skip certificate validation errors. The red screen is pretty scary and you have to first find and then click a tiny "Advanced options" link, read through some more tech babble and then click "Proceed anyway". In some cases, Chrome doesn't even show this option and you have to blindly type "thisisunsafe" to proceed. If you did all that are still willing to enter your password after this, you may deserve what's coming.

DigitallyRefined commented 6 months ago

Closing this, as the browsers built in certificate error page should be enough to warn users not to continue and if they do they shouldn't be using their passkeys.