ssh-audit
ssh-audit copied to clipboard
[exception] did not receive MSG_KEXINIT (20), instead received unknown message (1)
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 [email protected] ssh-rsa [email protected] rsa-sha2-256 [email protected] rsa-sha2-512 [email protected] ecdsa-sha2-nistp256 [email protected] ecdsa-sha2-nistp384 [email protected] [email protected] ssh-ed25519 [email protected] [email protected]
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 [email protected] ssh-rsa [email protected] rsa-sha2-256 [email protected] rsa-sha2-512 [email protected] ecdsa-sha2-nistp256 [email protected] ecdsa-sha2-nistp384 [email protected] ecdsa-sha2-nistp521 [email protected] [email protected] ssh-ed25519 [email protected] [email protected]
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, [email protected])
STDOUT (kex) curve25519-sha256 -- [info] available since OpenSSH 7.4, Dropbear SSH 2018.76
STDOUT (kex) [email protected] -- [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) [email protected] -- [info] available since OpenSSH 6.5
STDOUT (enc) [email protected] -- [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) [email protected] -- [info] available since OpenSSH 6.2
STDOUT (enc) [email protected] -- [info] available since OpenSSH 6.2
STDOUT (mac) [email protected] -- [info] available since OpenSSH 6.2
STDOUT (mac) [email protected] -- [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
Please can you:
- Run
ssh-audit --helpand provide the first line of output. - Run your ssh-audit command but with the addition of the
--debugparameter and paste the output returned. If there's anything in the output that you'd prefer to keep private then replace it with the wordREDACTED.
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.
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: ['[email protected]', 'aes128-ctr', 'aes192-ctr', 'aes256-ctr', '[email protected]', '[email protected]']
encryption algorithms server to client: ['[email protected]', 'aes128-ctr', 'aes192-ctr', 'aes256-ctr', '[email protected]', '[email protected]']
mac algorithms client to server: ['[email protected]', '[email protected]', '[email protected]', '[email protected]', '[email protected]', '[email protected]', '[email protected]', 'hmac-sha2-256', 'hmac-sha2-512', 'hmac-sha1']
mac algorithms server to client: ['[email protected]', '[email protected]', '[email protected]', '[email protected]', '[email protected]', '[email protected]', '[email protected]', 'hmac-sha2-256', 'hmac-sha2-512', 'hmac-sha1']
compression algorithms client to server: ['none', '[email protected]']
compression algorithms server to client: ['none', '[email protected]']
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.
@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!
@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, [email protected])
# 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) [email protected] -- [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) [email protected] -- [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) [email protected] -- [info] available since OpenSSH 6.2
(enc) [email protected] -- [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) [email protected] -- [info] available since OpenSSH 6.2
(mac) [email protected] -- [info] available since OpenSSH 6.2
(mac) [email protected] -- [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