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

[exception] did not receive MSG_KEXINIT (20), instead received unknown message (1) #144

Closed
BjoernAkAManf opened this issue Jul 29, 2022 · 5 comments

Comments

@BjoernAkAManf
Copy link

BjoernAkAManf commented Jul 29, 2022

Hi!

I'm working on a product, that needs to implement ssh / scp themselves. I've read a dozens of rfc's myself already, but still would rather not implement everything myself. As such I've opted to use Apache Mina SSHD.

Trying to disable the ecdsa-sha2-nistp521 Signature however seems to be problematic. I can see, that ssh-audit tries connecting with only that signature algorithm and then see that the server implementation concludes, that a session cannot be negotiated properly. As such it sends the Message SSH_MSG_DISCONNECT (1), while logging the error message: "SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE - sendKexInit() no resolved signatures available".

However ssh-audit then fails to execute with the following message: [exception] did not receive MSG_KEXINIT (20), instead received unknown message (1). While reading the RFC 4253 i would say, that this is to be expected though, as on Page 18 it says:

  If no algorithm satisfying all these conditions can be found, the
  connection fails, and both sides MUST disconnect.

My Test Code utilizes Containers (testContainers-java) and JUnit. For reference:

import lombok.Cleanup;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.output.Slf4jLogConsumer;
import org.testcontainers.containers.startupcheck.IndefiniteWaitOneShotStartupCheckStrategy;
import org.testcontainers.junit.jupiter.Testcontainers;
import org.testcontainers.utility.MountableFile;

import java.io.IOException;

import static org.testcontainers.Testcontainers.exposeHostPorts;

@Slf4j
@Testcontainers
public final class SSHTest {
    private static final int SSH_PORT = 2222;


    @Test
    public void testAudit() throws Exception {
        @Cleanup final var launcher = createLauncher();
        launcher.start();

        exposeHostPorts(SSH_PORT);

        @Cleanup final var container = createContainerAudit();
        container.start();
    }

    private static GenericContainer<?> createContainerAudit() {
        return new SSHAudit(new SSHAudit.Config(SSH_URL, SSH_PORT))
            .withLogConsumer(new Slf4jLogConsumer(log))
            .withStartupCheckStrategy(new IndefiniteWaitOneShotStartupCheckStrategy());
    }
}

import org.testcontainers.containers.GenericContainer;
import org.testcontainers.utility.DockerImageName;

final class SSHAudit extends GenericContainer<SSHAudit> {
    public SSHAudit(final Config config) {
        super(DockerImageName.parse("positronsecurity/ssh-audit"));
        this.setCommand(
            "-b",
//            "-l", "warn",
            config.url()
        );
    }

    public record Config(
        String host,
        int port
    ) {
        String url() {
            return this.host + ":" + this.port;
        }
    }
}

The cause of the error is linked here

I'm unsure on how one would approach this though. As I have not yet understood the code base here. My suggestion would be to check if the server disconnected, but i can see. that the protocol definition currently has no such field.

EDIT:

Output of Help Menu running in Docker Container
[main] INFO 🐳 [positronsecurity/ssh-audit:latest] - Container positronsecurity/ssh-audit:latest started in PT1.5658137S

STDOUT # ssh-audit.py v2.5.0, https://github.com/jtesta/ssh-audit
STDOUT 
STDOUT usage: ssh-audit.py [options] <host>
STDOUT 
STDOUT    -h,  --help             print this help
STDOUT    -1,  --ssh1             force ssh version 1 only
STDOUT    -2,  --ssh2             force ssh version 2 only
STDOUT    -4,  --ipv4             enable IPv4 (order of precedence)
STDOUT    -6,  --ipv6             enable IPv6 (order of precedence)
STDOUT    -b,  --batch            batch output
STDOUT    -c,  --client-audit     starts a server on port 2222 to audit client
STDOUT                                software config (use -p to change port;
STDOUT                                use -t to change timeout)
STDOUT    -d,  --debug            debug output
STDOUT    -j,  --json             JSON output (use -jj to enable indents)
STDOUT    -l,  --level=<level>    minimum output level (info|warn|fail)
STDOUT    -L,  --list-policies    list all the official, built-in policies
STDOUT         --lookup=<alg1,alg2,...>    looks up an algorithm(s) without
STDOUT                                     connecting to a server
STDOUT    -M,  --make-policy=<policy.txt>  creates a policy based on the target server
STDOUT                                     (i.e.: the target server has the ideal
STDOUT                                     configuration that other servers should
STDOUT                                     adhere to)
STDOUT    -m,  --manual           print the man page (Windows only)
STDOUT    -n,  --no-colors        disable colors
STDOUT    -p,  --port=<port>      port to connect
STDOUT    -P,  --policy=<policy.txt>  run a policy test using the specified policy
STDOUT    -t,  --timeout=<secs>   timeout (in seconds) for connection and reading
STDOUT                                (default: 5)
STDOUT    -T,  --targets=<hosts.txt>  a file containing a list of target hosts (one
STDOUT                                    per line, format HOST[:PORT]).  Use --threads
STDOUT                                    to control concurrent scans.
STDOUT         --threads=<threads>    number of threads to use when scanning multiple
STDOUT                                    targets (-T/--targets) (default: 32)
STDOUT    -v,  --verbose          verbose output
STDOUT 
END 
Output of --debug running in Docker Container (Error).

Supported Signatures:
ssh-dss
ssh-dss-cert-v01@openssh.com
ssh-rsa
ssh-rsa-cert-v01@openssh.com
rsa-sha2-256
rsa-sha2-256-cert-v01@openssh.com
rsa-sha2-512
rsa-sha2-512-cert-v01@openssh.com
ecdsa-sha2-nistp256
ecdsa-sha2-nistp256-cert-v01@openssh.com
ecdsa-sha2-nistp384
ecdsa-sha2-nistp384-cert-v01@openssh.com
sk-ecdsa-sha2-nistp256@openssh.com
ssh-ed25519
ssh-ed25519-cert-v01@openssh.com
sk-ssh-ed25519@openssh.com

STDOUT Starting audit of host.testcontainers.internal:2222...
STDOUT Connecting to 172.17.0.3:2222...
STDOUT Getting banner...
STDOUT KEX initialisation...
STDOUT (gen) banner: SSH-2.0-APACHE-SSHD-2.8.0
STDOUT [exception] did not receive MSG_KEXINIT (20), instead received unknown message (1)
END 
...
Output of --debug running in Docker Container (Successful, but audit fails).

Supported Signatures:
ssh-dss
ssh-dss-cert-v01@openssh.com
ssh-rsa
ssh-rsa-cert-v01@openssh.com
rsa-sha2-256
rsa-sha2-256-cert-v01@openssh.com
rsa-sha2-512
rsa-sha2-512-cert-v01@openssh.com
ecdsa-sha2-nistp256
ecdsa-sha2-nistp256-cert-v01@openssh.com
ecdsa-sha2-nistp384
ecdsa-sha2-nistp384-cert-v01@openssh.com
ecdsa-sha2-nistp521
ecdsa-sha2-nistp521-cert-v01@openssh.com
sk-ecdsa-sha2-nistp256@openssh.com
ssh-ed25519
ssh-ed25519-cert-v01@openssh.com
sk-ssh-ed25519@openssh.com


STDOUT Starting audit of host.testcontainers.internal:2222...
STDOUT Connecting to 172.17.0.3:2222...
STDOUT Getting banner...
STDOUT KEX initialisation...
STDOUT Preparing to perform DH group exchange using diffie-hellman-group-exchange-sha256...
STDOUT Connecting to 172.17.0.3:2222...
STDOUT Getting banner...
STDOUT KEX initialisation...
STDOUT Preparing to perform DH group exchange using diffie-hellman-group-exchange-sha256 with modulus size 512...
STDOUT Connecting to 172.17.0.3:2222...
STDOUT Getting banner...
STDOUT KEX initialisation...
STDOUT Preparing to perform DH group exchange using diffie-hellman-group-exchange-sha256 with modulus size 768...
STDOUT Connecting to 172.17.0.3:2222...
STDOUT Getting banner...
STDOUT KEX initialisation...
STDOUT Preparing to perform DH group exchange using diffie-hellman-group-exchange-sha256 with modulus size 1024...
STDOUT Connecting to 172.17.0.3:2222...
STDOUT Getting banner...
STDOUT KEX initialisation...
STDOUT Preparing to perform DH group exchange using diffie-hellman-group-exchange-sha256 with modulus size 1536...
STDOUT Connecting to 172.17.0.3:2222...
STDOUT Getting banner...
STDOUT KEX initialisation...
STDOUT Preparing to perform DH group exchange using diffie-hellman-group-exchange-sha256 with modulus size 2048...
STDOUT Connecting to 172.17.0.3:2222...
STDOUT Getting banner...
STDOUT KEX initialisation...
STDOUT (gen) banner: SSH-2.0-APACHE-SSHD-2.8.0
STDOUT (gen) compatibility: OpenSSH 7.4+, Dropbear SSH 2018.76+
STDOUT (gen) compression: enabled (zlib, zlib@openssh.com)
STDOUT (kex) curve25519-sha256 -- [info] available since OpenSSH 7.4, Dropbear SSH 2018.76
STDOUT (kex) curve25519-sha256@libssh.org -- [info] available since OpenSSH 6.5, Dropbear SSH 2013.62
STDOUT (kex) curve448-sha512
STDOUT (kex) diffie-hellman-group-exchange-sha256 (2048-bit) -- [info] available since OpenSSH 4.4
STDOUT (kex) diffie-hellman-group18-sha512 -- [info] available since OpenSSH 7.3
STDOUT (kex) diffie-hellman-group17-sha512
STDOUT (kex) diffie-hellman-group16-sha512 -- [info] available since OpenSSH 7.3, Dropbear SSH 2016.73
STDOUT (kex) diffie-hellman-group15-sha512
STDOUT (kex) diffie-hellman-group14-sha256 -- [info] available since OpenSSH 7.3, Dropbear SSH 2016.73
STDOUT (kex) ext-info-s
STDOUT (key) ecdsa-sha2-nistp521 -- [fail] using weak elliptic curves
STDOUT (key) ecdsa-sha2-nistp521 -- [warn] using weak random number generator could reveal the key
STDOUT (key) ecdsa-sha2-nistp521 -- [info] available since OpenSSH 5.7, Dropbear SSH 2013.62
STDOUT (enc) chacha20-poly1305@openssh.com -- [info] available since OpenSSH 6.5
STDOUT (enc) chacha20-poly1305@openssh.com -- [info] default cipher since OpenSSH 6.9.
STDOUT (enc) aes128-ctr -- [info] available since OpenSSH 3.7, Dropbear SSH 0.52
STDOUT (enc) aes192-ctr -- [info] available since OpenSSH 3.7
STDOUT (enc) aes256-ctr -- [info] available since OpenSSH 3.7, Dropbear SSH 0.52
STDOUT (enc) aes128-gcm@openssh.com -- [info] available since OpenSSH 6.2
STDOUT (enc) aes256-gcm@openssh.com -- [info] available since OpenSSH 6.2
STDOUT (mac) hmac-sha2-256-etm@openssh.com -- [info] available since OpenSSH 6.2
STDOUT (mac) hmac-sha2-512-etm@openssh.com -- [info] available since OpenSSH 6.2
STDOUT (rec) -ecdsa-sha2-nistp521-- key algorithm to remove 
STDOUT (nfo) For hardening guides on common OSes, please see: <https://www.ssh-audit.com/hardening_guides.html>
END 

@thecliguy
Copy link
Contributor

Please can you:

  • Run ssh-audit --help and provide the first line of output.
  • Run your ssh-audit command but with the addition of the --debug parameter and paste the output returned. If there's anything in the output that you'd prefer to keep private then replace it with the word REDACTED.

@BjoernAkAManf
Copy link
Author

I've updated the initial post with the output.

After skimming the Git Commit Messages, i don't think there is a particular fix in dev either.
I also do not think any output needs to be redacted either. Hope this additional Information is helpful.

@thecliguy
Copy link
Contributor

Hi,

Thanks for providing the additional information requested.

When ssh-audit is used against a server it acts as a client. The majority of the information that ssh-audit obtains is gathered by issuing an KEXINIT to the server and then analysing the KEXINIT that it gets back from the server.

In my experience, when a client issues a KEXINIT to a server, the server should respond with a KEXINIT, even when there are no mutually supported algorithms.

To prove this point, I modified ssh-audit so that all calls to send_kexinit were performed using a value of 'foo' for each algorithm, EG:

  • key_exchanges: 'foo'
  • hostkeys: 'foo'
  • ciphers: 'foo'
  • macs: 'foo'
  • compressions: 'foo'

I then proceeded to audit two different SSH servers, one of which was my own private server running OpenSSH and the other is the publicly available test.rebex.net which runs Rebex Buru SFTP Server.

I was able to successfully audit both servers.

Here's an excerpt from my modified ssh-audit showing that it sent "foo" for all algorithms in the KEXINIT:

Getting banner...
KEX initialisation...
-----------------------------------------------------------
DIRECTION: CLIENT-TO-SERVER
host key algorithms:                     ['foo']
key exchange algorithms:                 ['foo']
encryption algorithms client to server:  ['foo']
encryption algorithms server to client:  ['foo']
mac algorithms client to server:         ['foo']
mac algorithms server to client:         ['foo']
compression algorithms client to server: ['foo']
compression algorithms server to client: ['foo']
languages client to server:              ['']
languages server to client:              ['']
-----------------------------------------------------------

Here's an excerpt from my private SSH server showing that it received the value of "foo":

thecliguy@SANDBOX:~$ sudo tail -f /var/log/auth.log | grep foo
Aug  3 22:11:43 SANDBOX sshd[251379]: debug2: KEX algorithms: foo [preauth]
Aug  3 22:11:43 SANDBOX sshd[251379]: debug2: host key algorithms: foo [preauth]
Aug  3 22:11:43 SANDBOX sshd[251379]: debug2: ciphers ctos: foo [preauth]
Aug  3 22:11:43 SANDBOX sshd[251379]: debug2: ciphers stoc: foo [preauth]
Aug  3 22:11:43 SANDBOX sshd[251379]: debug2: MACs ctos: foo [preauth]
Aug  3 22:11:43 SANDBOX sshd[251379]: debug2: MACs stoc: foo [preauth]
Aug  3 22:11:43 SANDBOX sshd[251379]: debug2: compression ctos: foo [preauth]
Aug  3 22:11:43 SANDBOX sshd[251379]: debug2: compression stoc: foo [preauth]
Aug  3 22:11:43 SANDBOX sshd[251379]: Unable to negotiate with REDACTED port 57526: no matching key exchange method found. Their offer: foo [preauth]

Here's an excerpt from my modified ssh-audit showing that it received a KEXINIT back from the server:

-----------------------------------------------------------
DIRECTION: SERVER-TO-CLIENT
host key algorithms:                     ['rsa-sha2-512', 'rsa-sha2-256', 'ssh-ed25519']
key exchange algorithms:                 ['curve25519-sha256', 'diffie-hellman-group16-sha512', 'diffie-hellman-group18-sha512', 'diffie-hellman-group14-sha256']
encryption algorithms client to server:  ['chacha20-poly1305@openssh.com', 'aes128-ctr', 'aes192-ctr', 'aes256-ctr', 'aes128-gcm@openssh.com', 'aes256-gcm@openssh.com']
encryption algorithms server to client:  ['chacha20-poly1305@openssh.com', 'aes128-ctr', 'aes192-ctr', 'aes256-ctr', 'aes128-gcm@openssh.com', 'aes256-gcm@openssh.com']
mac algorithms client to server:         ['umac-64-etm@openssh.com', 'umac-128-etm@openssh.com', 'hmac-sha2-256-etm@openssh.com', 'hmac-sha2-512-etm@openssh.com', 'hmac-sha1-etm@openssh.com', 'umac-64@openssh.com', 'umac-128@openssh.com', 'hmac-sha2-256', 'hmac-sha2-512', 'hmac-sha1']
mac algorithms server to client:         ['umac-64-etm@openssh.com', 'umac-128-etm@openssh.com', 'hmac-sha2-256-etm@openssh.com', 'hmac-sha2-512-etm@openssh.com', 'hmac-sha1-etm@openssh.com', 'umac-64@openssh.com', 'umac-128@openssh.com', 'hmac-sha2-256', 'hmac-sha2-512', 'hmac-sha1']
compression algorithms client to server: ['none', 'zlib@openssh.com']
compression algorithms server to client: ['none', 'zlib@openssh.com']
languages client to server:              ['']
languages server to client:              ['']
-----------------------------------------------------------

The only consequence of ssh-audit sending "foo" in the KEXINIT is that it if it needs to venture beyond the KEXINIT it can't do so. For example, if the target server supports Diffie-Hellman Group Exchange then ssh-audit will fail when attempting to perform a number of DH exchanges in order to determine if the modulus size is an acceptable value. Similarly, ssh-audit attempts and fails to perform multiple key exchanges where it iterates each host key type supported by the server in an effort to obtain the respective key size and fingerprint. Even under these conditions, an audit will still complete but minus a few values.

In summary, when ssh-audit acts as a client, I don't think it can be responsible for a server failing to respond to a KEXINIT with a KEXINIT.

I would suggest that you try using another client tool to send a KEXINIT to the server and see if you can get it to respond with a KEXINIT. If you can't, then it would seem fairly conclusive that the server is at fault.

@jtesta
Copy link
Owner

jtesta commented Mar 20, 2023

@BjoernAkAManf : can you reproduce this problem against a host available on the public Internet? If so, what is its hostname/IP? Otherwise, can you describe the server software & configuration that triggers it? This would help us debug the issue. Thanks!

@jtesta
Copy link
Owner

jtesta commented Aug 31, 2023

@BjoernAkAManf : I tested the master version of ssh-audit against the latest version of Apache MINA SSHD (v2.10.0 as of this writing), and it appears to work (see below). So I suppose I'll close this issue. If you observe any problems with the latest version of ssh-audit, though, please open another issue! Thanks!

$ ./ssh-audit.py 10.x.x.x:2222
# general
(gen) banner: SSH-2.0-APACHE-SSHD-2.10.0
(gen) compatibility: OpenSSH 7.4+ (some functionality from 6.6), Dropbear SSH 2018.76+
(gen) compression: enabled (zlib, zlib@openssh.com)

# key exchange algorithms
(kex) curve25519-sha256                     -- [info] available since OpenSSH 7.4, Dropbear SSH 2018.76
                                            `- [info] default key exchange since OpenSSH 6.4
(kex) curve25519-sha256@libssh.org          -- [info] available since OpenSSH 6.4, Dropbear SSH 2013.62
                                            `- [info] default key exchange since OpenSSH 6.4
(kex) curve448-sha512
(kex) ecdh-sha2-nistp521                    -- [fail] using elliptic curves that are suspected as being backdoored by the U.S. National Security Agency
                                            `- [info] available since OpenSSH 5.7, Dropbear SSH 2013.62
(kex) ecdh-sha2-nistp384                    -- [fail] using elliptic curves that are suspected as being backdoored by the U.S. National Security Agency
                                            `- [info] available since OpenSSH 5.7, Dropbear SSH 2013.62
(kex) ecdh-sha2-nistp256                    -- [fail] using elliptic curves that are suspected as being backdoored by the U.S. National Security Agency
                                            `- [info] available since OpenSSH 5.7, Dropbear SSH 2013.62
(kex) diffie-hellman-group-exchange-sha256 (2048-bit) -- [warn] 2048-bit modulus only provides 112-bits of symmetric strength
                                                      `- [info] available since OpenSSH 4.4
(kex) diffie-hellman-group18-sha512         -- [info] available since OpenSSH 7.3
(kex) diffie-hellman-group17-sha512
(kex) diffie-hellman-group16-sha512         -- [info] available since OpenSSH 7.3, Dropbear SSH 2016.73
(kex) diffie-hellman-group15-sha512
(kex) diffie-hellman-group14-sha256         -- [warn] 2048-bit modulus only provides 112-bits of symmetric strength
                                            `- [info] available since OpenSSH 7.3, Dropbear SSH 2016.73
(kex) ext-info-s

# host-key algorithms
(key) ecdsa-sha2-nistp521                   -- [fail] using elliptic curves that are suspected as being backdoored by the U.S. National Security Agency
                                            `- [warn] using weak random number generator could reveal the key
                                            `- [info] available since OpenSSH 5.7, Dropbear SSH 2013.62

# encryption algorithms (ciphers)
(enc) chacha20-poly1305@openssh.com         -- [info] available since OpenSSH 6.5
                                            `- [info] default cipher since OpenSSH 6.9
(enc) aes128-ctr                            -- [info] available since OpenSSH 3.7, Dropbear SSH 0.52
(enc) aes192-ctr                            -- [info] available since OpenSSH 3.7
(enc) aes256-ctr                            -- [info] available since OpenSSH 3.7, Dropbear SSH 0.52
(enc) aes128-gcm@openssh.com                -- [info] available since OpenSSH 6.2
(enc) aes256-gcm@openssh.com                -- [info] available since OpenSSH 6.2
(enc) aes128-cbc                            -- [warn] using weak cipher mode
                                            `- [info] available since OpenSSH 2.3.0, Dropbear SSH 0.28
(enc) aes192-cbc                            -- [warn] using weak cipher mode
                                            `- [info] available since OpenSSH 2.3.0
(enc) aes256-cbc                            -- [warn] using weak cipher mode
                                            `- [info] available since OpenSSH 2.3.0, Dropbear SSH 0.47

# message authentication code algorithms
(mac) hmac-sha2-256-etm@openssh.com         -- [info] available since OpenSSH 6.2
(mac) hmac-sha2-512-etm@openssh.com         -- [info] available since OpenSSH 6.2
(mac) hmac-sha1-etm@openssh.com             -- [fail] using broken SHA-1 hash algorithm
                                            `- [info] available since OpenSSH 6.2
(mac) hmac-sha2-256                         -- [warn] using encrypt-and-MAC mode
                                            `- [info] available since OpenSSH 5.9, Dropbear SSH 2013.56
(mac) hmac-sha2-512                         -- [warn] using encrypt-and-MAC mode
                                            `- [info] available since OpenSSH 5.9, Dropbear SSH 2013.56
(mac) hmac-sha1                             -- [fail] using broken SHA-1 hash algorithm
                                            `- [warn] using encrypt-and-MAC mode
                                            `- [info] available since OpenSSH 2.1.0, Dropbear SSH 0.28

@jtesta jtesta closed this as completed Aug 31, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants