CVSS 5.3 CVE-2016-20012
CVSS 5.3 CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N
OpenSSH through 8.7 allows remote attackers, who have a suspicion that a certain combination of username and public key is known to an SSH server, to test whether this suspicion is correct. This occurs because a challenge is sent only when that combination could be valid for a login session.
Description
The only required authentication ‘method name’ is “publickey” authentication. All implementations must support this method; however, not all users need to have public keys.
This makes it complicated to find out, if a user is allowed to login and wants to use publickey authentication or another method like password. The reason is, because publickey authentication comes before password authentication.
For a man in the middle server, it’s important to know, which authentication method will be used by the client. This information can be queried from the destination server.
All SSH server implementations must provide a method, which allows the client to check if a given username and publickey combination is known by the server.
The reason for implementing this method was because 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.
The server must respond to this message with either
SSH_MSG_USERAUTH_FAILURE or with the following:
graph TD
A[SSH Client] -->|send publickey| B(OpenSSH)
B --> C{<b>username</b><br> and<br> <b>publickey</b><br>known?}
C -->|yes| D[send<br><b>SSH_MSG_USERAUTH_PK_OK</b>]
C -->|no| E[send<br><b>SSH_MSG_USERAUTH_FAILURE</b>]
Note
According to RFC-4252 the client is not required to complete the authentication process.
If the client receives a SSH_MSG_USERAUTH_PK_OK message, the username/publickey combination is known by the server.
When a SSH_MSG_USERAUTH_FAILURE the client can send a new username/publickey combination to the server.
If no valid combination was found and no publickeys are left, the user is not allowed to login with publickey authentication.
This allowed a man in the middle server to check, if the intercepted user is allowed to login with publickey authentication or not.
OpenSSH refers to this behavior as the user validity oracle: the server acts as an oracle that answers the question “would this username and public key be valid for authentication?” — without requiring the client to prove it holds the private key.
Role in SSH-MITM’s attack chain
The user validity oracle serves two distinct purposes in SSH-MITM.
During an active MITM session
When a victim connects and offers a public key, SSH-MITM queries the user validity oracle on the real server for each key the client presents — before accepting or rejecting the authentication. The server’s response reveals:
whether the victim intends to use public key authentication
which specific key the real server will accept
This is how SSH-MITM determines the authentication method and key in use, and is the prerequisite for follow-up techniques such as trivial authentication.
During reconnaissance (standalone)
The ssh-mitm check-publickey subcommand queries the user validity oracle
on target servers to map which keys grant access to which accounts — without
establishing a full session or needing any private key material. See
Get Started for the tutorial chapter on this technique.
Test with SSH-MITM
SSH-MITM’s authentication process implements this method to check if the intercepted user is allowed to login with publickey authentication on the remote server.
There is also a standalone check available, which allows during an audit to check a username/publickey combination against a server.
If you are using SSH-MITM <= 4.x.x you must use the audit subcommand.
$ ssh-mitm audit check-publickey --host 127.0.0.1 \
--username testuser \
--public-key ~/.ssh/id_rsa.pub
valid key
SSH-MITM 5 and later implemented the check-publickey as its own subcommand.
$ ssh-mitm check-publickey --host 127.0.0.1 \
--username testuser \
--public-keys ~/.ssh/id_rsa.pub
The --public-keys flag also accepts a URL, which makes it straightforward
to test keys fetched directly from a GitHub, GitLab, or similar profile:
$ ssh-mitm check-publickey --host target \
--username alice \
--public-keys https://github.com/alice.keys
References
Tip
Try it in the tutorial
Chapter 6 of the interactive tutorial demonstrates CVE-2016-20012
live — SSH-MITM fetches user123’s public keys from an internal GitLab
instance and tests them against target servers using check-publickey:
$ ssh-mitm tutorial
See Get Started for the full tutorial list.