jtesta / ssh-audit

SSH server & client security auditing (banner, key exchange, encryption, mac, compression, compatibility, security, etc)
MIT License
3.33k stars 174 forks source link

Should ssh-audit Scan for User Key Algorithms? #128

Open thecliguy opened 2 years ago

thecliguy commented 2 years ago

I was recently working on a project where GoAnywhere Managed File Transfer was used as an SFTP file transfer client. I noticed a feature that I've never seen in a file transfer client before which is the ability to configure the RSA Key Signature Algorithm that's used when authentication is performed with an RSA key pair (instead of a password).

This got me thinking about something...

The algorithm that's used in conjunction with a host key is not necessarily the same as the algorithm that's used in conjunction with a user key (for authentication). So for example, on an OpenSSH server instance you may have disabled ssh-rsa being used in conjunction with host keys but it can probably still be used in conjunction with user keys.

The question I'm uncertain about is from a security perspective is should we care which algorithms can potentially be used by a client or server in conjunction with user keys? If we should care about this then is it possible for ssh-audit to scan for this?

My understanding is that host key algorithms are easy to identify because they're advertised as part of the Key Exchange Initalization (SSH_MSG_KEXINIT). But I'm uncertain whether the algorithms used in conjunction with user keys are so easily identifiable?

See examples below demonstrating the effect of changing the RSA Key Signature Algorithm value in GoAnywhere Managed File Transfer:

EXAMPLES

Example 1: OpenSSH 8.2p1 on Ubuntu 20.04 LTS using WSL2

To prove that the host key algorithms have no influence on the the algorithms used in conjunction with a user key, the only enabled host key algorithm on both the client and the server was ecdsa-sha2-nistp256, see ssh-audit excerpts below:

--------------------------------------------------------------------------------
Client
======

# host-key algorithms
(key) ecdsa-sha2-nistp256                   -- [fail] using weak elliptic curves
                                            `- [warn] using weak random number generator could reveal the key
                                            `- [info] available since OpenSSH 5.7, Dropbear SSH 2013.62
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
Server
======

# host-key algorithms
(key) ecdsa-sha2-nistp256                   -- [fail] using weak elliptic curves
                                            `- [warn] using weak random number generator could reveal the key
                                            `- [info] available since OpenSSH 5.7, Dropbear SSH 2013.62
--------------------------------------------------------------------------------

I performed the following tests where you can see the influence that GoAnywhere's 'RSA Key Signature Algorithm' setting has in the logs produced by OpenSSH.

(NB: OpenSSH server's LogLevel was set to DEBUG3 in /etc/ssh/sshd_config)

Test 1: 'RSA Key Signature Algorithm' in GoAnywhere set to 'ssh-rsa'

thecliguy@SANDBOX:~$ sudo tail -f /var/log/auth.log | grep userauth_pubkey
Nov  2 20:58:16 SANDBOX sshd[1423]: debug2: userauth_pubkey: valid user thecliguy querying public key ssh-rsa REDACTED [preauth]
Nov  2 20:58:16 SANDBOX sshd[1423]: debug1: userauth_pubkey: test pkalg ssh-rsa pkblob RSA SHA256:REDACTED [preauth]
Nov  2 20:58:16 SANDBOX sshd[1423]: debug2: userauth_pubkey: authenticated 0 pkalg ssh-rsa [preauth]
Nov  2 20:58:16 SANDBOX sshd[1423]: debug2: userauth_pubkey: valid user thecliguy attempting public key ssh-rsa REDACTED [preauth]
Nov  2 20:58:16 SANDBOX sshd[1423]: debug3: userauth_pubkey: have ssh-rsa signature for RSA SHA256:REDACTED [preauth]
Nov  2 20:58:16 SANDBOX sshd[1423]: debug2: userauth_pubkey: authenticated 1 pkalg ssh-rsa [preauth]

Test 2: 'RSA Key Signature Algorithm' in GoAnywhere set to 'rsa-sha2-256'

thecliguy@SANDBOX:~$ sudo tail -f /var/log/auth.log | grep userauth_pubkey
Nov  2 20:58:47 SANDBOX sshd[1504]: debug2: userauth_pubkey: valid user thecliguy querying public key rsa-sha2-256 REDACTED [preauth]
Nov  2 20:58:47 SANDBOX sshd[1504]: debug1: userauth_pubkey: test pkalg rsa-sha2-256 pkblob RSA SHA256:REDACTED [preauth]
Nov  2 20:58:47 SANDBOX sshd[1504]: debug2: userauth_pubkey: authenticated 0 pkalg rsa-sha2-256 [preauth]
Nov  2 20:58:47 SANDBOX sshd[1504]: debug2: userauth_pubkey: valid user thecliguy attempting public key rsa-sha2-256 REDACTED [preauth]
Nov  2 20:58:47 SANDBOX sshd[1504]: debug3: userauth_pubkey: have rsa-sha2-256 signature for RSA SHA256:REDACTED [preauth]
Nov  2 20:58:47 SANDBOX sshd[1504]: debug2: userauth_pubkey: authenticated 1 pkalg rsa-sha2-256 [preauth]

Test 3: 'RSA Key Signature Algorithm' in GoAnywhere set to 'rsa-sha2-512'

thecliguy@SANDBOX:~$ sudo tail -f /var/log/auth.log | grep userauth_pubkey
Nov  2 20:59:34 SANDBOX sshd[1619]: debug2: userauth_pubkey: valid user thecliguy querying public key rsa-sha2-512 REDACTED [preauth]
Nov  2 20:59:34 SANDBOX sshd[1619]: debug1: userauth_pubkey: test pkalg rsa-sha2-512 pkblob RSA SHA256:REDACTED [preauth]
Nov  2 20:59:34 SANDBOX sshd[1619]: debug2: userauth_pubkey: authenticated 0 pkalg rsa-sha2-512 [preauth]
Nov  2 20:59:34 SANDBOX sshd[1619]: debug2: userauth_pubkey: valid user thecliguy attempting public key rsa-sha2-512 REDACTED [preauth]
Nov  2 20:59:34 SANDBOX sshd[1619]: debug3: userauth_pubkey: have rsa-sha2-512 signature for RSA SHA256:REDACTED [preauth]
Nov  2 20:59:34 SANDBOX sshd[1619]: debug2: userauth_pubkey: authenticated 1 pkalg rsa-sha2-512 [preauth]

Example 2: CompleteFTP on Windows 10

To prove that the host key algorithms have no influence on the the algorithms used in conjunction with a user key, the only enabled host key algorithm on both the client and the server was ecdsa-sha2-nistp256, see ssh-audit excerpts below:

--------------------------------------------------------------------------------
# Client

# host-key algorithms
(key) ecdsa-sha2-nistp256                   -- [fail] using weak elliptic curves
                                            `- [warn] using weak random number generator could reveal the key
                                            `- [info] available since OpenSSH 5.7, Dropbear SSH 2013.62
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
# Server

# host-key algorithms
(key) ecdsa-sha2-nistp256                   -- [fail] using weak elliptic curves
                                            `- [warn] using weak random number generator could reveal the key
                                            `- [info] available since OpenSSH 5.7, Dropbear SSH 2013.62
--------------------------------------------------------------------------------

I performed the following tests where you can see the influence that GoAnywhere's 'RSA Key Signature Algorithm' setting has in the Diagnostics.log produced by CompleteFTP. It appears as though CompleteFTP only supports ssh-rsa therefore using 'rsa-sha2-256' and 'rsa-sha2-512' fail.

(NB: CompleteFTP's sever logging level was set to All)

Test 1: 'RSA Key Signature Algorithm' in GoAnywhere set to 'ssh-rsa'

2021-11-02 21:06:25,607 DEBUG SSHAuthService [Session.37:Default Site.5022:user?:127.0.0.1] ProcessPacket pt=SSH_MSG_USERAUTH_REQUEST 
2021-11-02 21:06:25,607 DEBUG SSHAuthService [Session.37:Default Site.5022:user?:127.0.0.1] Auth request - user=thecliguy, service=ssh-connection, method=publickey 
2021-11-02 21:06:25,607 DEBUG UserManager [Session.37:Default Site.5022:user?:127.0.0.1] GetSpecifiedUser: user=thecliguy 
2021-11-02 21:06:25,607 DEBUG UserManager [Session.37:Default Site.5022:user?:127.0.0.1] GetUserByID: user=fghsdfgb-34te-46fg-n3df-45dfg56dfdfg 
2021-11-02 21:06:25,607 DEBUG UserManager [Session.37:Default Site.5022:user?:127.0.0.1] Retrieved user from cache: fghsdfgb-34te-46fg-n3df-45dfg56dfdfg 
2021-11-02 21:06:25,607 DEBUG UserSession [Session.37:Default Site.5022:thecliguy:127.0.0.1] Session user set to 'thecliguy' 
2021-11-02 21:06:25,607 DEBUG PublicKeyAuthentication [Session.37:Default Site.5022:thecliguy:127.0.0.1] Client sent RSA public key

Test 2: 'RSA Key Signature Algorithm' in GoAnywhere set to 'rsa-sha2-256'

2021-11-02 21:09:39,960 DEBUG SSHAuthService [Session.39:Default Site.5022:user?:127.0.0.1] ProcessPacket pt=SSH_MSG_USERAUTH_REQUEST 
2021-11-02 21:09:39,960 DEBUG SSHAuthService [Session.39:Default Site.5022:user?:127.0.0.1] Auth request - user=thecliguy, service=ssh-connection, method=publickey 
2021-11-02 21:09:39,960 DEBUG UserManager [Session.39:Default Site.5022:user?:127.0.0.1] GetSpecifiedUser: user=thecliguy 
2021-11-02 21:09:39,960 DEBUG UserManager [Session.39:Default Site.5022:user?:127.0.0.1] GetUserByID: user=fghsdfgb-34te-46fg-n3df-45dfg56dfdfg 
2021-11-02 21:09:39,960 DEBUG UserManager [Session.39:Default Site.5022:user?:127.0.0.1] Retrieved user from cache: fghsdfgb-34te-46fg-n3df-45dfg56dfdfg 
2021-11-02 21:09:39,960 DEBUG UserSession [Session.39:Default Site.5022:thecliguy:127.0.0.1] Session user set to 'thecliguy' 
2021-11-02 21:09:39,960 WARN PublicKeyAuthentication [Session.39:Default Site.5022:thecliguy:127.0.0.1] Unknown public key algorithm rsa-sha2-256 

Test 3: 'RSA Key Signature Algorithm' in GoAnywhere set to 'rsa-sha2-512'

2021-11-02 21:12:46,215 DEBUG SSHAuthService [Session.41:Default Site.5022:user?:127.0.0.1] ProcessPacket pt=SSH_MSG_USERAUTH_REQUEST 
2021-11-02 21:12:46,215 DEBUG SSHAuthService [Session.41:Default Site.5022:user?:127.0.0.1] Auth request - user=thecliguy, service=ssh-connection, method=publickey 
2021-11-02 21:12:46,215 DEBUG UserManager [Session.41:Default Site.5022:user?:127.0.0.1] GetSpecifiedUser: user=thecliguy 
2021-11-02 21:12:46,215 DEBUG UserManager [Session.41:Default Site.5022:user?:127.0.0.1] GetUserByID: user=fghsdfgb-34te-46fg-n3df-45dfg56dfdfg 
2021-11-02 21:12:46,215 DEBUG UserManager [Session.41:Default Site.5022:user?:127.0.0.1] Retrieved user from cache: fghsdfgb-34te-46fg-n3df-45dfg56dfdfg 
2021-11-02 21:12:46,215 DEBUG UserSession [Session.41:Default Site.5022:thecliguy:127.0.0.1] Session user set to 'thecliguy' 
2021-11-02 21:12:46,215 WARN PublicKeyAuthentication [Session.41:Default Site.5022:thecliguy:127.0.0.1] Unknown public key algorithm rsa-sha2-512 
jtesta commented 2 years ago

Let me make sure I'm understanding what you're saying. You're talking about public key user authentication using weak algorithms even though the server is properly hardened?

Yes, that would be an issue. And it looks like OpenSSH supports restricting public key authentication algorithms too (see PubkeyAcceptedAlgorithms, CASignatureAlgorithms, and HostbasedAcceptedAlgorithms in: https://man.openbsd.org/sshd_config.5).

I think testing for pubkey auth algorithms can only be done after performing a handshake with the server. Given that one of ssh-audit's primary goals is to avoid external dependencies, this would mean doing more manual work. Although the hostkey tests already do some kex handshaking (see https://github.com/jtesta/ssh-audit/blob/5fbcb1b90f28e84c96bef4eb02f5a652604486a4/src/ssh_audit/hostkeytest.py#L138 ).

I can add this to my to-do list, though to be honest it may take a while (6+ months) before I'm able to write the patch. If anyone else would like to do it in the meantime, though, I'd happily accept the PR!

thecliguy commented 2 years ago

Hi Joe - In a nutshell, I'm proposing that we consider adding functionality to ssh-audit so that it can scan for pubkey auth algorithms.

I think it would be fascinating to have visibility of this especially when using client and server products where it's not configurable (or not even documented).

thecliguy commented 1 year ago

RFC 8308 defines an extension mechanism for SSH, enabling peers to signal support for and negotiate certain capabilities. One of the extensions to use this mechanism is server-sig-algs, where a server provides a client with list of signature algorithms that it supports as part of a publickey authentication. The client begins by including the value ext-info-c in the kex_algorithms field of a SSH_MSG_KEXINIT message that’s sent to a server and then prepares for the server to respond with an SSH_MSG_EXT_INFO message containing server-sig-algs=alg1,alg2,....

I'd like to try and make ssh-audit read server-sig-algs that's returned by a server. Here's how far I've got with a very rough proof of concept...

  1. Modified hostkeytest.py > perform_test > s.send_kexinit:
    # Include 'ext-info-c' in the kex_algorithms field of the SSH_MSG_KEXINIT message that’s sent to a server.
    s.send_kexinit(key_exchanges=[kex_str, 'ext-info-c'], hostkeys=[host_key_type], ciphers=server_kex.server.encryption, macs=server_kex.server.mac, compressions=server_kex.server.compression, languages=server_kex.server.languages)
  2. Once kex_group.send_init(s) is invoked, an OpenSSH server will now return an SSH_MSG_EXT_INFO message. This can be seen on an Ubuntu server by tailing /var/log/auth.log and grepping for SSH2_MSG_EXT_INFO when scanning with ssh-audit, EG:
    ~$ sudo tail -f /var/log/auth.log | grep SSH2_MSG_EXT_INFO
    Apr 29 23:57:18 SANDBOX01 sshd[241536]: debug1: Sending SSH2_MSG_EXT_INFO [preauth]

@jtesta : I've dabbled with various things but I really have no idea how to intercept and read the SSH_MSG_EXT_INFO message that's returned by an SSH server. Please can you offer some guidance on how to do this?