Hacker News new | ask | show | jobs
by Dylan16807 1861 days ago
> With SSH the protocol is designed differently, the remote site doesn't get an opportunity to store an ID and then ask your Security Key to authenticate

Why not?

Being able to work around a gap/flaw in the authentication protocol is nice but I definitely wouldn't call that "cool".

Also a yubikey being able to hold 25 of those is kind of pathetic.

1 comments

Why not, as in, why was the SSH standard, finished in 2006, not prepared for the way we'd prefer to authenticate in 2021? Because of time's arrow, locally stuff happens in order.

I was actually impressed that the OpenSSH team figured out a way to make this work at all without adding an entirely new mechanism to SSH which would then have taken ages to propagate out into the world and doubtless been the source of weird problems with poorly made proprietary SSH servers for many years after that. If you go back far enough in HN there's a comment where I supposed that couldn't be done.

> I was actually impressed that the OpenSSH team figured out a way to make this work at all without adding an entirely new mechanism to SSH

This is what they did, though: FIDO2 requires client and server support for the new "-sk" key types, since FIDO2 requires a very specific challenge/response format and does not just allow signing arbitrary hashes.

The older way of supporting SSH keys in security keys is through GPGs "smartcard" support, which requires using gpg-agent as an SSH agent and a security key that can speak CCID (i.e. pose as a smartcard reader with a permanently inserted smartcard over USB). That's what Yubikeys do, among others.

No, they just added a handful of new public key types, that's not even as invasive as adding a new authentication method to SSH.

For example, if your client knows some new FIDO backed credentials and is wondering if the proprietary ten year old SFTP server you're connecting to will trust them (it won't) it does exactly the same type of thing it did for other new OpenSSH key types, such as Ed25519. The server doesn't recognise these new types, just as it didn't recognise Ed25519 and no new exciting problems are discovered even though the people who wrote that server only read half of RFC 4252 while squinting and it only actually does RSA and password authentication and gets both of these wrong.

If they'd added a new method to support this, let's call it "securitykey" chances are that crappy server blows up whenever you just mention that you've heard of this "securitykey" method that was not explicitly listed in the document the programmers half-skimmed. Yes I have seen real SSH servers that behave this way, it isn't pretty and good luck getting somebody who has chosen to spend money on a bad proprietary SSH server to replace it with something that's not garbage.

And that still wouldn't enable them to sidestep the residential credential problem. To do so I think they'd need to reach down into the protocol layer and add another message, which again, it'd likely be compatible with all the competent SSH implementations on your preferred Free Software platform, but undoubtedly break the expensive half-arsed solution somebody spent $5000 on.

Also, if you do build that you run into another problem, even in a shiny Free Software environment, where do these IDs the server is now responsible for live? Is the SSH server now writing to files in the home directories of users it is authenticating? That sounds like a recipe for exciting new security bugs, not what we wanted.

> To do so I think they'd need to reach down into the protocol layer and add another message, which again, it'd likely be compatible with all the competent SSH implementations on your preferred Free Software platform, but undoubtedly break the expensive half-arsed solution somebody spent $5000 on.

The message wouldn't show up unless the server offers this new key type, would it?

> Also, if you do build that you run into another problem, even in a shiny Free Software environment, where do these IDs the server is now responsible for live? Is the SSH server now writing to files in the home directories of users it is authenticating? That sounds like a recipe for exciting new security bugs, not what we wanted.

It's not the job of the SSH server to write to authorized_keys, so it's not the job of the SSH server to write these blobs either.

> The message wouldn't show up unless the server offers this new key type, would it?

Good point. I think you can probably guard this so that neither clients nor servers ever see the new SSH authentication message if they aren't onboard with this plan, but it's a bit complicated.

The problem is on your first flight you don't know the ID, so your SSH_MSG_USERAUTH_REQUEST will definitely fail. That's OK, the protocol expects this, it's how lots of things already work. The server sends SSH_MSG_USERAUTH_FAILURE but unlike REQUEST, the FAILURE message isn't extensible, the only way forward it imagines is to tell you other methods that might work, and your method might work, you just don't know the ID.

So you're going to need to have this failure step function as a signal to inject the new message, a hypothetical SSH_MSG_USERAUTH_SECURITYKEY_ID_LIST or something, with one or more IDs for which the server claims to know a corresponding public key, the same way protocols like WebAuthn work.

The more I write about this, the more I'm convinced somebody could have actually built it, but since the OpenSSH people did the work to bring FIDO to SSH and I did not, I don't really have the right to criticise. For all I know they spent six months trying this approach and ended up in a cul-de-sac.

> It's not the job of the SSH server to write to authorized_keys, so it's not the job of the SSH server to write these blobs either.

Good point, you could probably build something where the ID lives in (the new type of) SSH public keys or some equivalent file, so it gets concatenated to authorized_keys and then the server just needs to know to dredge the ID out from there and send it to a client in the new message.

> The more I write about this, the more I'm convinced somebody could have actually built it, but since the OpenSSH people did the work to bring FIDO to SSH and I did not, I don't really have the right to criticise. For all I know they spent six months trying this approach and ended up in a cul-de-sac.

These were my thoughts exactly when I first read about the new feature in 8.2.

Would be really cool to learn about the internal reasoning for the solution that they ended up with.

> Good point, you could probably build something where the ID lives in (the new type of) SSH public keys or some equivalent file, so it gets concatenated to authorized_keys and then the server just needs to know to dredge the ID out from there and send it to a client in the new message.

That would open you up to being fingerprinted by the server, right? WebAuthN combats this by scoping the ID to the RP domain name, but SSH servers aren't guaranteed to have a (canonical) name.

So you're saying that buggy SSH servers are much more likely to blow up when encountering new methods rather than new key types? That's interesting (and I don't doubt it, although I fortunately haven't had to work with non-OpenSSH servers much).
They could have added a new optional mechanism. I'm asking about github's servers specifically, not the long tail rest of the world.

Also, wait, if github isn't doing custom things on their end, how are they enforcing this rule that you need to tap once per connection?

The touch/no-touch requirement is controlled by the server (or in FIDO2 terminology, the "relying party").

OpenSSH exposes this as a new sshd option called "no-touch-required", which Github probably just does not set.

Specifically, Security Keys sign a blob of data to authenticate. Most of that blob is nonsense to the Security Key. It might mean something to a big complicated web browser or your SSH client, but not the simple, and thus hopefully secure, Security Key.

But, there's a field of bitflags. The Security Key knows what those mean. One of those bitflags is "User Present" or UP, which means, "I promise I have some means to verify a human interacted with me and they did".

For U2F and WebAuthn UP is just mandatory. So, most devices you will find just always set UP, even if the Relying Party doesn't ask them to. However some devices you could choose not to ask for UP, and a device could in this case just skip the touch step, but it must not sign a message with that UP bitflag set in this case.

Some of the flags are currently unused, one that's also interesting for SSH in some environments is UV, "User Verified" which means the device claims to have some way to know if this is its real owner or just a toddler clicking the button. UV is typically set for fingerprint readers, facial recognition, or the cheapest option, a Yubikey with a PIN can set UV if you entered your PIN.

Is the device explicitly not allowed to use a single touch to establish UP for a few minutes?
User presence is defined in present time. There are no FIDO police who'll burn down your factory or arrest your executives if your device doesn't do this, but removing this safeguard has (at least potentially) negative consequences.

I believe some theoretical attacks against user privacy would benefit from being able to attempt a huge number of "authentication" steps without annoying the human by making them touch the sensor. As with the Socialist Millionaire's Protocol or Magic Wormhole, we're relying on the fact that humans get annoyed fairly quickly and will just give up if it doesn't work, so attacks that require a large number of iterations cannot mechanically succeed.