Skip to content
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

CVE-2016-20012 - Publickey Information leak - Only allow SSH_MSG_USERAUTH_REQUEST with signature #270

Closed
wants to merge 10 commits into from

Conversation

manfred-kaiser
Copy link

@manfred-kaiser manfred-kaiser commented Sep 15, 2021

CVE: https://nvd.nist.gov/vuln/detail/CVE-2016-20012

This pull request adds a new configuration option to the server to disable user enumeration when using publickey authentication.

The user enumeration was first mentioned on 6. june 2002:

* XXX this allows testing whether a user is allowed
* to login: if you happen to have a valid pubkey this
* message is sent. the message is NEVER sent at all
* if a user is not allowed to login. is this an
* issue? -markus

Publickey authentication:

Publickey authentication is defined in RFC-4252 (released January 2006)

A client is allowed to ask the server, if a specific public key is known by the server. This allows the client to generate a signature only if it's necessary. If the publickey is not known, no signature must be created.

Private keys are often stored in an encrypted form at the client
host, and the user must supply a passphrase before the signature can
be generated. Even if they are not, the signing operation involves
some expensive computation. To avoid unnecessary processing and user
interaction, the following message is provided for querying whether
authentication using the "publickey" method would be acceptable.

 byte      SSH_MSG_USERAUTH_REQUEST

This behavior allows an attacker to check if a user is allowed to login.

RFC-4252 also defines, that it's allowed to send a SSH_MSG_USERAUTH_REQUEST with a signature directly:

To perform actual authentication, the client MAY then send a
signature generated using the private key. The client MAY send the
signature directly without first verifying whether the key is
acceptable. The signature is sent using the following packet:

 byte      SSH_MSG_USERAUTH_REQUEST

The patch

This patch adds a new configuration option to the OpenSSH server: PubkeyDisablePKCheck no

If this configuration option is enbabled, the client is not able to send a SSH_MSG_USERAUTH_REQUEST without signature. In cases, when a client asks the server if a publickey is known, the server denies the login.

A patch was also applied to the client, because the client allways asks the server if a publickey is known. Even, when the configuration option IdentitiesOnly is enabled.

If the client was configured with IdentitiesOnly, SSH_MSG_USERAUTH_REQUEST with a signature is directly sent to the server. This makes the OpenSSH Client compatible with the server.

Other clients

I have created a patch for PuTTY, to make PuTTY compatible with the new setting: https://github.com/manfred-kaiser/putty/commit/5e33243c57aef8aa12a9c8aa0d198c66834aaaa1

This patch was sent to Simon Tatham (PuTTY developer), with a request to merge it in the next release.

WinSCP, Filezille and other clients, which are based on PuTTY can use the new configuration option. So they should be compatible in the near future.

@manfred-kaiser
Copy link
Author

I made this information public, because this vulnerability is public known at least since 2016!

https://utcc.utoronto.ca/~cks/space/blog/tech/SSHKeysAreInfoLeak

I also found a script, which was created in 2019, which is able to do the user enumeration:
https://rushter.com/blog/public-ssh-keys/

@djmdjm
Copy link
Contributor

djmdjm commented Sep 16, 2021

There is no "user enumeration" here. This feature allows testing whether a particular key may be accepted by a particular account. There is no general way to query which accounts are valid without valid public keys for each one, much less the ability to enumerate all the accounts on a system. At most, it is an account existence oracle and a limited one at that.

OpenSSH has long had a policy of not treating account existence oracles as security bugs. E.g. https://www.openwall.com/lists/oss-security/2018/08/24/1

The motivation for this feature is to avoid unnecessary unwrapping and exposure of private keys. Removing or disabling it would likely result in users exposing more keys via ssh-agent or by password-less files. We have judged the consequences to outweigh the benefits.

@manfred-kaiser manfred-kaiser changed the title Publickey User Enumeration - Only allow SSH_MSG_USERAUTH_REQUEST with signature CVE-2016-20012 - Publickey User Enumeration - Only allow SSH_MSG_USERAUTH_REQUEST with signature Sep 16, 2021
@manfred-kaiser
Copy link
Author

manfred-kaiser commented Sep 16, 2021

Server side:

It's an optional feature and disabled by default. So this will not change the behavior in default installations!
An administrator has to enable this feature on the server.

Client side:

A connection has to be configured with IdentitiesOnly yes and IdentityFile /home/user/.ssh/id_rsa.

The important config option is IdentitiesOnly yes, because when this option is enabled, only the configured keys are used. So there is no exposing of keys or the need of unencrypted keys!

This configuration option already exists and is not added by the patch. I only changed the bahavior. If this option is configured, the client send SSH_MSG_USERAUTH_REQUEST with a signature, instead of asking, if a publickey is usable. This is allowed in RFC-4252.

The user has to configure the keys, which should be used to login to a server. This does not expose any unused keys or bother the user to enter a password for a key, which is not usable (as long as the user has not accidentally configured a wrong key).

If you think, that the IdentitiesOnly config option should not be used, a new option can be added. But my intention was not to make it more complicated as necessary.

Further steps:

I think, the users/administrators should decide, if they want to enable the new setting or not.
But it's important, that the administrators know the advantages and disadvantages about the new config option.

As a developer, we should not decide how the software should be used. We should give the users options and let them choose how to use it.

Disclosure

I'm working on an audit tool for ssh. This tool is capable of man in the middle attacks. In the past it was not able to spoof the login process. The reason was, that a mitm server didn't know, how the client wants to login to the server.

With this information leak, my tool is able to check, if the users wants to login with password or with publickey authentication. If publickey authentication is possible, my tool accepts the same key as the destination server, which allows other spoofing attacks (we already talked about that).

I know, that the fingerprint mitigates man in the middle attacks, but how many users really compare the fingerprint to a trusted source? But this is another problem...

@manfred-kaiser manfred-kaiser changed the title CVE-2016-20012 - Publickey User Enumeration - Only allow SSH_MSG_USERAUTH_REQUEST with signature CVE-2016-20012 - Publickey Information leak - Only allow SSH_MSG_USERAUTH_REQUEST with signature Sep 16, 2021
@manfred-kaiser
Copy link
Author

fixed the initial value for options->pubkey_disable_pk_check = 0; in servconf.c, which enabled the new feature PubkeyDisablePKCheck if it was not set in the config file.

Now the tests should run without errors and the new option is disabled.

@manfred-kaiser
Copy link
Author

I'm getting an error for the agent tests 😞

ok connect after login grace timeout
run test agent.sh ...

WARNING: Unsafe (group or world writable) directory permissions found:
 /home/user/openssh-portable/regress /home/user/openssh-portable /home/user

These could be abused to locally escalate privileges.  If you are
sure that this is not a risk (eg there are no other users), you can
bypass this check by setting TEST_SSH_UNSAFE_PERMISSIONS=1

ssh connect with failed (exit code 255)
...
ssh connect with failed (exit code 255)
failed simple agent test
make[1]: *** [Makefile:219: t-exec] Fehler 1

The reason is, that I'm reusing the IdentitiesOnly config option to send the SSH_MSG_USERAUTH_REQUEST directly, which breaks the tests 😞

@manfred-kaiser
Copy link
Author

I have added a new configuration option PubkeyDisablePKCheck to the client.

It was not intended to introduce a new one, but by reusing IdentitiesOnly the tests failed 😞

The behavior of the client is only changed when PubkeyDisablePKCheck and IdentitiesOnly is set!

If one setting is not enabled, it uses the default behavior and asks if a public key is allowed.

Example config for a client, which sends a SSH_MSG_USERAUTH_REQUEST with a signature directly:

Host testhost
     HostName localhost
     User user
     Port 10022
     PubkeyDisablePKCheck yes
     IdentitiesOnly yes
     IdentityFile /home/user/.ssh/id_rsa

@manfred-kaiser
Copy link
Author

I have fixed a copy&paste error 😞 and the tests are working now.

Please review the code!

If I should change some things, please write back.

@manfred-kaiser manfred-kaiser marked this pull request as draft September 18, 2021 07:51
@mfriedl
Copy link
Contributor

mfriedl commented Oct 13, 2021

As back in 2002 I still think it's not a big problem and the current behaviour is preferable over the problem caused by the suggested changes.

@manfred-kaiser
Copy link
Author

As back in 2002 I still think it's not a big problem and the current behaviour is preferable over the problem caused by the suggested changes.

@mfriedl sorry for the inconvenience 😞

That's right, that changing the behaviour will break compatibility with most clients and libraries, because they rely on the publickey lookup step.

I understand your argument, that such a change will result in more problems for the users. They are forced to use compatible clients, which does not exist. The ssh client and library developers have to rewrite their libraries and other applications have to be changed to work with the new libraries.

On the other side, there is an information leak, which can be used for targeted man in the middle attacks. As long as the users validates the fingerprint and does not connect to an untrusted server this should not be a big problem.

But users does not validate the fingerprint and they are using agent forwarding. Even if you are using ssh-askpass, it's possible to compromise the session and this information leak is an important part for the man in the middle attack.

@mfriedl I have invited you to my git repo for the presentation, which I presented on "CERT Stammtisch" 😉

@djmdjm
Copy link
Contributor

djmdjm commented Oct 15, 2021 via email

@manfred-kaiser
Copy link
Author

manfred-kaiser commented Oct 18, 2021

The reason for this pull request was to discuss the main problem, that users does not verify fingerprints and ignore warnings about changed host keys. Also #258 was to reduce the risk of mitm attacks when a wrong fingerprint was already accepted.

It's not a problem of incompatibility. This can AFAIK be avoided by having the server return success for all PK_OK trials.

As you wrote, returning PK_OK is a security issue and should be avoided.

The only solution is to configure the private key and send a signature directly, which is allowed by RFC-4252 but most/all clients does not support this feature.

Without braking compatibility or introducing new security issues, it's not possible to mitigate this information leak.

I believe this optimises for a case where security has already been forgone (an attacker has successfully impersonated a trusted host) in a way that has negative consequences for every other user of the protocol. IMO this is a bad tradeoff

I know, that the suggested changes are only workarounds, but a lot of users does not verify the fingerprint.

By using SSHFP records or certificates, mitm attacks should not be possible, but such a setup is complicated. A lot of servers does not have a dns recored and a lot of domains are not protected with DNSSEC. Setting up and manage a CA requires a lot of knowledge and work.

Server administrators already have problems to provide the fingerprint via a trusted source.

Example: Recently I had to connect to a virtual machine from a large and well known hosting company and when I connected for the first time over ssh I had to verify the fingerprint. In the web based management interface there was no option to display the server fingerprint. I wrote the support, that I need to verify the fingerprint of my server. The support member knows, that it's important to verify it, but there was no option for them to get the server fingerprint. So I had 2 options: Accepting the fingerprint with the risk of a mitm attack or not using the server and doing my work.

  • How can a administrators be forced to provide fingerprints via a trusted source?
  • How can I force a user to verify the fingerprint and not accepting it without verification?

@manfred-kaiser
Copy link
Author

Thinking about the problem, all suggested changes wont help to reduce the risk during mitm attacks.

If you need to connect to a server for the first time, most servers does not know your public key and you need to login with password authentication. So there is always the risk for full a man in the middle attack, if the fingerprint is not verified

But in most cases, you have no option to copy the public key to the server without using ssh.

So how can we enforce publishing the fingerprint via trusted sources to all server administrators? I think this is the main problem and the only possible solution to mitigate mitm attacks.

@manfred-kaiser
Copy link
Author

manfred-kaiser commented Oct 20, 2021

Thinking about the problem, all suggested changes wont help to reduce the risk during mitm attacks.

In the last posts I talked about a mitm attack, when the user connects to another server and accepts the server fingerprint. In those cases, the suggested changes won't help to mitigate mitm attacks.

What I have missed is when the user connects to a compromised server. The best example is the Matrix hack from 2019. A developer connected to a compromised server. This is not a classic mitm scenario, where the fingerprint can protect the user.

They have a good writeup: https://matrix.org/blog/2019/05/08/post-mortem-and-remediations-for-apr-11-security-incident#ssh

When agent forwarding is not used, the attacker is only able to monitor the compromised server but is not able to compromise other servers.

If an agent was accidentally forwarded, the attacker is able to compromise other servers. Even if you use 2 factor authentication with fido2 tokens. This is the point, where my suggested changes come in.

With CVE-2021-36368 (#258) the attacker is able to spoof a fido2 token and CVE-2016-20012 (#270) can be used to find out which key must be spoofed.

As long as the users are using agent forwarding and does not verify the fingerprint against trusted sources, there is always the risk to get compromised.

How can I enforce such rules to all users?

@djmdjm @mfriedl So what do you recommend?

Copy link

@mahesh621 mahesh621 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link

@mahesh621 mahesh621 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.

@manfred-kaiser
Copy link
Author

manfred-kaiser commented Oct 22, 2021

@mahesh621 you wrote, that you have tested the patch and a login was not successful. Have you used a patched client?

There is also a patch for the openssh client, which have to be applied. As we discussed, at the moment most clients are not compatible with my suggested configuration option.

You have to use the patched client and configured the connection?

Host testhost
     HostName localhost
     User user
     Port 10022
     PubkeyDisablePKCheck yes
     IdentitiesOnly yes
     IdentityFile /home/user/.ssh/id_rsa
  • PubkeyDisablePKCheck - disable publickey lookup in the client and send signature directly, which is RFC-4252 conform
  • IdentitiesOnly - only use configured keys. So there is no need to unwrap unused keys
  • IdentityFile - key, which is used to login to the server

Both Options PubkeyDisablePKCheck and IdentitiesOnly must be configured. If you forgot to configure one option, the client uses the old behaviour and a login is not possible. If IdentitiesOnly is used, you must configure IdentityFile.

So all three options must be configured to be compatible!

On the ServerSide, you have to only configure PubkeyDisablePKCheck yes. But as you wrote, this already works.

Note: This setup is not compatible with agent forwarding, but in my opinion agent forwarding is a security issue, and should not be used!

@manfred-kaiser
Copy link
Author

manfred-kaiser commented Oct 22, 2021

@mahesh621 You have applied the patch to OpenSSH 7.6, I have not tested, if the patch works with this version.

The easiest way is to checkout the patch for CVE-2016-20012 is to use my repo https://github.com/manfred-kaiser/openssh-portable because there are some conflicts with the current master at the moment, which I have to resolve.

If you are interested, I have another fork, which is up to date with the latest master and where the patches for CVE-2016-20012 (#270) and CVE-2021-36368 (#258) are applied: https://github.com/ssh-mitm/openssh-portable

Copy link

@mahesh621 mahesh621 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@manfred-kaiser
Has this proposed patch been accepted by the openssh maintainers and integrated latest OPNESSH version?

@manfred-kaiser
Copy link
Author

@manfred-kaiser Has this proposed patch been accepted by the openssh maintainers and integrated latest OPNESSH version?

Sorry for the late response. This patch was not merged, because it would break too much things.

I've done some tests, but all tested clients rely on the SSH_MSG_USERAUTH_REQUEST method - even in cases when only one private key was used.

There might be a risk using the SSH_MSG_USERAUTH_REQUEST request, because this information can be used during mitm attacks to verify if the intercepted user is allowed to login with publickey authentication or not. This behavior can be used to determine the correct authentication method for the remote server.

@cjwangd
Copy link

cjwangd commented Jun 15, 2022

could you fix it as soon as possible?

@manfred-kaiser
Copy link
Author

manfred-kaiser commented Jun 15, 2022

could you fix it as soon as possible?

As I mentioned, this feature can improve security, but lacks compatibility with nearly all available clients.

At the mement I don't recommend using this feature.

If you are still interested in this feature, you can use my fork: https://github.com/manfred-kaiser/openssh-enhanced

I keep this fork up to date with the latest master from OpenSSH.

@ymecho
Copy link

ymecho commented Jul 13, 2022

Is this issue fixed now?

@daztucker
Copy link
Contributor

The opinion of the OpenSSH team is that this change causes more problems than it solves and we do not intend to apply it. (See Damien's earlier comment for more details.) If you disagree you are welcome to use Manfred's fork.

@manfred-kaiser
Copy link
Author

manfred-kaiser commented Jul 13, 2022

Is this issue fixed now?

This "issue" won't get fixed in the near future. One reason is, most (all?) clients rely on the publickey lookup. It also makes ssh more difficult to use and more error prone - you have to configure each connection.

In my opinion, if you want to get rid of the publickey lookup, you have to patch the clients first to be compatible with such a big change.

But keep in mind this will introduce more problems -> there are applications which rely on unmaintained libraries or will get abandoned in the near future. For example the maintainer of sshfs has stopped development and looks for a new maintainer. With such big changes I fear more developers will stop maintaining their projects.

For example the deprecation of the sha1 algorithms introduced serious problems because a lot of projects where not able provide a compatible version in time. Some of those applications are still not fully compatible or has some errors in handling the introduced features.

One reason for opening this pull request was to discuss the publickey lookup and show the security implications but @daztucker and @djmdjm and even Simon Tatham (PuTTY developer) convinced me that it's a bad idea to disable the publickey lookup.

@ymecho At the moment I recommend using my fork only for testing purposes but if you really want this feature you are free to use my fork. But keep in mind, I'm only updating the source code - I don't provide ready to use packages.

@897221242
Copy link

May I ask if the building CVE-2016-20012 has been fixed in the openssh-9.3p2.tar.gz version? Thank you

@daztucker
Copy link
Contributor

May I ask if the building CVE-2016-20012 has been fixed in the openssh-9.3p2.tar.gz version? Thank you

The OpenSSH team does not intend to change anything regarding this behaviour as in our opinion the existing proposals to change it cause more problems than they solve. It's arguable that whether or not there should even be a CVE since the behaviour is part of the spec.

@manfred-kaiser
Copy link
Author

manfred-kaiser commented Jul 24, 2023

May I ask if the building CVE-2016-20012 has been fixed in the openssh-9.3p2.tar.gz version? Thank you

The behavior is defined in RFC 4252.

Private keys are often stored in an encrypted form at the client
host, and the user must supply a passphrase before the signature can
be generated. ... To avoid unnecessary processing and user
interaction, the following message is provided for querying whether
authentication using the "publickey" method would be acceptable.

According to the RFC this step is optional but at the moment ALL major ssh client implementations require this step.

So the proposed change will slightly increase security but the result is, that you don't have any compatible ssh clients, which is a much bigger problem.

@897221242 if you really want to get this "fixed" you should propose a change to RFC 4252 and implement compatible authentication procedures in all major ssh clients and libraries.

This pull request was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
8 participants