Question about webauthn signatures?
Damien Miller
djm at mindrot.org
Fri May 7 12:41:17 AEST 2021
On Thu, 6 May 2021, Tyson Whitehead wrote:
> > The webauthn signature type (note: note a key type) was added to support
> > browser-based SSH clients that can only interact with FIDO keys via the
> > webauthn APIs. These APIs do not allow "bare" FIDO signatures, but
> > implictly include weborigin information in the signed data.
>
> Thank you for the clarification. I believe I understand now it is for the
> signature in the SSH_MSG_USERAUTH_REQUEST when the client only has access to
> the device via the webauthn API. That makes sense.
>
> Many of our non-unix savvy users just use passwords as settings up keys is
> difficult for them. From reading up on the FIDO2 standard, it would seem that
> it should be possible to just have server-side FIDO2 keys. This could be a
> huge plus as we could generate and register these keys on our clusters for
> them off our website. They could just use them without having to setup
> anything on their end.
That's true of FIDO web authentication. What we implemented in SSH
(ab-)uses the FIDO spec to fit SSH's existing publickey user
authentication, because users and lots of tooling is built around that.
This unfortunately precluded the use of server-side keys, as there is no
mechanism for the server to communicate key handles to the client.
I do have vague plans to do a more web-like FIDO authentication method
for OpenSSH in the future, but haven't got around to it yet.
> I was looking at RFC4252 (The SSH Authentication Protocol) to see if
> FIDO2-based server-side could be retrofitted into the SSH protocol, and it
> seemed to me like it could be done. Specifically, the "publickey"
> authentication protocol has the client send
>
> byte SSH_MSG_USERAUTH_REQUEST
> string user name in ISO-10646 UTF-8 encoding
> string service name in US-ASCII
> string "publickey"
> boolean FALSE
> string public key algorithm name
> string public key blob
>
> and the server respond with
>
> byte SSH_MSG_USERAUTH_PK_OK
> string public key algorithm name from the request
> string public key blob from the request
>
> so I am thinking it could be (slightly) abused by
>
> 1. creating a another esk-ecdsa key type where the key handle was stored with
> the public key
> 2. have the client pass an empty "public key blob" when sending the
> SSH_MSG_USERAUTH_REQUEST message for this key type
> 3. have the server respond back with the key handle (or the entire public key
> with the key handle) in the "public key blob" of its SSH_MSG_USERAUTH_PK_OK
> response
>
> Support for multiple keys could be done by having repeated queries return
> subsequent ones. The server could also reply with fakes to avoid leaking
> information about whether any such keys actually exist.
I was thinking something like:
c->s
byte SSH_MSG_USERAUTH_REQUEST
string username
string service name
string "fido-discover-v00 at openssh.com"
string reserved
s->c
byte SSH_MSG_USERAUTH_INFO_REQUEST
string reserved
string[] key_info
(this message number was defined for GSS authentication, w/
SSH_MSG_USERAUTH_INFO_REQUEST always going in the s->c direction and
SSH_MSG_USERAUTH_INFO_RESPONSE always going c->s).
where each key_info member contains
string pkblob
string key handle
uint8 flags
string reserved
The client could then try the key handles supplied against their attached
security keys to find one that will sign a challenge and then make a
regular public key authentication attempt:
byte SSH_MSG_USERAUTH_INFO_RESPONSE
string username
string service name
string "publickey"
bool true
string pkalg
string pkblob
string signature
**
The protocol bits are pretty easy, the UI is a bit more complicated. The
main problem is that we need some way to store the keys eligible for
fido-discover-v00 at openssh.com.
One possibility is marking them using some tag in authorized_keys, but
the information we need to return is more than currently exists in the
sk-* public key formats. So we'd need a new encoding that stores the
extra information and likely some ugly special-casing to glue it all
together.
Perhaps authorized_keys entries like
fido[,option...] sk-ecdsa-sha2-nistp256 at openssh.com pubkeyblob keyhandleblob
flags would be reconstructed from the options listed on the key:
no-touch-required, verify-required, etc.
Another alternative would be to define a pubkey blob format that includes
all the information. Not sure which is nicer...
> > The only thing that AFAIK uses it is the test Javascript that I wrote:
> > regress/unittests/sshsig/webauthn.html in the source distribution. If you
> > stick it on a web server then you can generate FIDO keys and webauthn
> > signatures that you can verify using ssh-keygen -Y. It's the basis of
> > the webauthn signature unit tests.
>
> Very interesting. I added a bit on top of your javascript to also export the
> private key to see if we could do the key generation sever side in order to
> make things easier for our non-unix-savvy users
>
> https://staff.sharcnet.ca/tyson/webauthnkey.html
ah good idea, this inspired me to add a similar feature to mine now too.
https://github.com/openssh/openssh-portable/commit/c0d7e36e979
> The resulting keys seem to work fine in SSH, which makes me think, if SSH
> could support pure server-side key, and we could generate these keys with
> Webauthn, it would actually make things even easier for our non-unix-savvy
> users (buy a key, press a button on our website to register it) while really
> tightening up user accounts and thereby decreasing the attack vectors against
> us.
yep, agree. I think a FIDO-style authn method would be a nice addition.
-d
More information about the openssh-unix-dev
mailing list