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
x/crypto/ssh: Consider relaxing public key and signature matching for RSA keys in SSH_MSG_USERAUTH_REQUEST #53391
Comments
This could probably have been a comment on #49269 cc @golang/security |
I created a new issue because the fix could be made independent of #49269 since anytime the client decides to use I believe Ubuntu 18.04 LTS is supported through 2028: https://ubuntu.com/about/release-cycle. I will raise a bug report with UPDATE: Filed https://bugs.launchpad.net/ubuntu/+source/gnupg2/+bug/1978851. |
When we put gitlab-sshd in production, we noticed a number of clients using RSA keys would fail to login. The server would report: ``` ssh: signature "ssh-rsa" not compatible with selected algorithm "rsa-sha2-512" ``` This is reproducible On Ubuntu 18.04, which ships gpg-agent v2.2.4 and OpenSSH v7.6. That version of gpg-agent does not support `rsa-sha2-256` or `rsa-sha2-512`, but OpenSSH does. As a result, OpenSSH specifies `rsa-sha-512` as the public key algorithm to use in the user authentication request message, but gpg-agent includes an `ssh-rsa` signature. OpenSSH servers tolerates this discrepancy, but the Go implementation fails because it expects a strict match. This commit pulls in https://gitlab.com/gitlab-org/golang-crypto/-/merge_requests/9 to fix the problem. Relates to: 1. golang/go#53391 2. https://gitlab.com/gitlab-org/gitlab-shell/-/issues/587 Changelog: fixed
When we put gitlab-sshd in production, we noticed a number of clients using RSA keys would fail to login. The server would report: ``` ssh: signature "ssh-rsa" not compatible with selected algorithm "rsa-sha2-512" ``` This is reproducible on Ubuntu 18.04, which ships gpg-agent v2.2.4 and OpenSSH v7.6. That version of gpg-agent does not support `rsa-sha2-256` or `rsa-sha2-512`, but OpenSSH does. As a result, OpenSSH specifies `rsa-sha-512` as the public key algorithm to use in the user authentication request message, but gpg-agent includes an `ssh-rsa` signature. OpenSSH servers tolerates this discrepancy, but the Go implementation fails because it expects a strict match. This commit pulls in https://gitlab.com/gitlab-org/golang-crypto/-/merge_requests/9 to fix the problem. Relates to: 1. golang/go#53391 2. https://gitlab.com/gitlab-org/gitlab-shell/-/issues/587 Changelog: fixed
Buggy SSH clients, such as gpg-agent v2.2.4 and OpenSSH v7.6 shipped in Ubuntu 18.04, may send `ssh-rsa-512` as the public key algorithm but actually include an `rsa-sha` signature. If RFC 3808 (extension negotiation) is implemented, these clients will fail to authenticate with the error: ``` ssh: signature "ssh-rsa" came in for selected algorithm "rsa-sha2-512", public key is type ssh-rsa ``` According to RFC 8332 section 3.2: If the client includes the signature field, the client MUST encode the same algorithm name in the signature as in SSH_MSG_USERAUTH_REQUEST -- either "rsa-sha2-256" or "rsa-sha2-512". If a server receives a mismatching request, it MAY apply arbitrary authentication penalties, including but not limited to authentication failure or disconnect. ...A server MAY, but is not required to, accept this variant or another variant that corresponds to a good-faith implementation and is considered safe to accept. While the client is expected to do the right thing, in practice older clients may not fully support `ssh-rsa-256` and `ssh-rsa-512`. For example, gpg-agent v2.2.6 added support for these newer signature types. To accomodate these clients, relax the mat constraint: if the `SSH_MSG_USERAUTH_REQUEST` message specifies an RSA public key algorithm and includes an RSA public key, then allow any of the following signature types: - `rsa-sha-512` - `rsa-sha-256` - `rsa-sha` This emulates what OpenSSH does. OpenSSH only considers that the RSA family is specified and then verifies if the signature and public key match. Closes golang/go#53391
Buggy SSH clients, such as gpg-agent v2.2.4 and OpenSSH v7.6 shipped in Ubuntu 18.04, may send `ssh-rsa-512` as the public key algorithm but actually include an `rsa-sha` signature. If RFC 3808 (extension negotiation) is implemented, these clients will fail to authenticate with the error: ``` ssh: signature "ssh-rsa" came in for selected algorithm "rsa-sha2-512", public key is type ssh-rsa ``` According to RFC 8332 section 3.2: If the client includes the signature field, the client MUST encode the same algorithm name in the signature as in SSH_MSG_USERAUTH_REQUEST -- either "rsa-sha2-256" or "rsa-sha2-512". If a server receives a mismatching request, it MAY apply arbitrary authentication penalties, including but not limited to authentication failure or disconnect. ...A server MAY, but is not required to, accept this variant or another variant that corresponds to a good-faith implementation and is considered safe to accept. While the client is expected to do the right thing, in practice older clients may not fully support `ssh-rsa-256` and `ssh-rsa-512`. For example, gpg-agent v2.2.6 added support for these newer signature types. To accomodate these clients, relax the matching constraint: if the `SSH_MSG_USERAUTH_REQUEST` message specifies an RSA public key algorithm and includes an RSA public key, then allow any of the following signature types: - `rsa-sha-512` - `rsa-sha-256` - `rsa-sha` This emulates what OpenSSH does. OpenSSH only considers that the RSA family is specified and then verifies if the signature and public key match. Closes golang/go#53391
Buggy SSH clients, such as gpg-agent v2.2.4 and OpenSSH v7.6 shipped in Ubuntu 18.04, may send `ssh-rsa-512` as the public key algorithm but actually include an `rsa-sha` signature. If RFC 3808 (extension negotiation) is implemented, these clients will fail to authenticate with the error: ``` ssh: signature "ssh-rsa" came in for selected algorithm "rsa-sha2-512", public key is type ssh-rsa ``` According to RFC 8332 section 3.2: If the client includes the signature field, the client MUST encode the same algorithm name in the signature as in SSH_MSG_USERAUTH_REQUEST -- either "rsa-sha2-256" or "rsa-sha2-512". If a server receives a mismatching request, it MAY apply arbitrary authentication penalties, including but not limited to authentication failure or disconnect. ...A server MAY, but is not required to, accept this variant or another variant that corresponds to a good-faith implementation and is considered safe to accept. While the client is expected to do the right thing, in practice older clients may not fully support `ssh-rsa-256` and `ssh-rsa-512`. For example, gpg-agent v2.2.6 added support for these newer signature types. To accomodate these clients, relax the matching constraint: if the `SSH_MSG_USERAUTH_REQUEST` message specifies an RSA public key algorithm and includes an RSA public key, then allow any of the following signature types: - `rsa-sha-512` - `rsa-sha-256` - `rsa-sha` This emulates what OpenSSH does. OpenSSH only considers that the RSA family is specified and then verifies if the signature and public key match. Closes golang/go#53391
Buggy SSH clients, such as gpg-agent v2.2.4 and OpenSSH v7.6 shipped in Ubuntu 18.04, may send `ssh-rsa-512` as the public key algorithm but actually include an `rsa-sha` signature. If RFC 3808 (extension negotiation) is implemented, these clients will fail to authenticate with the error: ``` ssh: signature "ssh-rsa" came in for selected algorithm "rsa-sha2-512", public key is type ssh-rsa ``` According to RFC 8332 section 3.2: If the client includes the signature field, the client MUST encode the same algorithm name in the signature as in SSH_MSG_USERAUTH_REQUEST -- either "rsa-sha2-256" or "rsa-sha2-512". If a server receives a mismatching request, it MAY apply arbitrary authentication penalties, including but not limited to authentication failure or disconnect. ...A server MAY, but is not required to, accept this variant or another variant that corresponds to a good-faith implementation and is considered safe to accept. While the client is expected to do the right thing, in practice older clients may not fully support `ssh-rsa-256` and `ssh-rsa-512`. For example, gpg-agent v2.2.6 added support for these newer signature types. To accomodate these clients, relax the matching constraint: if the `SSH_MSG_USERAUTH_REQUEST` message specifies an RSA public key algorithm and includes an RSA public key, then allow any of the following signature types: - `rsa-sha-512` - `rsa-sha-256` - `rsa-sha` This emulates what OpenSSH does. OpenSSH only considers that the RSA family is specified and then verifies if the signature and public key match. Closes golang/go#53391
What version of Go are you using (
go version
)?Does this issue reproduce with the latest release?
No, but if SSH server extension is implemented (golang/crypto#197), this issue will show up under certain circumstances for older clients.
What did you do?
I applied golang/crypto#197, which implements RFC 3808 (server extension negotiation), to the
master
branch. Then I attempted to log into a Go SSH server with an Yubikey RSA key on Ubuntu 18.04. The login failed:In https://github.com/golang/crypto/blob/793ad666bf5ec61392092b27061be9618e4e219b/ssh/server.go#L567, the SSH server performs this check:
This is a sensible check and works for most cases. However, in Ubuntu 18.04 with
gpg-agent
v2.2.4 and OpenSSH v7.6, logins that use an RSA key withgpg-agent
will fail to login. This problem does not happen with an OpenSSH server, however.What did you expect to see?
As the example from RFC8332 shows, here is an example SSH_MSG_USERAUTH_REQUEST message:
Why does this happen? Since the server advertises it supports
rsa-sha2-512
, the OpenSSH client will attempt to use it in the signature. However,gpg-agent
v2.2.4 does not supportrsa-sha2-512
; this was added in v2.2.6 via gpg/gnupg@80b775b. As a result, it appears that theSSH_MSG_USERAUTH_REQUEST
hasrsa-sha2-512
in 1 butssh-sha
for 3.The Go crypto library expects that 1 and 3 match. However, OpenSSH is a bit more lenient, and it only checks that 1 is an RSA algorithm (
rsa-dsa
,rsa-sha2-256
, orrsa-sha2-512
), and that this matches with an RSA key in 2. In more detail:sshkey_type_from_name(pkalg)
returnsKEY_RSA
type (https://github.com/openssh/openssh-portable/blob/0f3455356bc284d7c6f4d3c1614d31161bd5dcc2/sshkey.c#L91-L94).KEY_RSA
, so https://github.com/openssh/openssh-portable/blob/abd59663df37a42152e37980113ccaa405b9a282/auth2-pubkey.c#L127 matches.ssh_rsa_verify
in https://github.com/openssh/openssh-portable/blob/83fa3a044891887369ce8b487ce88d713a04df48/ssh-rsa.c#L222. It determines the signature format in 3.https://datatracker.ietf.org/doc/html/rfc8332#section-3.2 speaks to the problem we're seeing here:
Technically, the spec says here that the strict match on the server side is acceptable, but the spec also says that a server may relax this match since we know that:
SSH_MSG_USERAUTH_REQUEST
public key algorithm isssh-rsa
.rsa-sha
.rsa-sha
,rsa-sha2-256
, orrsa-sha2-512
.I realize this may just be covering up old bugs related to
gpg-agent
or OpenSSH, but that's what we're seeing in the wild.The text was updated successfully, but these errors were encountered: