diff options
Diffstat (limited to 'test')
118 files changed, 4610 insertions, 0 deletions
diff --git a/test/conftest.py b/test/conftest.py new file mode 100644 index 0000000..e3878b1 --- /dev/null +++ b/test/conftest.py @@ -0,0 +1,145 @@ +import io +import sys +import socket +import pytest + + +@pytest.fixture(scope='module') +def ssh_audit(): + import ssh_audit.ssh_audit + return ssh_audit.ssh_audit + + +# pylint: disable=attribute-defined-outside-init +class _OutputSpy(list): + def begin(self): + self.__out = io.StringIO() + self.__old_stdout = sys.stdout + sys.stdout = self.__out + + def flush(self): + lines = self.__out.getvalue().splitlines() + sys.stdout = self.__old_stdout + self.__out = None + return lines + + +@pytest.fixture(scope='module') +def output_spy(): + return _OutputSpy() + + +class _VirtualGlobalSocket: + def __init__(self, vsocket): + self.vsocket = vsocket + self.addrinfodata = {} + + # pylint: disable=unused-argument + def create_connection(self, address, timeout=0, source_address=None): + # pylint: disable=protected-access + return self.vsocket._connect(address, True) + + # pylint: disable=unused-argument + def socket(self, + family=socket.AF_INET, + socktype=socket.SOCK_STREAM, + proto=0, + fileno=None): + return self.vsocket + + def getaddrinfo(self, host, port, family=0, socktype=0, proto=0, flags=0): + key = '{}#{}'.format(host, port) + if key in self.addrinfodata: + data = self.addrinfodata[key] + if isinstance(data, Exception): + raise data + return data + if host == 'localhost': + r = [] + if family in (0, socket.AF_INET): + r.append((socket.AF_INET, 1, 6, '', ('127.0.0.1', port))) + if family in (0, socket.AF_INET6): + r.append((socket.AF_INET6, 1, 6, '', ('::1', port))) + return r + return [] + + +class _VirtualSocket: + def __init__(self): + self.sock_address = ('127.0.0.1', 0) + self.peer_address = None + self._connected = False + self.timeout = -1.0 + self.rdata = [] + self.sdata = [] + self.errors = {} + self.gsock = _VirtualGlobalSocket(self) + + def _check_err(self, method): + method_error = self.errors.get(method) + if method_error: + raise method_error + + def connect(self, address): + return self._connect(address, False) + + def _connect(self, address, ret=True): + self.peer_address = address + self._connected = True + self._check_err('connect') + return self if ret else None + + def settimeout(self, timeout): + self.timeout = timeout + + def gettimeout(self): + return self.timeout + + def getpeername(self): + if self.peer_address is None or not self._connected: + raise OSError(57, 'Socket is not connected') + return self.peer_address + + def getsockname(self): + return self.sock_address + + def bind(self, address): + self.sock_address = address + + def listen(self, backlog): + pass + + def accept(self): + # pylint: disable=protected-access + conn = _VirtualSocket() + conn.sock_address = self.sock_address + conn.peer_address = ('127.0.0.1', 0) + conn._connected = True + return conn, conn.peer_address + + def recv(self, bufsize, flags=0): + # pylint: disable=unused-argument + if not self._connected: + raise OSError(54, 'Connection reset by peer') + if not len(self.rdata) > 0: + return b'' + data = self.rdata.pop(0) + if isinstance(data, Exception): + raise data + return data + + def send(self, data): + if self.peer_address is None or not self._connected: + raise OSError(32, 'Broken pipe') + self._check_err('send') + self.sdata.append(data) + + +@pytest.fixture() +def virtual_socket(monkeypatch): + vsocket = _VirtualSocket() + gsock = vsocket.gsock + monkeypatch.setattr(socket, 'create_connection', gsock.create_connection) + monkeypatch.setattr(socket, 'socket', gsock.socket) + monkeypatch.setattr(socket, 'getaddrinfo', gsock.getaddrinfo) + return vsocket diff --git a/test/docker/.ed25519.sk b/test/docker/.ed25519.sk new file mode 100644 index 0000000..58b097b --- /dev/null +++ b/test/docker/.ed25519.sk @@ -0,0 +1 @@ +iÜ›ãÈÍíVÌè¿ÓZ/Dì<†î|S“zË=°:×1vu}¢ï„JòÝ·ŸŠ"à^Bb&U‰ìP«
’CJ?
\ No newline at end of file diff --git a/test/docker/Dockerfile b/test/docker/Dockerfile new file mode 100644 index 0000000..eef0139 --- /dev/null +++ b/test/docker/Dockerfile @@ -0,0 +1,32 @@ +FROM ubuntu:16.04 + +COPY openssh-4.0p1/sshd /openssh/sshd-4.0p1 +COPY openssh-5.6p1/sshd /openssh/sshd-5.6p1 +COPY openssh-8.0p1/sshd /openssh/sshd-8.0p1 +COPY dropbear-2019.78/dropbear /dropbear/dropbear-2019.78 +COPY tinyssh-20190101/build/bin/tinysshd /tinysshd/tinyssh-20190101 + +# Dropbear host keys. +COPY dropbear_*_host_key* /etc/dropbear/ + +# OpenSSH configs. +COPY sshd_config* /etc/ssh/ + +# OpenSSH host keys & moduli file. +COPY ssh_host_* /etc/ssh/ +COPY ssh1_host_* /etc/ssh/ +COPY moduli_1024 /usr/local/etc/moduli + +# TinySSH host keys. +COPY ed25519.pk /etc/tinyssh/ +COPY .ed25519.sk /etc/tinyssh/ + +COPY debug.sh /debug.sh + +RUN apt update 2> /dev/null +RUN apt install -y libssl-dev strace rsyslog ucspi-tcp 2> /dev/null +RUN apt clean 2> /dev/null +RUN useradd -s /bin/false sshd +RUN mkdir /var/empty + +EXPOSE 22 diff --git a/test/docker/debug.sh b/test/docker/debug.sh new file mode 100755 index 0000000..c4be343 --- /dev/null +++ b/test/docker/debug.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +# This script is run on in docker container. It will enable logging for sshd in +# /var/log/auth.log. + +/etc/init.d/rsyslog start +sleep 1 +/openssh/sshd-5.6p1 -o LogLevel=DEBUG3 -f /etc/ssh/sshd_config-5.6p1_test1 +/bin/bash diff --git a/test/docker/dropbear_dss_host_key b/test/docker/dropbear_dss_host_key Binary files differnew file mode 100644 index 0000000..3388632 --- /dev/null +++ b/test/docker/dropbear_dss_host_key diff --git a/test/docker/dropbear_ecdsa_host_key b/test/docker/dropbear_ecdsa_host_key Binary files differnew file mode 100644 index 0000000..318ebb0 --- /dev/null +++ b/test/docker/dropbear_ecdsa_host_key diff --git a/test/docker/dropbear_rsa_host_key_1024 b/test/docker/dropbear_rsa_host_key_1024 Binary files differnew file mode 100644 index 0000000..d9ce331 --- /dev/null +++ b/test/docker/dropbear_rsa_host_key_1024 diff --git a/test/docker/dropbear_rsa_host_key_3072 b/test/docker/dropbear_rsa_host_key_3072 Binary files differnew file mode 100644 index 0000000..006249a --- /dev/null +++ b/test/docker/dropbear_rsa_host_key_3072 diff --git a/test/docker/ed25519.pk b/test/docker/ed25519.pk new file mode 100644 index 0000000..82cfb47 --- /dev/null +++ b/test/docker/ed25519.pk @@ -0,0 +1 @@ +1vu}¢ï„JòÝ·ŸŠ"à^Bb&U‰ìP«
’CJ?
\ No newline at end of file diff --git a/test/docker/expected_results/dropbear_2019.78_test1.json b/test/docker/expected_results/dropbear_2019.78_test1.json new file mode 100644 index 0000000..186cb06 --- /dev/null +++ b/test/docker/expected_results/dropbear_2019.78_test1.json @@ -0,0 +1 @@ +{"banner": {"comments": null, "protocol": [2, 0], "raw": "SSH-2.0-dropbear_2019.78", "software": "dropbear_2019.78"}, "compression": ["zlib@openssh.com", "none"], "enc": ["aes128-ctr", "aes256-ctr", "aes128-cbc", "aes256-cbc", "3des-ctr", "3des-cbc"], "fingerprints": [{"hash": "CDfAU12pjQS7/91kg7gYacza0U/6PDbE04Ic3IpYxkM", "hash_alg": "SHA256", "hostkey": "ssh-rsa"}, {"hash": "63:7f:54:f7:0a:28:7f:75:0b:f4:07:0b:fc:66:51:a2", "hash_alg": "MD5", "hostkey": "ssh-rsa"}], "kex": [{"algorithm": "curve25519-sha256"}, {"algorithm": "curve25519-sha256@libssh.org"}, {"algorithm": "ecdh-sha2-nistp521"}, {"algorithm": "ecdh-sha2-nistp384"}, {"algorithm": "ecdh-sha2-nistp256"}, {"algorithm": "diffie-hellman-group14-sha256"}, {"algorithm": "diffie-hellman-group14-sha1"}, {"algorithm": "kexguess2@matt.ucc.asn.au"}], "key": [{"algorithm": "ecdsa-sha2-nistp256"}, {"algorithm": "ssh-rsa", "keysize": 1024}, {"algorithm": "ssh-dss"}], "mac": ["hmac-sha1-96", "hmac-sha1", "hmac-sha2-256"], "target": "localhost"} diff --git a/test/docker/expected_results/dropbear_2019.78_test1.txt b/test/docker/expected_results/dropbear_2019.78_test1.txt new file mode 100644 index 0000000..93205f4 --- /dev/null +++ b/test/docker/expected_results/dropbear_2019.78_test1.txt @@ -0,0 +1,88 @@ +[0;36m# general[0m +[0;32m(gen) banner: SSH-2.0-dropbear_2019.78[0m +[0;32m(gen) software: Dropbear SSH 2019.78[0m +[0;32m(gen) compatibility: OpenSSH 7.4+ (some functionality from 6.6), Dropbear SSH 2018.76+[0m +[0;32m(gen) compression: enabled (zlib@openssh.com)[0m + +[0;36m# key exchange algorithms[0m +[0;32m(kex) curve25519-sha256 -- [info] available since OpenSSH 7.4, Dropbear SSH 2018.76[0m +[0;32m(kex) curve25519-sha256@libssh.org -- [info] available since OpenSSH 6.5, Dropbear SSH 2013.62[0m +[0;31m(kex) ecdh-sha2-nistp521 -- [fail] using weak elliptic curves[0m + `- [info] available since OpenSSH 5.7, Dropbear SSH 2013.62 +[0;31m(kex) ecdh-sha2-nistp384 -- [fail] using weak elliptic curves[0m + `- [info] available since OpenSSH 5.7, Dropbear SSH 2013.62 +[0;31m(kex) ecdh-sha2-nistp256 -- [fail] using weak elliptic curves[0m + `- [info] available since OpenSSH 5.7, Dropbear SSH 2013.62 +[0;32m(kex) diffie-hellman-group14-sha256 -- [info] available since OpenSSH 7.3, Dropbear SSH 2016.73[0m +[0;33m(kex) diffie-hellman-group14-sha1 -- [warn] using weak hashing algorithm[0m + `- [info] available since OpenSSH 3.9, Dropbear SSH 0.53 +[0;32m(kex) kexguess2@matt.ucc.asn.au -- [info] available since Dropbear SSH 2013.57[0m + +[0;36m# host-key algorithms[0m +[0;31m(key) ecdsa-sha2-nistp256 -- [fail] using weak elliptic curves[0m +[0;33m `- [warn] using weak random number generator could reveal the key[0m + `- [info] available since OpenSSH 5.7, Dropbear SSH 2013.62 +[0;31m(key) ssh-rsa (1024-bit) -- [fail] using weak hashing algorithm[0m +[0;31m `- [fail] using small 1024-bit modulus[0m + `- [info] available since OpenSSH 2.5.0, Dropbear SSH 0.28 + `- [info] a future deprecation notice has been issued in OpenSSH 8.2: https://www.openssh.com/txt/release-8.2 +[0;31m(key) ssh-dss -- [fail] using small 1024-bit modulus[0m +[0;31m `- [fail] removed (in server) and disabled (in client) since OpenSSH 7.0, weak algorithm[0m +[0;33m `- [warn] using weak random number generator could reveal the key[0m + `- [info] available since OpenSSH 2.1.0, Dropbear SSH 0.28 + +[0;36m# encryption algorithms (ciphers)[0m +[0;32m(enc) aes128-ctr -- [info] available since OpenSSH 3.7, Dropbear SSH 0.52[0m +[0;32m(enc) aes256-ctr -- [info] available since OpenSSH 3.7, Dropbear SSH 0.52[0m +[0;31m(enc) aes128-cbc -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] using weak cipher mode[0m + `- [info] available since OpenSSH 2.3.0, Dropbear SSH 0.28 +[0;31m(enc) aes256-cbc -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] using weak cipher mode[0m + `- [info] available since OpenSSH 2.3.0, Dropbear SSH 0.47 +[0;31m(enc) 3des-ctr -- [fail] using weak cipher[0m + `- [info] available since Dropbear SSH 0.52 +[0;31m(enc) 3des-cbc -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] disabled (in client) since OpenSSH 7.4, unsafe algorithm[0m +[0;33m `- [warn] using weak cipher[0m +[0;33m `- [warn] using weak cipher mode[0m +[0;33m `- [warn] using small 64-bit block size[0m + `- [info] available since OpenSSH 1.2.2, Dropbear SSH 0.28 + +[0;36m# message authentication code algorithms[0m +[0;31m(mac) hmac-sha1-96 -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m +[0;33m `- [warn] using encrypt-and-MAC mode[0m +[0;33m `- [warn] using weak hashing algorithm[0m + `- [info] available since OpenSSH 2.5.0, Dropbear SSH 0.47 +[0;33m(mac) hmac-sha1 -- [warn] using encrypt-and-MAC mode[0m +[0;33m `- [warn] using weak hashing algorithm[0m + `- [info] available since OpenSSH 2.1.0, Dropbear SSH 0.28 +[0;33m(mac) hmac-sha2-256 -- [warn] using encrypt-and-MAC mode[0m + `- [info] available since OpenSSH 5.9, Dropbear SSH 2013.56 + +[0;36m# fingerprints[0m +[0;32m(fin) ssh-rsa: SHA256:CDfAU12pjQS7/91kg7gYacza0U/6PDbE04Ic3IpYxkM[0m + +[0;36m# algorithm recommendations (for Dropbear SSH 2019.78)[0m +[0;31m(rec) -3des-cbc -- enc algorithm to remove [0m +[0;31m(rec) -3des-ctr -- enc algorithm to remove [0m +[0;31m(rec) -aes128-cbc -- enc algorithm to remove [0m +[0;31m(rec) -aes256-cbc -- enc algorithm to remove [0m +[0;31m(rec) -ecdh-sha2-nistp256 -- kex algorithm to remove [0m +[0;31m(rec) -ecdh-sha2-nistp384 -- kex algorithm to remove [0m +[0;31m(rec) -ecdh-sha2-nistp521 -- kex algorithm to remove [0m +[0;31m(rec) -ecdsa-sha2-nistp256 -- key algorithm to remove [0m +[0;31m(rec) -hmac-sha1-96 -- mac algorithm to remove [0m +[0;31m(rec) -ssh-dss -- key algorithm to remove [0m +[0;31m(rec) -ssh-rsa -- key algorithm to remove [0m +[0;32m(rec) +diffie-hellman-group16-sha512 -- kex algorithm to append [0m +[0;32m(rec) +twofish128-ctr -- enc algorithm to append [0m +[0;32m(rec) +twofish256-ctr -- enc algorithm to append [0m +[0;33m(rec) -diffie-hellman-group14-sha1 -- kex algorithm to remove [0m +[0;33m(rec) -hmac-sha1 -- mac algorithm to remove [0m +[0;33m(rec) -hmac-sha2-256 -- mac algorithm to remove [0m + +[0;36m# additional info[0m +[0;33m(nfo) For hardening guides on common OSes, please see: <https://www.ssh-audit.com/hardening_guides.html>[0m + diff --git a/test/docker/expected_results/openssh_4.0p1_test1.json b/test/docker/expected_results/openssh_4.0p1_test1.json new file mode 100644 index 0000000..33e63cf --- /dev/null +++ b/test/docker/expected_results/openssh_4.0p1_test1.json @@ -0,0 +1 @@ +{"banner": {"comments": null, "protocol": [1, 99], "raw": "SSH-1.99-OpenSSH_4.0", "software": "OpenSSH_4.0"}, "compression": ["none", "zlib"], "enc": ["aes128-cbc", "3des-cbc", "blowfish-cbc", "cast128-cbc", "arcfour", "aes192-cbc", "aes256-cbc", "rijndael-cbc@lysator.liu.se", "aes128-ctr", "aes192-ctr", "aes256-ctr"], "fingerprints": [{"hash": "YZ457EBcJTSxRKI3yXRgtAj3PBf5B9/F36b1SVooml4", "hash_alg": "SHA256", "hostkey": "ssh-rsa"}, {"hash": "3c:c3:38:f8:55:39:c0:4a:5a:17:89:60:2c:a1:fc:6a", "hash_alg": "MD5", "hostkey": "ssh-rsa"}], "kex": [{"algorithm": "diffie-hellman-group-exchange-sha1", "keysize": 1024}, {"algorithm": "diffie-hellman-group14-sha1"}, {"algorithm": "diffie-hellman-group1-sha1"}], "key": [{"algorithm": "ssh-rsa", "keysize": 1024}, {"algorithm": "ssh-dss"}], "mac": ["hmac-md5", "hmac-sha1", "hmac-ripemd160", "hmac-ripemd160@openssh.com", "hmac-sha1-96", "hmac-md5-96"], "target": "localhost"} diff --git a/test/docker/expected_results/openssh_4.0p1_test1.txt b/test/docker/expected_results/openssh_4.0p1_test1.txt new file mode 100644 index 0000000..419105a --- /dev/null +++ b/test/docker/expected_results/openssh_4.0p1_test1.txt @@ -0,0 +1,145 @@ +[0;36m# general[0m +[0;31m(gen) banner: SSH-1.99-OpenSSH_4.0[0m +[0;31m(gen) protocol SSH1 enabled[0m +[0;32m(gen) software: OpenSSH 4.0[0m +[0;32m(gen) compatibility: OpenSSH 3.9-6.6, Dropbear SSH 0.53+ (some functionality from 0.52)[0m +[0;32m(gen) compression: enabled (zlib)[0m + +[0;36m# security[0m +[0;33m(cve) CVE-2018-15473 -- (CVSSv2: 5.3) enumerate usernames due to timing discrepencies[0m +[0;33m(cve) CVE-2016-3115 -- (CVSSv2: 5.5) bypass command restrictions via crafted X11 forwarding data[0m +[0;33m(cve) CVE-2014-1692 -- (CVSSv2: 7.5) cause DoS via triggering error condition (memory corruption)[0m +[0;33m(cve) CVE-2012-0814 -- (CVSSv2: 3.5) leak data via debug messages[0m +[0;33m(cve) CVE-2011-5000 -- (CVSSv2: 3.5) cause DoS via large value in certain length field (memory consumption)[0m +[0;33m(cve) CVE-2010-5107 -- (CVSSv2: 5.0) cause DoS via large number of connections (slot exhaustion)[0m +[0;33m(cve) CVE-2010-4755 -- (CVSSv2: 4.0) cause DoS via crafted glob expression (CPU and memory consumption)[0m +[0;33m(cve) CVE-2010-4478 -- (CVSSv2: 7.5) bypass authentication check via crafted values[0m +[0;33m(cve) CVE-2008-5161 -- (CVSSv2: 2.6) recover plaintext data from ciphertext[0m +[0;33m(cve) CVE-2008-4109 -- (CVSSv2: 5.0) cause DoS via multiple login attempts (slot exhaustion)[0m +[0;33m(cve) CVE-2008-1657 -- (CVSSv2: 6.5) bypass command restrictions via modifying session file[0m +[0;33m(cve) CVE-2008-1483 -- (CVSSv2: 6.9) hijack forwarded X11 connections[0m +[0;33m(cve) CVE-2007-4752 -- (CVSSv2: 7.5) privilege escalation via causing an X client to be trusted[0m +[0;33m(cve) CVE-2007-2243 -- (CVSSv2: 5.0) discover valid usernames through different responses[0m +[0;33m(cve) CVE-2006-5052 -- (CVSSv2: 5.0) discover valid usernames through different responses[0m +[0;31m(cve) CVE-2006-5051 -- (CVSSv2: 9.3) cause DoS or execute arbitrary code (double free)[0m +[0;33m(cve) CVE-2006-4924 -- (CVSSv2: 7.8) cause DoS via crafted packet (CPU consumption)[0m +[0;33m(cve) CVE-2006-0225 -- (CVSSv2: 4.6) execute arbitrary code[0m +[0;33m(cve) CVE-2005-2798 -- (CVSSv2: 5.0) leak data about authentication credentials[0m +[0;31m(sec) SSH v1 enabled -- SSH v1 can be exploited to recover plaintext passwords[0m + +[0;36m# key exchange algorithms[0m +[0;31m(kex) diffie-hellman-group-exchange-sha1 (1024-bit) -- [fail] using small 1024-bit modulus[0m +[0;33m `- [warn] using weak hashing algorithm[0m + `- [info] available since OpenSSH 2.3.0 +[0;33m(kex) diffie-hellman-group14-sha1 -- [warn] using weak hashing algorithm[0m + `- [info] available since OpenSSH 3.9, Dropbear SSH 0.53 +[0;31m(kex) diffie-hellman-group1-sha1 -- [fail] using small 1024-bit modulus[0m +[0;31m `- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;31m `- [fail] disabled (in client) since OpenSSH 7.0, logjam attack[0m +[0;33m `- [warn] using weak hashing algorithm[0m + `- [info] available since OpenSSH 2.3.0, Dropbear SSH 0.28 + +[0;36m# host-key algorithms[0m +[0;31m(key) ssh-rsa (1024-bit) -- [fail] using weak hashing algorithm[0m +[0;31m `- [fail] using small 1024-bit modulus[0m + `- [info] available since OpenSSH 2.5.0, Dropbear SSH 0.28 + `- [info] a future deprecation notice has been issued in OpenSSH 8.2: https://www.openssh.com/txt/release-8.2 +[0;31m(key) ssh-dss -- [fail] using small 1024-bit modulus[0m +[0;31m `- [fail] removed (in server) and disabled (in client) since OpenSSH 7.0, weak algorithm[0m +[0;33m `- [warn] using weak random number generator could reveal the key[0m + `- [info] available since OpenSSH 2.1.0, Dropbear SSH 0.28 + +[0;36m# encryption algorithms (ciphers)[0m +[0;31m(enc) aes128-cbc -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] using weak cipher mode[0m + `- [info] available since OpenSSH 2.3.0, Dropbear SSH 0.28 +[0;31m(enc) 3des-cbc -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] disabled (in client) since OpenSSH 7.4, unsafe algorithm[0m +[0;33m `- [warn] using weak cipher[0m +[0;33m `- [warn] using weak cipher mode[0m +[0;33m `- [warn] using small 64-bit block size[0m + `- [info] available since OpenSSH 1.2.2, Dropbear SSH 0.28 +[0;31m(enc) blowfish-cbc -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;31m `- [fail] disabled since Dropbear SSH 0.53[0m +[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m +[0;33m `- [warn] using weak cipher mode[0m +[0;33m `- [warn] using small 64-bit block size[0m + `- [info] available since OpenSSH 1.2.2, Dropbear SSH 0.28 +[0;31m(enc) cast128-cbc -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m +[0;33m `- [warn] using weak cipher mode[0m +[0;33m `- [warn] using small 64-bit block size[0m + `- [info] available since OpenSSH 2.1.0 +[0;31m(enc) arcfour -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m +[0;33m `- [warn] using weak cipher[0m + `- [info] available since OpenSSH 2.1.0 +[0;31m(enc) aes192-cbc -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] using weak cipher mode[0m + `- [info] available since OpenSSH 2.3.0 +[0;31m(enc) aes256-cbc -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] using weak cipher mode[0m + `- [info] available since OpenSSH 2.3.0, Dropbear SSH 0.47 +[0;31m(enc) rijndael-cbc@lysator.liu.se -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m +[0;33m `- [warn] using weak cipher mode[0m + `- [info] available since OpenSSH 2.3.0 +[0;32m(enc) aes128-ctr -- [info] available since OpenSSH 3.7, Dropbear SSH 0.52[0m +[0;32m(enc) aes192-ctr -- [info] available since OpenSSH 3.7[0m +[0;32m(enc) aes256-ctr -- [info] available since OpenSSH 3.7, Dropbear SSH 0.52[0m + +[0;36m# message authentication code algorithms[0m +[0;31m(mac) hmac-md5 -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m +[0;33m `- [warn] using encrypt-and-MAC mode[0m +[0;33m `- [warn] using weak hashing algorithm[0m + `- [info] available since OpenSSH 2.1.0, Dropbear SSH 0.28 +[0;33m(mac) hmac-sha1 -- [warn] using encrypt-and-MAC mode[0m +[0;33m `- [warn] using weak hashing algorithm[0m + `- [info] available since OpenSSH 2.1.0, Dropbear SSH 0.28 +[0;31m(mac) hmac-ripemd160 -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m +[0;33m `- [warn] using encrypt-and-MAC mode[0m + `- [info] available since OpenSSH 2.5.0 +[0;31m(mac) hmac-ripemd160@openssh.com -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m +[0;33m `- [warn] using encrypt-and-MAC mode[0m + `- [info] available since OpenSSH 2.1.0 +[0;31m(mac) hmac-sha1-96 -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m +[0;33m `- [warn] using encrypt-and-MAC mode[0m +[0;33m `- [warn] using weak hashing algorithm[0m + `- [info] available since OpenSSH 2.5.0, Dropbear SSH 0.47 +[0;31m(mac) hmac-md5-96 -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m +[0;33m `- [warn] using encrypt-and-MAC mode[0m +[0;33m `- [warn] using weak hashing algorithm[0m + `- [info] available since OpenSSH 2.5.0 + +[0;36m# fingerprints[0m +[0;32m(fin) ssh-rsa: SHA256:YZ457EBcJTSxRKI3yXRgtAj3PBf5B9/F36b1SVooml4[0m + +[0;36m# algorithm recommendations (for OpenSSH 4.0)[0m +[0;31m(rec) -3des-cbc -- enc algorithm to remove [0m +[0;31m(rec) -aes128-cbc -- enc algorithm to remove [0m +[0;31m(rec) -aes192-cbc -- enc algorithm to remove [0m +[0;31m(rec) -aes256-cbc -- enc algorithm to remove [0m +[0;31m(rec) -arcfour -- enc algorithm to remove [0m +[0;31m(rec) -blowfish-cbc -- enc algorithm to remove [0m +[0;31m(rec) -cast128-cbc -- enc algorithm to remove [0m +[0;31m(rec) -diffie-hellman-group-exchange-sha1 -- kex algorithm to remove [0m +[0;31m(rec) -diffie-hellman-group1-sha1 -- kex algorithm to remove [0m +[0;31m(rec) -hmac-md5 -- mac algorithm to remove [0m +[0;31m(rec) -hmac-md5-96 -- mac algorithm to remove [0m +[0;31m(rec) -hmac-ripemd160 -- mac algorithm to remove [0m +[0;31m(rec) -hmac-ripemd160@openssh.com -- mac algorithm to remove [0m +[0;31m(rec) -hmac-sha1-96 -- mac algorithm to remove [0m +[0;31m(rec) -rijndael-cbc@lysator.liu.se -- enc algorithm to remove [0m +[0;31m(rec) -ssh-dss -- key algorithm to remove [0m +[0;31m(rec) -ssh-rsa -- key algorithm to remove [0m +[0;33m(rec) -diffie-hellman-group14-sha1 -- kex algorithm to remove [0m +[0;33m(rec) -hmac-sha1 -- mac algorithm to remove [0m + +[0;36m# additional info[0m +[0;33m(nfo) For hardening guides on common OSes, please see: <https://www.ssh-audit.com/hardening_guides.html>[0m + diff --git a/test/docker/expected_results/openssh_5.6p1_custom_policy_test1.json b/test/docker/expected_results/openssh_5.6p1_custom_policy_test1.json new file mode 100644 index 0000000..52d9e38 --- /dev/null +++ b/test/docker/expected_results/openssh_5.6p1_custom_policy_test1.json @@ -0,0 +1 @@ +{"errors": [], "host": "localhost", "passed": true, "policy": "Docker policy: test1 (version 1)"} diff --git a/test/docker/expected_results/openssh_5.6p1_custom_policy_test1.txt b/test/docker/expected_results/openssh_5.6p1_custom_policy_test1.txt new file mode 100644 index 0000000..01146f8 --- /dev/null +++ b/test/docker/expected_results/openssh_5.6p1_custom_policy_test1.txt @@ -0,0 +1,3 @@ +Host: localhost:2222 +Policy: Docker policy: test1 (version 1) +Result: [0;32m✔ Passed[0m diff --git a/test/docker/expected_results/openssh_5.6p1_custom_policy_test10.json b/test/docker/expected_results/openssh_5.6p1_custom_policy_test10.json new file mode 100644 index 0000000..7bf35ae --- /dev/null +++ b/test/docker/expected_results/openssh_5.6p1_custom_policy_test10.json @@ -0,0 +1 @@ +{"errors": [{"actual": ["3072"], "expected_optional": [""], "expected_required": ["4096"], "mismatched_field": "RSA host key (ssh-rsa-cert-v01@openssh.com) sizes"}, {"actual": ["1024"], "expected_optional": [""], "expected_required": ["4096"], "mismatched_field": "RSA CA key (ssh-rsa-cert-v01@openssh.com) sizes"}], "host": "localhost", "passed": false, "policy": "Docker poliicy: test10 (version 1)"} diff --git a/test/docker/expected_results/openssh_5.6p1_custom_policy_test10.txt b/test/docker/expected_results/openssh_5.6p1_custom_policy_test10.txt new file mode 100644 index 0000000..7f8befc --- /dev/null +++ b/test/docker/expected_results/openssh_5.6p1_custom_policy_test10.txt @@ -0,0 +1,13 @@ +Host: localhost:2222 +Policy: Docker poliicy: test10 (version 1) +Result: [0;31m⌠Failed![0m +[0;33m +Errors: + * RSA CA key (ssh-rsa-cert-v01@openssh.com) sizes did not match. + - Expected: 4096 + - Actual: 1024 + + * RSA host key (ssh-rsa-cert-v01@openssh.com) sizes did not match. + - Expected: 4096 + - Actual: 3072 +[0m diff --git a/test/docker/expected_results/openssh_5.6p1_custom_policy_test2.json b/test/docker/expected_results/openssh_5.6p1_custom_policy_test2.json new file mode 100644 index 0000000..4d39f6a --- /dev/null +++ b/test/docker/expected_results/openssh_5.6p1_custom_policy_test2.json @@ -0,0 +1 @@ +{"errors": [{"actual": ["diffie-hellman-group-exchange-sha256", "diffie-hellman-group-exchange-sha1", "diffie-hellman-group14-sha1", "diffie-hellman-group1-sha1"], "expected_optional": [""], "expected_required": ["kex_alg1", "kex_alg2"], "mismatched_field": "Key exchanges"}], "host": "localhost", "passed": false, "policy": "Docker policy: test2 (version 1)"} diff --git a/test/docker/expected_results/openssh_5.6p1_custom_policy_test2.txt b/test/docker/expected_results/openssh_5.6p1_custom_policy_test2.txt new file mode 100644 index 0000000..e88e44b --- /dev/null +++ b/test/docker/expected_results/openssh_5.6p1_custom_policy_test2.txt @@ -0,0 +1,9 @@ +Host: localhost:2222 +Policy: Docker policy: test2 (version 1) +Result: [0;31m⌠Failed![0m +[0;33m +Errors: + * Key exchanges did not match. + - Expected: kex_alg1, kex_alg2 + - Actual: diffie-hellman-group-exchange-sha256, diffie-hellman-group-exchange-sha1, diffie-hellman-group14-sha1, diffie-hellman-group1-sha1 +[0m diff --git a/test/docker/expected_results/openssh_5.6p1_custom_policy_test3.json b/test/docker/expected_results/openssh_5.6p1_custom_policy_test3.json new file mode 100644 index 0000000..519fc40 --- /dev/null +++ b/test/docker/expected_results/openssh_5.6p1_custom_policy_test3.json @@ -0,0 +1 @@ +{"errors": [{"actual": ["ssh-rsa", "ssh-dss"], "expected_optional": [""], "expected_required": ["ssh-rsa", "ssh-dss", "key_alg1"], "mismatched_field": "Host keys"}], "host": "localhost", "passed": false, "policy": "Docker policy: test3 (version 1)"} diff --git a/test/docker/expected_results/openssh_5.6p1_custom_policy_test3.txt b/test/docker/expected_results/openssh_5.6p1_custom_policy_test3.txt new file mode 100644 index 0000000..cf7eefc --- /dev/null +++ b/test/docker/expected_results/openssh_5.6p1_custom_policy_test3.txt @@ -0,0 +1,9 @@ +Host: localhost:2222 +Policy: Docker policy: test3 (version 1) +Result: [0;31m⌠Failed![0m +[0;33m +Errors: + * Host keys did not match. + - Expected: ssh-rsa, ssh-dss, key_alg1 + - Actual: ssh-rsa, ssh-dss +[0m diff --git a/test/docker/expected_results/openssh_5.6p1_custom_policy_test4.json b/test/docker/expected_results/openssh_5.6p1_custom_policy_test4.json new file mode 100644 index 0000000..83db23b --- /dev/null +++ b/test/docker/expected_results/openssh_5.6p1_custom_policy_test4.json @@ -0,0 +1 @@ +{"errors": [{"actual": ["aes128-ctr", "aes192-ctr", "aes256-ctr", "arcfour256", "arcfour128", "aes128-cbc", "3des-cbc", "blowfish-cbc", "cast128-cbc", "aes192-cbc", "aes256-cbc", "arcfour", "rijndael-cbc@lysator.liu.se"], "expected_optional": [""], "expected_required": ["cipher_alg1", "cipher_alg2"], "mismatched_field": "Ciphers"}], "host": "localhost", "passed": false, "policy": "Docker policy: test4 (version 1)"} diff --git a/test/docker/expected_results/openssh_5.6p1_custom_policy_test4.txt b/test/docker/expected_results/openssh_5.6p1_custom_policy_test4.txt new file mode 100644 index 0000000..514b715 --- /dev/null +++ b/test/docker/expected_results/openssh_5.6p1_custom_policy_test4.txt @@ -0,0 +1,9 @@ +Host: localhost:2222 +Policy: Docker policy: test4 (version 1) +Result: [0;31m⌠Failed![0m +[0;33m +Errors: + * Ciphers did not match. + - Expected: cipher_alg1, cipher_alg2 + - Actual: aes128-ctr, aes192-ctr, aes256-ctr, arcfour256, arcfour128, aes128-cbc, 3des-cbc, blowfish-cbc, cast128-cbc, aes192-cbc, aes256-cbc, arcfour, rijndael-cbc@lysator.liu.se +[0m diff --git a/test/docker/expected_results/openssh_5.6p1_custom_policy_test5.json b/test/docker/expected_results/openssh_5.6p1_custom_policy_test5.json new file mode 100644 index 0000000..3fbfe09 --- /dev/null +++ b/test/docker/expected_results/openssh_5.6p1_custom_policy_test5.json @@ -0,0 +1 @@ +{"errors": [{"actual": ["hmac-md5", "hmac-sha1", "umac-64@openssh.com", "hmac-ripemd160", "hmac-ripemd160@openssh.com", "hmac-sha1-96", "hmac-md5-96"], "expected_optional": [""], "expected_required": ["hmac-md5", "hmac-sha1", "umac-64@openssh.com", "hmac-ripemd160", "hmac-ripemd160@openssh.com", "hmac_alg1", "hmac-md5-96"], "mismatched_field": "MACs"}], "host": "localhost", "passed": false, "policy": "Docker policy: test5 (version 1)"} diff --git a/test/docker/expected_results/openssh_5.6p1_custom_policy_test5.txt b/test/docker/expected_results/openssh_5.6p1_custom_policy_test5.txt new file mode 100644 index 0000000..746ca8c --- /dev/null +++ b/test/docker/expected_results/openssh_5.6p1_custom_policy_test5.txt @@ -0,0 +1,9 @@ +Host: localhost:2222 +Policy: Docker policy: test5 (version 1) +Result: [0;31m⌠Failed![0m +[0;33m +Errors: + * MACs did not match. + - Expected: hmac-md5, hmac-sha1, umac-64@openssh.com, hmac-ripemd160, hmac-ripemd160@openssh.com, hmac_alg1, hmac-md5-96 + - Actual: hmac-md5, hmac-sha1, umac-64@openssh.com, hmac-ripemd160, hmac-ripemd160@openssh.com, hmac-sha1-96, hmac-md5-96 +[0m diff --git a/test/docker/expected_results/openssh_5.6p1_custom_policy_test7.json b/test/docker/expected_results/openssh_5.6p1_custom_policy_test7.json new file mode 100644 index 0000000..cb4b860 --- /dev/null +++ b/test/docker/expected_results/openssh_5.6p1_custom_policy_test7.json @@ -0,0 +1 @@ +{"errors": [], "host": "localhost", "passed": true, "policy": "Docker poliicy: test7 (version 1)"} diff --git a/test/docker/expected_results/openssh_5.6p1_custom_policy_test7.txt b/test/docker/expected_results/openssh_5.6p1_custom_policy_test7.txt new file mode 100644 index 0000000..4014b23 --- /dev/null +++ b/test/docker/expected_results/openssh_5.6p1_custom_policy_test7.txt @@ -0,0 +1,3 @@ +Host: localhost:2222 +Policy: Docker poliicy: test7 (version 1) +Result: [0;32m✔ Passed[0m diff --git a/test/docker/expected_results/openssh_5.6p1_custom_policy_test8.json b/test/docker/expected_results/openssh_5.6p1_custom_policy_test8.json new file mode 100644 index 0000000..a7fa650 --- /dev/null +++ b/test/docker/expected_results/openssh_5.6p1_custom_policy_test8.json @@ -0,0 +1 @@ +{"errors": [{"actual": ["1024"], "expected_optional": [""], "expected_required": ["2048"], "mismatched_field": "RSA CA key (ssh-rsa-cert-v01@openssh.com) sizes"}], "host": "localhost", "passed": false, "policy": "Docker poliicy: test8 (version 1)"} diff --git a/test/docker/expected_results/openssh_5.6p1_custom_policy_test8.txt b/test/docker/expected_results/openssh_5.6p1_custom_policy_test8.txt new file mode 100644 index 0000000..36dceba --- /dev/null +++ b/test/docker/expected_results/openssh_5.6p1_custom_policy_test8.txt @@ -0,0 +1,9 @@ +Host: localhost:2222 +Policy: Docker poliicy: test8 (version 1) +Result: [0;31m⌠Failed![0m +[0;33m +Errors: + * RSA CA key (ssh-rsa-cert-v01@openssh.com) sizes did not match. + - Expected: 2048 + - Actual: 1024 +[0m diff --git a/test/docker/expected_results/openssh_5.6p1_custom_policy_test9.json b/test/docker/expected_results/openssh_5.6p1_custom_policy_test9.json new file mode 100644 index 0000000..6e9faec --- /dev/null +++ b/test/docker/expected_results/openssh_5.6p1_custom_policy_test9.json @@ -0,0 +1 @@ +{"errors": [{"actual": ["3072"], "expected_optional": [""], "expected_required": ["4096"], "mismatched_field": "RSA host key (ssh-rsa-cert-v01@openssh.com) sizes"}], "host": "localhost", "passed": false, "policy": "Docker poliicy: test9 (version 1)"} diff --git a/test/docker/expected_results/openssh_5.6p1_custom_policy_test9.txt b/test/docker/expected_results/openssh_5.6p1_custom_policy_test9.txt new file mode 100644 index 0000000..fc91c9f --- /dev/null +++ b/test/docker/expected_results/openssh_5.6p1_custom_policy_test9.txt @@ -0,0 +1,9 @@ +Host: localhost:2222 +Policy: Docker poliicy: test9 (version 1) +Result: [0;31m⌠Failed![0m +[0;33m +Errors: + * RSA host key (ssh-rsa-cert-v01@openssh.com) sizes did not match. + - Expected: 4096 + - Actual: 3072 +[0m diff --git a/test/docker/expected_results/openssh_5.6p1_test1.json b/test/docker/expected_results/openssh_5.6p1_test1.json new file mode 100644 index 0000000..f189bd8 --- /dev/null +++ b/test/docker/expected_results/openssh_5.6p1_test1.json @@ -0,0 +1 @@ +{"banner": {"comments": null, "protocol": [2, 0], "raw": "SSH-2.0-OpenSSH_5.6", "software": "OpenSSH_5.6"}, "compression": ["none", "zlib@openssh.com"], "enc": ["aes128-ctr", "aes192-ctr", "aes256-ctr", "arcfour256", "arcfour128", "aes128-cbc", "3des-cbc", "blowfish-cbc", "cast128-cbc", "aes192-cbc", "aes256-cbc", "arcfour", "rijndael-cbc@lysator.liu.se"], "fingerprints": [{"hash": "YZ457EBcJTSxRKI3yXRgtAj3PBf5B9/F36b1SVooml4", "hash_alg": "SHA256", "hostkey": "ssh-rsa"}, {"hash": "3c:c3:38:f8:55:39:c0:4a:5a:17:89:60:2c:a1:fc:6a", "hash_alg": "MD5", "hostkey": "ssh-rsa"}], "kex": [{"algorithm": "diffie-hellman-group-exchange-sha256", "keysize": 1024}, {"algorithm": "diffie-hellman-group-exchange-sha1", "keysize": 1024}, {"algorithm": "diffie-hellman-group14-sha1"}, {"algorithm": "diffie-hellman-group1-sha1"}], "key": [{"algorithm": "ssh-rsa", "keysize": 1024}, {"algorithm": "ssh-dss"}], "mac": ["hmac-md5", "hmac-sha1", "umac-64@openssh.com", "hmac-ripemd160", "hmac-ripemd160@openssh.com", "hmac-sha1-96", "hmac-md5-96"], "target": "localhost"} diff --git a/test/docker/expected_results/openssh_5.6p1_test1.txt b/test/docker/expected_results/openssh_5.6p1_test1.txt new file mode 100644 index 0000000..014d7e7 --- /dev/null +++ b/test/docker/expected_results/openssh_5.6p1_test1.txt @@ -0,0 +1,153 @@ +[0;36m# general[0m +[0;32m(gen) banner: SSH-2.0-OpenSSH_5.6[0m +[0;32m(gen) software: OpenSSH 5.6[0m +[0;32m(gen) compatibility: OpenSSH 4.7-6.6, Dropbear SSH 0.53+ (some functionality from 0.52)[0m +[0;32m(gen) compression: enabled (zlib@openssh.com)[0m + +[0;36m# security[0m +[0;33m(cve) CVE-2018-15473 -- (CVSSv2: 5.3) enumerate usernames due to timing discrepencies[0m +[0;33m(cve) CVE-2016-3115 -- (CVSSv2: 5.5) bypass command restrictions via crafted X11 forwarding data[0m +[0;33m(cve) CVE-2016-1907 -- (CVSSv2: 5.0) cause DoS via crafted network traffic (out of bounds read)[0m +[0;33m(cve) CVE-2015-6564 -- (CVSSv2: 6.9) privilege escalation via leveraging sshd uid[0m +[0;33m(cve) CVE-2015-6563 -- (CVSSv2: 1.9) conduct impersonation attack[0m +[0;33m(cve) CVE-2014-2532 -- (CVSSv2: 5.8) bypass environment restrictions via specific string before wildcard[0m +[0;33m(cve) CVE-2014-1692 -- (CVSSv2: 7.5) cause DoS via triggering error condition (memory corruption)[0m +[0;33m(cve) CVE-2012-0814 -- (CVSSv2: 3.5) leak data via debug messages[0m +[0;33m(cve) CVE-2011-5000 -- (CVSSv2: 3.5) cause DoS via large value in certain length field (memory consumption)[0m +[0;33m(cve) CVE-2010-5107 -- (CVSSv2: 5.0) cause DoS via large number of connections (slot exhaustion)[0m +[0;33m(cve) CVE-2010-4755 -- (CVSSv2: 4.0) cause DoS via crafted glob expression (CPU and memory consumption)[0m +[0;33m(cve) CVE-2010-4478 -- (CVSSv2: 7.5) bypass authentication check via crafted values[0m + +[0;36m# key exchange algorithms[0m +[0;31m(kex) diffie-hellman-group-exchange-sha256 (1024-bit) -- [fail] using small 1024-bit modulus[0m + `- [info] available since OpenSSH 4.4 +[0;31m(kex) diffie-hellman-group-exchange-sha1 (1024-bit) -- [fail] using small 1024-bit modulus[0m +[0;33m `- [warn] using weak hashing algorithm[0m + `- [info] available since OpenSSH 2.3.0 +[0;33m(kex) diffie-hellman-group14-sha1 -- [warn] using weak hashing algorithm[0m + `- [info] available since OpenSSH 3.9, Dropbear SSH 0.53 +[0;31m(kex) diffie-hellman-group1-sha1 -- [fail] using small 1024-bit modulus[0m +[0;31m `- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;31m `- [fail] disabled (in client) since OpenSSH 7.0, logjam attack[0m +[0;33m `- [warn] using weak hashing algorithm[0m + `- [info] available since OpenSSH 2.3.0, Dropbear SSH 0.28 + +[0;36m# host-key algorithms[0m +[0;31m(key) ssh-rsa (1024-bit) -- [fail] using weak hashing algorithm[0m +[0;31m `- [fail] using small 1024-bit modulus[0m + `- [info] available since OpenSSH 2.5.0, Dropbear SSH 0.28 + `- [info] a future deprecation notice has been issued in OpenSSH 8.2: https://www.openssh.com/txt/release-8.2 +[0;31m(key) ssh-dss -- [fail] using small 1024-bit modulus[0m +[0;31m `- [fail] removed (in server) and disabled (in client) since OpenSSH 7.0, weak algorithm[0m +[0;33m `- [warn] using weak random number generator could reveal the key[0m + `- [info] available since OpenSSH 2.1.0, Dropbear SSH 0.28 + +[0;36m# encryption algorithms (ciphers)[0m +[0;32m(enc) aes128-ctr -- [info] available since OpenSSH 3.7, Dropbear SSH 0.52[0m +[0;32m(enc) aes192-ctr -- [info] available since OpenSSH 3.7[0m +[0;32m(enc) aes256-ctr -- [info] available since OpenSSH 3.7, Dropbear SSH 0.52[0m +[0;31m(enc) arcfour256 -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m +[0;33m `- [warn] using weak cipher[0m + `- [info] available since OpenSSH 4.2 +[0;31m(enc) arcfour128 -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m +[0;33m `- [warn] using weak cipher[0m + `- [info] available since OpenSSH 4.2 +[0;31m(enc) aes128-cbc -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] using weak cipher mode[0m + `- [info] available since OpenSSH 2.3.0, Dropbear SSH 0.28 +[0;31m(enc) 3des-cbc -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] disabled (in client) since OpenSSH 7.4, unsafe algorithm[0m +[0;33m `- [warn] using weak cipher[0m +[0;33m `- [warn] using weak cipher mode[0m +[0;33m `- [warn] using small 64-bit block size[0m + `- [info] available since OpenSSH 1.2.2, Dropbear SSH 0.28 +[0;31m(enc) blowfish-cbc -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;31m `- [fail] disabled since Dropbear SSH 0.53[0m +[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m +[0;33m `- [warn] using weak cipher mode[0m +[0;33m `- [warn] using small 64-bit block size[0m + `- [info] available since OpenSSH 1.2.2, Dropbear SSH 0.28 +[0;31m(enc) cast128-cbc -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m +[0;33m `- [warn] using weak cipher mode[0m +[0;33m `- [warn] using small 64-bit block size[0m + `- [info] available since OpenSSH 2.1.0 +[0;31m(enc) aes192-cbc -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] using weak cipher mode[0m + `- [info] available since OpenSSH 2.3.0 +[0;31m(enc) aes256-cbc -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] using weak cipher mode[0m + `- [info] available since OpenSSH 2.3.0, Dropbear SSH 0.47 +[0;31m(enc) arcfour -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m +[0;33m `- [warn] using weak cipher[0m + `- [info] available since OpenSSH 2.1.0 +[0;31m(enc) rijndael-cbc@lysator.liu.se -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m +[0;33m `- [warn] using weak cipher mode[0m + `- [info] available since OpenSSH 2.3.0 + +[0;36m# message authentication code algorithms[0m +[0;31m(mac) hmac-md5 -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m +[0;33m `- [warn] using encrypt-and-MAC mode[0m +[0;33m `- [warn] using weak hashing algorithm[0m + `- [info] available since OpenSSH 2.1.0, Dropbear SSH 0.28 +[0;33m(mac) hmac-sha1 -- [warn] using encrypt-and-MAC mode[0m +[0;33m `- [warn] using weak hashing algorithm[0m + `- [info] available since OpenSSH 2.1.0, Dropbear SSH 0.28 +[0;33m(mac) umac-64@openssh.com -- [warn] using encrypt-and-MAC mode[0m +[0;33m `- [warn] using small 64-bit tag size[0m + `- [info] available since OpenSSH 4.7 +[0;31m(mac) hmac-ripemd160 -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m +[0;33m `- [warn] using encrypt-and-MAC mode[0m + `- [info] available since OpenSSH 2.5.0 +[0;31m(mac) hmac-ripemd160@openssh.com -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m +[0;33m `- [warn] using encrypt-and-MAC mode[0m + `- [info] available since OpenSSH 2.1.0 +[0;31m(mac) hmac-sha1-96 -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m +[0;33m `- [warn] using encrypt-and-MAC mode[0m +[0;33m `- [warn] using weak hashing algorithm[0m + `- [info] available since OpenSSH 2.5.0, Dropbear SSH 0.47 +[0;31m(mac) hmac-md5-96 -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m +[0;33m `- [warn] using encrypt-and-MAC mode[0m +[0;33m `- [warn] using weak hashing algorithm[0m + `- [info] available since OpenSSH 2.5.0 + +[0;36m# fingerprints[0m +[0;32m(fin) ssh-rsa: SHA256:YZ457EBcJTSxRKI3yXRgtAj3PBf5B9/F36b1SVooml4[0m + +[0;36m# algorithm recommendations (for OpenSSH 5.6)[0m +[0;31m(rec) !diffie-hellman-group-exchange-sha256 -- kex algorithm to change (increase modulus size to 2048 bits or larger) [0m +[0;31m(rec) -3des-cbc -- enc algorithm to remove [0m +[0;31m(rec) -aes128-cbc -- enc algorithm to remove [0m +[0;31m(rec) -aes192-cbc -- enc algorithm to remove [0m +[0;31m(rec) -aes256-cbc -- enc algorithm to remove [0m +[0;31m(rec) -arcfour -- enc algorithm to remove [0m +[0;31m(rec) -arcfour128 -- enc algorithm to remove [0m +[0;31m(rec) -arcfour256 -- enc algorithm to remove [0m +[0;31m(rec) -blowfish-cbc -- enc algorithm to remove [0m +[0;31m(rec) -cast128-cbc -- enc algorithm to remove [0m +[0;31m(rec) -diffie-hellman-group-exchange-sha1 -- kex algorithm to remove [0m +[0;31m(rec) -diffie-hellman-group1-sha1 -- kex algorithm to remove [0m +[0;31m(rec) -hmac-md5 -- mac algorithm to remove [0m +[0;31m(rec) -hmac-md5-96 -- mac algorithm to remove [0m +[0;31m(rec) -hmac-ripemd160 -- mac algorithm to remove [0m +[0;31m(rec) -hmac-ripemd160@openssh.com -- mac algorithm to remove [0m +[0;31m(rec) -hmac-sha1-96 -- mac algorithm to remove [0m +[0;31m(rec) -rijndael-cbc@lysator.liu.se -- enc algorithm to remove [0m +[0;31m(rec) -ssh-dss -- key algorithm to remove [0m +[0;31m(rec) -ssh-rsa -- key algorithm to remove [0m +[0;33m(rec) -diffie-hellman-group14-sha1 -- kex algorithm to remove [0m +[0;33m(rec) -hmac-sha1 -- mac algorithm to remove [0m +[0;33m(rec) -umac-64@openssh.com -- mac algorithm to remove [0m + +[0;36m# additional info[0m +[0;33m(nfo) For hardening guides on common OSes, please see: <https://www.ssh-audit.com/hardening_guides.html>[0m + diff --git a/test/docker/expected_results/openssh_5.6p1_test2.json b/test/docker/expected_results/openssh_5.6p1_test2.json new file mode 100644 index 0000000..64d1590 --- /dev/null +++ b/test/docker/expected_results/openssh_5.6p1_test2.json @@ -0,0 +1 @@ +{"banner": {"comments": null, "protocol": [2, 0], "raw": "SSH-2.0-OpenSSH_5.6", "software": "OpenSSH_5.6"}, "compression": ["none", "zlib@openssh.com"], "enc": ["aes128-ctr", "aes192-ctr", "aes256-ctr", "arcfour256", "arcfour128", "aes128-cbc", "3des-cbc", "blowfish-cbc", "cast128-cbc", "aes192-cbc", "aes256-cbc", "arcfour", "rijndael-cbc@lysator.liu.se"], "fingerprints": [{"hash": "YZ457EBcJTSxRKI3yXRgtAj3PBf5B9/F36b1SVooml4", "hash_alg": "SHA256", "hostkey": "ssh-rsa"}, {"hash": "3c:c3:38:f8:55:39:c0:4a:5a:17:89:60:2c:a1:fc:6a", "hash_alg": "MD5", "hostkey": "ssh-rsa"}], "kex": [{"algorithm": "diffie-hellman-group-exchange-sha256", "keysize": 1024}, {"algorithm": "diffie-hellman-group-exchange-sha1", "keysize": 1024}, {"algorithm": "diffie-hellman-group14-sha1"}, {"algorithm": "diffie-hellman-group1-sha1"}], "key": [{"algorithm": "ssh-rsa", "keysize": 1024}, {"algorithm": "ssh-rsa-cert-v01@openssh.com", "casize": 1024, "keysize": 1024}], "mac": ["hmac-md5", "hmac-sha1", "umac-64@openssh.com", "hmac-ripemd160", "hmac-ripemd160@openssh.com", "hmac-sha1-96", "hmac-md5-96"], "target": "localhost"} diff --git a/test/docker/expected_results/openssh_5.6p1_test2.txt b/test/docker/expected_results/openssh_5.6p1_test2.txt new file mode 100644 index 0000000..2a6825f --- /dev/null +++ b/test/docker/expected_results/openssh_5.6p1_test2.txt @@ -0,0 +1,153 @@ +[0;36m# general[0m +[0;32m(gen) banner: SSH-2.0-OpenSSH_5.6[0m +[0;32m(gen) software: OpenSSH 5.6[0m +[0;32m(gen) compatibility: OpenSSH 5.6-6.6, Dropbear SSH 0.53+ (some functionality from 0.52)[0m +[0;32m(gen) compression: enabled (zlib@openssh.com)[0m + +[0;36m# security[0m +[0;33m(cve) CVE-2018-15473 -- (CVSSv2: 5.3) enumerate usernames due to timing discrepencies[0m +[0;33m(cve) CVE-2016-3115 -- (CVSSv2: 5.5) bypass command restrictions via crafted X11 forwarding data[0m +[0;33m(cve) CVE-2016-1907 -- (CVSSv2: 5.0) cause DoS via crafted network traffic (out of bounds read)[0m +[0;33m(cve) CVE-2015-6564 -- (CVSSv2: 6.9) privilege escalation via leveraging sshd uid[0m +[0;33m(cve) CVE-2015-6563 -- (CVSSv2: 1.9) conduct impersonation attack[0m +[0;33m(cve) CVE-2014-2532 -- (CVSSv2: 5.8) bypass environment restrictions via specific string before wildcard[0m +[0;33m(cve) CVE-2014-1692 -- (CVSSv2: 7.5) cause DoS via triggering error condition (memory corruption)[0m +[0;33m(cve) CVE-2012-0814 -- (CVSSv2: 3.5) leak data via debug messages[0m +[0;33m(cve) CVE-2011-5000 -- (CVSSv2: 3.5) cause DoS via large value in certain length field (memory consumption)[0m +[0;33m(cve) CVE-2010-5107 -- (CVSSv2: 5.0) cause DoS via large number of connections (slot exhaustion)[0m +[0;33m(cve) CVE-2010-4755 -- (CVSSv2: 4.0) cause DoS via crafted glob expression (CPU and memory consumption)[0m +[0;33m(cve) CVE-2010-4478 -- (CVSSv2: 7.5) bypass authentication check via crafted values[0m + +[0;36m# key exchange algorithms[0m +[0;31m(kex) diffie-hellman-group-exchange-sha256 (1024-bit) -- [fail] using small 1024-bit modulus[0m + `- [info] available since OpenSSH 4.4 +[0;31m(kex) diffie-hellman-group-exchange-sha1 (1024-bit) -- [fail] using small 1024-bit modulus[0m +[0;33m `- [warn] using weak hashing algorithm[0m + `- [info] available since OpenSSH 2.3.0 +[0;33m(kex) diffie-hellman-group14-sha1 -- [warn] using weak hashing algorithm[0m + `- [info] available since OpenSSH 3.9, Dropbear SSH 0.53 +[0;31m(kex) diffie-hellman-group1-sha1 -- [fail] using small 1024-bit modulus[0m +[0;31m `- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;31m `- [fail] disabled (in client) since OpenSSH 7.0, logjam attack[0m +[0;33m `- [warn] using weak hashing algorithm[0m + `- [info] available since OpenSSH 2.3.0, Dropbear SSH 0.28 + +[0;36m# host-key algorithms[0m +[0;31m(key) ssh-rsa (1024-bit) -- [fail] using weak hashing algorithm[0m +[0;31m `- [fail] using small 1024-bit modulus[0m + `- [info] available since OpenSSH 2.5.0, Dropbear SSH 0.28 + `- [info] a future deprecation notice has been issued in OpenSSH 8.2: https://www.openssh.com/txt/release-8.2 +[0;31m(key) ssh-rsa-cert-v01@openssh.com (1024-bit cert/1024-bit CA) -- [fail] using weak hashing algorithm[0m +[0;31m `- [fail] using small 1024-bit modulus[0m + `- [info] available since OpenSSH 5.6 + `- [info] a future deprecation notice has been issued in OpenSSH 8.2: https://www.openssh.com/txt/release-8.2 + +[0;36m# encryption algorithms (ciphers)[0m +[0;32m(enc) aes128-ctr -- [info] available since OpenSSH 3.7, Dropbear SSH 0.52[0m +[0;32m(enc) aes192-ctr -- [info] available since OpenSSH 3.7[0m +[0;32m(enc) aes256-ctr -- [info] available since OpenSSH 3.7, Dropbear SSH 0.52[0m +[0;31m(enc) arcfour256 -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m +[0;33m `- [warn] using weak cipher[0m + `- [info] available since OpenSSH 4.2 +[0;31m(enc) arcfour128 -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m +[0;33m `- [warn] using weak cipher[0m + `- [info] available since OpenSSH 4.2 +[0;31m(enc) aes128-cbc -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] using weak cipher mode[0m + `- [info] available since OpenSSH 2.3.0, Dropbear SSH 0.28 +[0;31m(enc) 3des-cbc -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] disabled (in client) since OpenSSH 7.4, unsafe algorithm[0m +[0;33m `- [warn] using weak cipher[0m +[0;33m `- [warn] using weak cipher mode[0m +[0;33m `- [warn] using small 64-bit block size[0m + `- [info] available since OpenSSH 1.2.2, Dropbear SSH 0.28 +[0;31m(enc) blowfish-cbc -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;31m `- [fail] disabled since Dropbear SSH 0.53[0m +[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m +[0;33m `- [warn] using weak cipher mode[0m +[0;33m `- [warn] using small 64-bit block size[0m + `- [info] available since OpenSSH 1.2.2, Dropbear SSH 0.28 +[0;31m(enc) cast128-cbc -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m +[0;33m `- [warn] using weak cipher mode[0m +[0;33m `- [warn] using small 64-bit block size[0m + `- [info] available since OpenSSH 2.1.0 +[0;31m(enc) aes192-cbc -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] using weak cipher mode[0m + `- [info] available since OpenSSH 2.3.0 +[0;31m(enc) aes256-cbc -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] using weak cipher mode[0m + `- [info] available since OpenSSH 2.3.0, Dropbear SSH 0.47 +[0;31m(enc) arcfour -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m +[0;33m `- [warn] using weak cipher[0m + `- [info] available since OpenSSH 2.1.0 +[0;31m(enc) rijndael-cbc@lysator.liu.se -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m +[0;33m `- [warn] using weak cipher mode[0m + `- [info] available since OpenSSH 2.3.0 + +[0;36m# message authentication code algorithms[0m +[0;31m(mac) hmac-md5 -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m +[0;33m `- [warn] using encrypt-and-MAC mode[0m +[0;33m `- [warn] using weak hashing algorithm[0m + `- [info] available since OpenSSH 2.1.0, Dropbear SSH 0.28 +[0;33m(mac) hmac-sha1 -- [warn] using encrypt-and-MAC mode[0m +[0;33m `- [warn] using weak hashing algorithm[0m + `- [info] available since OpenSSH 2.1.0, Dropbear SSH 0.28 +[0;33m(mac) umac-64@openssh.com -- [warn] using encrypt-and-MAC mode[0m +[0;33m `- [warn] using small 64-bit tag size[0m + `- [info] available since OpenSSH 4.7 +[0;31m(mac) hmac-ripemd160 -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m +[0;33m `- [warn] using encrypt-and-MAC mode[0m + `- [info] available since OpenSSH 2.5.0 +[0;31m(mac) hmac-ripemd160@openssh.com -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m +[0;33m `- [warn] using encrypt-and-MAC mode[0m + `- [info] available since OpenSSH 2.1.0 +[0;31m(mac) hmac-sha1-96 -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m +[0;33m `- [warn] using encrypt-and-MAC mode[0m +[0;33m `- [warn] using weak hashing algorithm[0m + `- [info] available since OpenSSH 2.5.0, Dropbear SSH 0.47 +[0;31m(mac) hmac-md5-96 -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m +[0;33m `- [warn] using encrypt-and-MAC mode[0m +[0;33m `- [warn] using weak hashing algorithm[0m + `- [info] available since OpenSSH 2.5.0 + +[0;36m# fingerprints[0m +[0;32m(fin) ssh-rsa: SHA256:YZ457EBcJTSxRKI3yXRgtAj3PBf5B9/F36b1SVooml4[0m + +[0;36m# algorithm recommendations (for OpenSSH 5.6)[0m +[0;31m(rec) !diffie-hellman-group-exchange-sha256 -- kex algorithm to change (increase modulus size to 2048 bits or larger) [0m +[0;31m(rec) -3des-cbc -- enc algorithm to remove [0m +[0;31m(rec) -aes128-cbc -- enc algorithm to remove [0m +[0;31m(rec) -aes192-cbc -- enc algorithm to remove [0m +[0;31m(rec) -aes256-cbc -- enc algorithm to remove [0m +[0;31m(rec) -arcfour -- enc algorithm to remove [0m +[0;31m(rec) -arcfour128 -- enc algorithm to remove [0m +[0;31m(rec) -arcfour256 -- enc algorithm to remove [0m +[0;31m(rec) -blowfish-cbc -- enc algorithm to remove [0m +[0;31m(rec) -cast128-cbc -- enc algorithm to remove [0m +[0;31m(rec) -diffie-hellman-group-exchange-sha1 -- kex algorithm to remove [0m +[0;31m(rec) -diffie-hellman-group1-sha1 -- kex algorithm to remove [0m +[0;31m(rec) -hmac-md5 -- mac algorithm to remove [0m +[0;31m(rec) -hmac-md5-96 -- mac algorithm to remove [0m +[0;31m(rec) -hmac-ripemd160 -- mac algorithm to remove [0m +[0;31m(rec) -hmac-ripemd160@openssh.com -- mac algorithm to remove [0m +[0;31m(rec) -hmac-sha1-96 -- mac algorithm to remove [0m +[0;31m(rec) -rijndael-cbc@lysator.liu.se -- enc algorithm to remove [0m +[0;31m(rec) -ssh-rsa -- key algorithm to remove [0m +[0;31m(rec) -ssh-rsa-cert-v01@openssh.com -- key algorithm to remove [0m +[0;33m(rec) -diffie-hellman-group14-sha1 -- kex algorithm to remove [0m +[0;33m(rec) -hmac-sha1 -- mac algorithm to remove [0m +[0;33m(rec) -umac-64@openssh.com -- mac algorithm to remove [0m + +[0;36m# additional info[0m +[0;33m(nfo) For hardening guides on common OSes, please see: <https://www.ssh-audit.com/hardening_guides.html>[0m + diff --git a/test/docker/expected_results/openssh_5.6p1_test3.json b/test/docker/expected_results/openssh_5.6p1_test3.json new file mode 100644 index 0000000..db22eed --- /dev/null +++ b/test/docker/expected_results/openssh_5.6p1_test3.json @@ -0,0 +1 @@ +{"banner": {"comments": null, "protocol": [2, 0], "raw": "SSH-2.0-OpenSSH_5.6", "software": "OpenSSH_5.6"}, "compression": ["none", "zlib@openssh.com"], "enc": ["aes128-ctr", "aes192-ctr", "aes256-ctr", "arcfour256", "arcfour128", "aes128-cbc", "3des-cbc", "blowfish-cbc", "cast128-cbc", "aes192-cbc", "aes256-cbc", "arcfour", "rijndael-cbc@lysator.liu.se"], "fingerprints": [{"hash": "YZ457EBcJTSxRKI3yXRgtAj3PBf5B9/F36b1SVooml4", "hash_alg": "SHA256", "hostkey": "ssh-rsa"}, {"hash": "3c:c3:38:f8:55:39:c0:4a:5a:17:89:60:2c:a1:fc:6a", "hash_alg": "MD5", "hostkey": "ssh-rsa"}], "kex": [{"algorithm": "diffie-hellman-group-exchange-sha256", "keysize": 1024}, {"algorithm": "diffie-hellman-group-exchange-sha1", "keysize": 1024}, {"algorithm": "diffie-hellman-group14-sha1"}, {"algorithm": "diffie-hellman-group1-sha1"}], "key": [{"algorithm": "ssh-rsa", "keysize": 1024}, {"algorithm": "ssh-rsa-cert-v01@openssh.com", "casize": 3072, "keysize": 1024}], "mac": ["hmac-md5", "hmac-sha1", "umac-64@openssh.com", "hmac-ripemd160", "hmac-ripemd160@openssh.com", "hmac-sha1-96", "hmac-md5-96"], "target": "localhost"} diff --git a/test/docker/expected_results/openssh_5.6p1_test3.txt b/test/docker/expected_results/openssh_5.6p1_test3.txt new file mode 100644 index 0000000..657b22e --- /dev/null +++ b/test/docker/expected_results/openssh_5.6p1_test3.txt @@ -0,0 +1,153 @@ +[0;36m# general[0m +[0;32m(gen) banner: SSH-2.0-OpenSSH_5.6[0m +[0;32m(gen) software: OpenSSH 5.6[0m +[0;32m(gen) compatibility: OpenSSH 5.6-6.6, Dropbear SSH 0.53+ (some functionality from 0.52)[0m +[0;32m(gen) compression: enabled (zlib@openssh.com)[0m + +[0;36m# security[0m +[0;33m(cve) CVE-2018-15473 -- (CVSSv2: 5.3) enumerate usernames due to timing discrepencies[0m +[0;33m(cve) CVE-2016-3115 -- (CVSSv2: 5.5) bypass command restrictions via crafted X11 forwarding data[0m +[0;33m(cve) CVE-2016-1907 -- (CVSSv2: 5.0) cause DoS via crafted network traffic (out of bounds read)[0m +[0;33m(cve) CVE-2015-6564 -- (CVSSv2: 6.9) privilege escalation via leveraging sshd uid[0m +[0;33m(cve) CVE-2015-6563 -- (CVSSv2: 1.9) conduct impersonation attack[0m +[0;33m(cve) CVE-2014-2532 -- (CVSSv2: 5.8) bypass environment restrictions via specific string before wildcard[0m +[0;33m(cve) CVE-2014-1692 -- (CVSSv2: 7.5) cause DoS via triggering error condition (memory corruption)[0m +[0;33m(cve) CVE-2012-0814 -- (CVSSv2: 3.5) leak data via debug messages[0m +[0;33m(cve) CVE-2011-5000 -- (CVSSv2: 3.5) cause DoS via large value in certain length field (memory consumption)[0m +[0;33m(cve) CVE-2010-5107 -- (CVSSv2: 5.0) cause DoS via large number of connections (slot exhaustion)[0m +[0;33m(cve) CVE-2010-4755 -- (CVSSv2: 4.0) cause DoS via crafted glob expression (CPU and memory consumption)[0m +[0;33m(cve) CVE-2010-4478 -- (CVSSv2: 7.5) bypass authentication check via crafted values[0m + +[0;36m# key exchange algorithms[0m +[0;31m(kex) diffie-hellman-group-exchange-sha256 (1024-bit) -- [fail] using small 1024-bit modulus[0m + `- [info] available since OpenSSH 4.4 +[0;31m(kex) diffie-hellman-group-exchange-sha1 (1024-bit) -- [fail] using small 1024-bit modulus[0m +[0;33m `- [warn] using weak hashing algorithm[0m + `- [info] available since OpenSSH 2.3.0 +[0;33m(kex) diffie-hellman-group14-sha1 -- [warn] using weak hashing algorithm[0m + `- [info] available since OpenSSH 3.9, Dropbear SSH 0.53 +[0;31m(kex) diffie-hellman-group1-sha1 -- [fail] using small 1024-bit modulus[0m +[0;31m `- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;31m `- [fail] disabled (in client) since OpenSSH 7.0, logjam attack[0m +[0;33m `- [warn] using weak hashing algorithm[0m + `- [info] available since OpenSSH 2.3.0, Dropbear SSH 0.28 + +[0;36m# host-key algorithms[0m +[0;31m(key) ssh-rsa (1024-bit) -- [fail] using weak hashing algorithm[0m +[0;31m `- [fail] using small 1024-bit modulus[0m + `- [info] available since OpenSSH 2.5.0, Dropbear SSH 0.28 + `- [info] a future deprecation notice has been issued in OpenSSH 8.2: https://www.openssh.com/txt/release-8.2 +[0;31m(key) ssh-rsa-cert-v01@openssh.com (1024-bit cert/3072-bit CA) -- [fail] using weak hashing algorithm[0m +[0;31m `- [fail] using small 1024-bit modulus[0m + `- [info] available since OpenSSH 5.6 + `- [info] a future deprecation notice has been issued in OpenSSH 8.2: https://www.openssh.com/txt/release-8.2 + +[0;36m# encryption algorithms (ciphers)[0m +[0;32m(enc) aes128-ctr -- [info] available since OpenSSH 3.7, Dropbear SSH 0.52[0m +[0;32m(enc) aes192-ctr -- [info] available since OpenSSH 3.7[0m +[0;32m(enc) aes256-ctr -- [info] available since OpenSSH 3.7, Dropbear SSH 0.52[0m +[0;31m(enc) arcfour256 -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m +[0;33m `- [warn] using weak cipher[0m + `- [info] available since OpenSSH 4.2 +[0;31m(enc) arcfour128 -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m +[0;33m `- [warn] using weak cipher[0m + `- [info] available since OpenSSH 4.2 +[0;31m(enc) aes128-cbc -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] using weak cipher mode[0m + `- [info] available since OpenSSH 2.3.0, Dropbear SSH 0.28 +[0;31m(enc) 3des-cbc -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] disabled (in client) since OpenSSH 7.4, unsafe algorithm[0m +[0;33m `- [warn] using weak cipher[0m +[0;33m `- [warn] using weak cipher mode[0m +[0;33m `- [warn] using small 64-bit block size[0m + `- [info] available since OpenSSH 1.2.2, Dropbear SSH 0.28 +[0;31m(enc) blowfish-cbc -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;31m `- [fail] disabled since Dropbear SSH 0.53[0m +[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m +[0;33m `- [warn] using weak cipher mode[0m +[0;33m `- [warn] using small 64-bit block size[0m + `- [info] available since OpenSSH 1.2.2, Dropbear SSH 0.28 +[0;31m(enc) cast128-cbc -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m +[0;33m `- [warn] using weak cipher mode[0m +[0;33m `- [warn] using small 64-bit block size[0m + `- [info] available since OpenSSH 2.1.0 +[0;31m(enc) aes192-cbc -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] using weak cipher mode[0m + `- [info] available since OpenSSH 2.3.0 +[0;31m(enc) aes256-cbc -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] using weak cipher mode[0m + `- [info] available since OpenSSH 2.3.0, Dropbear SSH 0.47 +[0;31m(enc) arcfour -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m +[0;33m `- [warn] using weak cipher[0m + `- [info] available since OpenSSH 2.1.0 +[0;31m(enc) rijndael-cbc@lysator.liu.se -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m +[0;33m `- [warn] using weak cipher mode[0m + `- [info] available since OpenSSH 2.3.0 + +[0;36m# message authentication code algorithms[0m +[0;31m(mac) hmac-md5 -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m +[0;33m `- [warn] using encrypt-and-MAC mode[0m +[0;33m `- [warn] using weak hashing algorithm[0m + `- [info] available since OpenSSH 2.1.0, Dropbear SSH 0.28 +[0;33m(mac) hmac-sha1 -- [warn] using encrypt-and-MAC mode[0m +[0;33m `- [warn] using weak hashing algorithm[0m + `- [info] available since OpenSSH 2.1.0, Dropbear SSH 0.28 +[0;33m(mac) umac-64@openssh.com -- [warn] using encrypt-and-MAC mode[0m +[0;33m `- [warn] using small 64-bit tag size[0m + `- [info] available since OpenSSH 4.7 +[0;31m(mac) hmac-ripemd160 -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m +[0;33m `- [warn] using encrypt-and-MAC mode[0m + `- [info] available since OpenSSH 2.5.0 +[0;31m(mac) hmac-ripemd160@openssh.com -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m +[0;33m `- [warn] using encrypt-and-MAC mode[0m + `- [info] available since OpenSSH 2.1.0 +[0;31m(mac) hmac-sha1-96 -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m +[0;33m `- [warn] using encrypt-and-MAC mode[0m +[0;33m `- [warn] using weak hashing algorithm[0m + `- [info] available since OpenSSH 2.5.0, Dropbear SSH 0.47 +[0;31m(mac) hmac-md5-96 -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m +[0;33m `- [warn] using encrypt-and-MAC mode[0m +[0;33m `- [warn] using weak hashing algorithm[0m + `- [info] available since OpenSSH 2.5.0 + +[0;36m# fingerprints[0m +[0;32m(fin) ssh-rsa: SHA256:YZ457EBcJTSxRKI3yXRgtAj3PBf5B9/F36b1SVooml4[0m + +[0;36m# algorithm recommendations (for OpenSSH 5.6)[0m +[0;31m(rec) !diffie-hellman-group-exchange-sha256 -- kex algorithm to change (increase modulus size to 2048 bits or larger) [0m +[0;31m(rec) -3des-cbc -- enc algorithm to remove [0m +[0;31m(rec) -aes128-cbc -- enc algorithm to remove [0m +[0;31m(rec) -aes192-cbc -- enc algorithm to remove [0m +[0;31m(rec) -aes256-cbc -- enc algorithm to remove [0m +[0;31m(rec) -arcfour -- enc algorithm to remove [0m +[0;31m(rec) -arcfour128 -- enc algorithm to remove [0m +[0;31m(rec) -arcfour256 -- enc algorithm to remove [0m +[0;31m(rec) -blowfish-cbc -- enc algorithm to remove [0m +[0;31m(rec) -cast128-cbc -- enc algorithm to remove [0m +[0;31m(rec) -diffie-hellman-group-exchange-sha1 -- kex algorithm to remove [0m +[0;31m(rec) -diffie-hellman-group1-sha1 -- kex algorithm to remove [0m +[0;31m(rec) -hmac-md5 -- mac algorithm to remove [0m +[0;31m(rec) -hmac-md5-96 -- mac algorithm to remove [0m +[0;31m(rec) -hmac-ripemd160 -- mac algorithm to remove [0m +[0;31m(rec) -hmac-ripemd160@openssh.com -- mac algorithm to remove [0m +[0;31m(rec) -hmac-sha1-96 -- mac algorithm to remove [0m +[0;31m(rec) -rijndael-cbc@lysator.liu.se -- enc algorithm to remove [0m +[0;31m(rec) -ssh-rsa -- key algorithm to remove [0m +[0;31m(rec) -ssh-rsa-cert-v01@openssh.com -- key algorithm to remove [0m +[0;33m(rec) -diffie-hellman-group14-sha1 -- kex algorithm to remove [0m +[0;33m(rec) -hmac-sha1 -- mac algorithm to remove [0m +[0;33m(rec) -umac-64@openssh.com -- mac algorithm to remove [0m + +[0;36m# additional info[0m +[0;33m(nfo) For hardening guides on common OSes, please see: <https://www.ssh-audit.com/hardening_guides.html>[0m + diff --git a/test/docker/expected_results/openssh_5.6p1_test4.json b/test/docker/expected_results/openssh_5.6p1_test4.json new file mode 100644 index 0000000..a5c725d --- /dev/null +++ b/test/docker/expected_results/openssh_5.6p1_test4.json @@ -0,0 +1 @@ +{"banner": {"comments": null, "protocol": [2, 0], "raw": "SSH-2.0-OpenSSH_5.6", "software": "OpenSSH_5.6"}, "compression": ["none", "zlib@openssh.com"], "enc": ["aes128-ctr", "aes192-ctr", "aes256-ctr", "arcfour256", "arcfour128", "aes128-cbc", "3des-cbc", "blowfish-cbc", "cast128-cbc", "aes192-cbc", "aes256-cbc", "arcfour", "rijndael-cbc@lysator.liu.se"], "fingerprints": [{"hash": "nsWtdJ9Z67Vrf7OsUzQov7esXhsWAfVppArGh25u244", "hash_alg": "SHA256", "hostkey": "ssh-rsa"}, {"hash": "18:e2:51:fe:21:6c:78:d0:b8:cf:32:d4:bd:56:42:e1", "hash_alg": "MD5", "hostkey": "ssh-rsa"}], "kex": [{"algorithm": "diffie-hellman-group-exchange-sha256", "keysize": 1024}, {"algorithm": "diffie-hellman-group-exchange-sha1", "keysize": 1024}, {"algorithm": "diffie-hellman-group14-sha1"}, {"algorithm": "diffie-hellman-group1-sha1"}], "key": [{"algorithm": "ssh-rsa", "keysize": 3072}, {"algorithm": "ssh-rsa-cert-v01@openssh.com", "casize": 1024, "keysize": 3072}], "mac": ["hmac-md5", "hmac-sha1", "umac-64@openssh.com", "hmac-ripemd160", "hmac-ripemd160@openssh.com", "hmac-sha1-96", "hmac-md5-96"], "target": "localhost"} diff --git a/test/docker/expected_results/openssh_5.6p1_test4.txt b/test/docker/expected_results/openssh_5.6p1_test4.txt new file mode 100644 index 0000000..fb48d1c --- /dev/null +++ b/test/docker/expected_results/openssh_5.6p1_test4.txt @@ -0,0 +1,152 @@ +[0;36m# general[0m +[0;32m(gen) banner: SSH-2.0-OpenSSH_5.6[0m +[0;32m(gen) software: OpenSSH 5.6[0m +[0;32m(gen) compatibility: OpenSSH 5.6-6.6, Dropbear SSH 0.53+ (some functionality from 0.52)[0m +[0;32m(gen) compression: enabled (zlib@openssh.com)[0m + +[0;36m# security[0m +[0;33m(cve) CVE-2018-15473 -- (CVSSv2: 5.3) enumerate usernames due to timing discrepencies[0m +[0;33m(cve) CVE-2016-3115 -- (CVSSv2: 5.5) bypass command restrictions via crafted X11 forwarding data[0m +[0;33m(cve) CVE-2016-1907 -- (CVSSv2: 5.0) cause DoS via crafted network traffic (out of bounds read)[0m +[0;33m(cve) CVE-2015-6564 -- (CVSSv2: 6.9) privilege escalation via leveraging sshd uid[0m +[0;33m(cve) CVE-2015-6563 -- (CVSSv2: 1.9) conduct impersonation attack[0m +[0;33m(cve) CVE-2014-2532 -- (CVSSv2: 5.8) bypass environment restrictions via specific string before wildcard[0m +[0;33m(cve) CVE-2014-1692 -- (CVSSv2: 7.5) cause DoS via triggering error condition (memory corruption)[0m +[0;33m(cve) CVE-2012-0814 -- (CVSSv2: 3.5) leak data via debug messages[0m +[0;33m(cve) CVE-2011-5000 -- (CVSSv2: 3.5) cause DoS via large value in certain length field (memory consumption)[0m +[0;33m(cve) CVE-2010-5107 -- (CVSSv2: 5.0) cause DoS via large number of connections (slot exhaustion)[0m +[0;33m(cve) CVE-2010-4755 -- (CVSSv2: 4.0) cause DoS via crafted glob expression (CPU and memory consumption)[0m +[0;33m(cve) CVE-2010-4478 -- (CVSSv2: 7.5) bypass authentication check via crafted values[0m + +[0;36m# key exchange algorithms[0m +[0;31m(kex) diffie-hellman-group-exchange-sha256 (1024-bit) -- [fail] using small 1024-bit modulus[0m + `- [info] available since OpenSSH 4.4 +[0;31m(kex) diffie-hellman-group-exchange-sha1 (1024-bit) -- [fail] using small 1024-bit modulus[0m +[0;33m `- [warn] using weak hashing algorithm[0m + `- [info] available since OpenSSH 2.3.0 +[0;33m(kex) diffie-hellman-group14-sha1 -- [warn] using weak hashing algorithm[0m + `- [info] available since OpenSSH 3.9, Dropbear SSH 0.53 +[0;31m(kex) diffie-hellman-group1-sha1 -- [fail] using small 1024-bit modulus[0m +[0;31m `- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;31m `- [fail] disabled (in client) since OpenSSH 7.0, logjam attack[0m +[0;33m `- [warn] using weak hashing algorithm[0m + `- [info] available since OpenSSH 2.3.0, Dropbear SSH 0.28 + +[0;36m# host-key algorithms[0m +[0;31m(key) ssh-rsa (3072-bit) -- [fail] using weak hashing algorithm[0m + `- [info] available since OpenSSH 2.5.0, Dropbear SSH 0.28 + `- [info] a future deprecation notice has been issued in OpenSSH 8.2: https://www.openssh.com/txt/release-8.2 +[0;31m(key) ssh-rsa-cert-v01@openssh.com (3072-bit cert/1024-bit CA) -- [fail] using weak hashing algorithm[0m +[0;31m `- [fail] using small 1024-bit modulus[0m + `- [info] available since OpenSSH 5.6 + `- [info] a future deprecation notice has been issued in OpenSSH 8.2: https://www.openssh.com/txt/release-8.2 + +[0;36m# encryption algorithms (ciphers)[0m +[0;32m(enc) aes128-ctr -- [info] available since OpenSSH 3.7, Dropbear SSH 0.52[0m +[0;32m(enc) aes192-ctr -- [info] available since OpenSSH 3.7[0m +[0;32m(enc) aes256-ctr -- [info] available since OpenSSH 3.7, Dropbear SSH 0.52[0m +[0;31m(enc) arcfour256 -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m +[0;33m `- [warn] using weak cipher[0m + `- [info] available since OpenSSH 4.2 +[0;31m(enc) arcfour128 -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m +[0;33m `- [warn] using weak cipher[0m + `- [info] available since OpenSSH 4.2 +[0;31m(enc) aes128-cbc -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] using weak cipher mode[0m + `- [info] available since OpenSSH 2.3.0, Dropbear SSH 0.28 +[0;31m(enc) 3des-cbc -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] disabled (in client) since OpenSSH 7.4, unsafe algorithm[0m +[0;33m `- [warn] using weak cipher[0m +[0;33m `- [warn] using weak cipher mode[0m +[0;33m `- [warn] using small 64-bit block size[0m + `- [info] available since OpenSSH 1.2.2, Dropbear SSH 0.28 +[0;31m(enc) blowfish-cbc -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;31m `- [fail] disabled since Dropbear SSH 0.53[0m +[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m +[0;33m `- [warn] using weak cipher mode[0m +[0;33m `- [warn] using small 64-bit block size[0m + `- [info] available since OpenSSH 1.2.2, Dropbear SSH 0.28 +[0;31m(enc) cast128-cbc -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m +[0;33m `- [warn] using weak cipher mode[0m +[0;33m `- [warn] using small 64-bit block size[0m + `- [info] available since OpenSSH 2.1.0 +[0;31m(enc) aes192-cbc -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] using weak cipher mode[0m + `- [info] available since OpenSSH 2.3.0 +[0;31m(enc) aes256-cbc -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] using weak cipher mode[0m + `- [info] available since OpenSSH 2.3.0, Dropbear SSH 0.47 +[0;31m(enc) arcfour -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m +[0;33m `- [warn] using weak cipher[0m + `- [info] available since OpenSSH 2.1.0 +[0;31m(enc) rijndael-cbc@lysator.liu.se -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m +[0;33m `- [warn] using weak cipher mode[0m + `- [info] available since OpenSSH 2.3.0 + +[0;36m# message authentication code algorithms[0m +[0;31m(mac) hmac-md5 -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m +[0;33m `- [warn] using encrypt-and-MAC mode[0m +[0;33m `- [warn] using weak hashing algorithm[0m + `- [info] available since OpenSSH 2.1.0, Dropbear SSH 0.28 +[0;33m(mac) hmac-sha1 -- [warn] using encrypt-and-MAC mode[0m +[0;33m `- [warn] using weak hashing algorithm[0m + `- [info] available since OpenSSH 2.1.0, Dropbear SSH 0.28 +[0;33m(mac) umac-64@openssh.com -- [warn] using encrypt-and-MAC mode[0m +[0;33m `- [warn] using small 64-bit tag size[0m + `- [info] available since OpenSSH 4.7 +[0;31m(mac) hmac-ripemd160 -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m +[0;33m `- [warn] using encrypt-and-MAC mode[0m + `- [info] available since OpenSSH 2.5.0 +[0;31m(mac) hmac-ripemd160@openssh.com -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m +[0;33m `- [warn] using encrypt-and-MAC mode[0m + `- [info] available since OpenSSH 2.1.0 +[0;31m(mac) hmac-sha1-96 -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m +[0;33m `- [warn] using encrypt-and-MAC mode[0m +[0;33m `- [warn] using weak hashing algorithm[0m + `- [info] available since OpenSSH 2.5.0, Dropbear SSH 0.47 +[0;31m(mac) hmac-md5-96 -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m +[0;33m `- [warn] using encrypt-and-MAC mode[0m +[0;33m `- [warn] using weak hashing algorithm[0m + `- [info] available since OpenSSH 2.5.0 + +[0;36m# fingerprints[0m +[0;32m(fin) ssh-rsa: SHA256:nsWtdJ9Z67Vrf7OsUzQov7esXhsWAfVppArGh25u244[0m + +[0;36m# algorithm recommendations (for OpenSSH 5.6)[0m +[0;31m(rec) !diffie-hellman-group-exchange-sha256 -- kex algorithm to change (increase modulus size to 2048 bits or larger) [0m +[0;31m(rec) -3des-cbc -- enc algorithm to remove [0m +[0;31m(rec) -aes128-cbc -- enc algorithm to remove [0m +[0;31m(rec) -aes192-cbc -- enc algorithm to remove [0m +[0;31m(rec) -aes256-cbc -- enc algorithm to remove [0m +[0;31m(rec) -arcfour -- enc algorithm to remove [0m +[0;31m(rec) -arcfour128 -- enc algorithm to remove [0m +[0;31m(rec) -arcfour256 -- enc algorithm to remove [0m +[0;31m(rec) -blowfish-cbc -- enc algorithm to remove [0m +[0;31m(rec) -cast128-cbc -- enc algorithm to remove [0m +[0;31m(rec) -diffie-hellman-group-exchange-sha1 -- kex algorithm to remove [0m +[0;31m(rec) -diffie-hellman-group1-sha1 -- kex algorithm to remove [0m +[0;31m(rec) -hmac-md5 -- mac algorithm to remove [0m +[0;31m(rec) -hmac-md5-96 -- mac algorithm to remove [0m +[0;31m(rec) -hmac-ripemd160 -- mac algorithm to remove [0m +[0;31m(rec) -hmac-ripemd160@openssh.com -- mac algorithm to remove [0m +[0;31m(rec) -hmac-sha1-96 -- mac algorithm to remove [0m +[0;31m(rec) -rijndael-cbc@lysator.liu.se -- enc algorithm to remove [0m +[0;31m(rec) -ssh-rsa -- key algorithm to remove [0m +[0;31m(rec) -ssh-rsa-cert-v01@openssh.com -- key algorithm to remove [0m +[0;33m(rec) -diffie-hellman-group14-sha1 -- kex algorithm to remove [0m +[0;33m(rec) -hmac-sha1 -- mac algorithm to remove [0m +[0;33m(rec) -umac-64@openssh.com -- mac algorithm to remove [0m + +[0;36m# additional info[0m +[0;33m(nfo) For hardening guides on common OSes, please see: <https://www.ssh-audit.com/hardening_guides.html>[0m + diff --git a/test/docker/expected_results/openssh_5.6p1_test5.json b/test/docker/expected_results/openssh_5.6p1_test5.json new file mode 100644 index 0000000..24523b8 --- /dev/null +++ b/test/docker/expected_results/openssh_5.6p1_test5.json @@ -0,0 +1 @@ +{"banner": {"comments": null, "protocol": [2, 0], "raw": "SSH-2.0-OpenSSH_5.6", "software": "OpenSSH_5.6"}, "compression": ["none", "zlib@openssh.com"], "enc": ["aes128-ctr", "aes192-ctr", "aes256-ctr", "arcfour256", "arcfour128", "aes128-cbc", "3des-cbc", "blowfish-cbc", "cast128-cbc", "aes192-cbc", "aes256-cbc", "arcfour", "rijndael-cbc@lysator.liu.se"], "fingerprints": [{"hash": "nsWtdJ9Z67Vrf7OsUzQov7esXhsWAfVppArGh25u244", "hash_alg": "SHA256", "hostkey": "ssh-rsa"}, {"hash": "18:e2:51:fe:21:6c:78:d0:b8:cf:32:d4:bd:56:42:e1", "hash_alg": "MD5", "hostkey": "ssh-rsa"}], "kex": [{"algorithm": "diffie-hellman-group-exchange-sha256", "keysize": 1024}, {"algorithm": "diffie-hellman-group-exchange-sha1", "keysize": 1024}, {"algorithm": "diffie-hellman-group14-sha1"}, {"algorithm": "diffie-hellman-group1-sha1"}], "key": [{"algorithm": "ssh-rsa", "keysize": 3072}, {"algorithm": "ssh-rsa-cert-v01@openssh.com", "casize": 3072, "keysize": 3072}], "mac": ["hmac-md5", "hmac-sha1", "umac-64@openssh.com", "hmac-ripemd160", "hmac-ripemd160@openssh.com", "hmac-sha1-96", "hmac-md5-96"], "target": "localhost"} diff --git a/test/docker/expected_results/openssh_5.6p1_test5.txt b/test/docker/expected_results/openssh_5.6p1_test5.txt new file mode 100644 index 0000000..5ff250a --- /dev/null +++ b/test/docker/expected_results/openssh_5.6p1_test5.txt @@ -0,0 +1,151 @@ +[0;36m# general[0m +[0;32m(gen) banner: SSH-2.0-OpenSSH_5.6[0m +[0;32m(gen) software: OpenSSH 5.6[0m +[0;32m(gen) compatibility: OpenSSH 5.6-6.6, Dropbear SSH 0.53+ (some functionality from 0.52)[0m +[0;32m(gen) compression: enabled (zlib@openssh.com)[0m + +[0;36m# security[0m +[0;33m(cve) CVE-2018-15473 -- (CVSSv2: 5.3) enumerate usernames due to timing discrepencies[0m +[0;33m(cve) CVE-2016-3115 -- (CVSSv2: 5.5) bypass command restrictions via crafted X11 forwarding data[0m +[0;33m(cve) CVE-2016-1907 -- (CVSSv2: 5.0) cause DoS via crafted network traffic (out of bounds read)[0m +[0;33m(cve) CVE-2015-6564 -- (CVSSv2: 6.9) privilege escalation via leveraging sshd uid[0m +[0;33m(cve) CVE-2015-6563 -- (CVSSv2: 1.9) conduct impersonation attack[0m +[0;33m(cve) CVE-2014-2532 -- (CVSSv2: 5.8) bypass environment restrictions via specific string before wildcard[0m +[0;33m(cve) CVE-2014-1692 -- (CVSSv2: 7.5) cause DoS via triggering error condition (memory corruption)[0m +[0;33m(cve) CVE-2012-0814 -- (CVSSv2: 3.5) leak data via debug messages[0m +[0;33m(cve) CVE-2011-5000 -- (CVSSv2: 3.5) cause DoS via large value in certain length field (memory consumption)[0m +[0;33m(cve) CVE-2010-5107 -- (CVSSv2: 5.0) cause DoS via large number of connections (slot exhaustion)[0m +[0;33m(cve) CVE-2010-4755 -- (CVSSv2: 4.0) cause DoS via crafted glob expression (CPU and memory consumption)[0m +[0;33m(cve) CVE-2010-4478 -- (CVSSv2: 7.5) bypass authentication check via crafted values[0m + +[0;36m# key exchange algorithms[0m +[0;31m(kex) diffie-hellman-group-exchange-sha256 (1024-bit) -- [fail] using small 1024-bit modulus[0m + `- [info] available since OpenSSH 4.4 +[0;31m(kex) diffie-hellman-group-exchange-sha1 (1024-bit) -- [fail] using small 1024-bit modulus[0m +[0;33m `- [warn] using weak hashing algorithm[0m + `- [info] available since OpenSSH 2.3.0 +[0;33m(kex) diffie-hellman-group14-sha1 -- [warn] using weak hashing algorithm[0m + `- [info] available since OpenSSH 3.9, Dropbear SSH 0.53 +[0;31m(kex) diffie-hellman-group1-sha1 -- [fail] using small 1024-bit modulus[0m +[0;31m `- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;31m `- [fail] disabled (in client) since OpenSSH 7.0, logjam attack[0m +[0;33m `- [warn] using weak hashing algorithm[0m + `- [info] available since OpenSSH 2.3.0, Dropbear SSH 0.28 + +[0;36m# host-key algorithms[0m +[0;31m(key) ssh-rsa (3072-bit) -- [fail] using weak hashing algorithm[0m + `- [info] available since OpenSSH 2.5.0, Dropbear SSH 0.28 + `- [info] a future deprecation notice has been issued in OpenSSH 8.2: https://www.openssh.com/txt/release-8.2 +[0;31m(key) ssh-rsa-cert-v01@openssh.com (3072-bit cert/3072-bit CA) -- [fail] using weak hashing algorithm[0m + `- [info] available since OpenSSH 5.6 + `- [info] a future deprecation notice has been issued in OpenSSH 8.2: https://www.openssh.com/txt/release-8.2 + +[0;36m# encryption algorithms (ciphers)[0m +[0;32m(enc) aes128-ctr -- [info] available since OpenSSH 3.7, Dropbear SSH 0.52[0m +[0;32m(enc) aes192-ctr -- [info] available since OpenSSH 3.7[0m +[0;32m(enc) aes256-ctr -- [info] available since OpenSSH 3.7, Dropbear SSH 0.52[0m +[0;31m(enc) arcfour256 -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m +[0;33m `- [warn] using weak cipher[0m + `- [info] available since OpenSSH 4.2 +[0;31m(enc) arcfour128 -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m +[0;33m `- [warn] using weak cipher[0m + `- [info] available since OpenSSH 4.2 +[0;31m(enc) aes128-cbc -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] using weak cipher mode[0m + `- [info] available since OpenSSH 2.3.0, Dropbear SSH 0.28 +[0;31m(enc) 3des-cbc -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] disabled (in client) since OpenSSH 7.4, unsafe algorithm[0m +[0;33m `- [warn] using weak cipher[0m +[0;33m `- [warn] using weak cipher mode[0m +[0;33m `- [warn] using small 64-bit block size[0m + `- [info] available since OpenSSH 1.2.2, Dropbear SSH 0.28 +[0;31m(enc) blowfish-cbc -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;31m `- [fail] disabled since Dropbear SSH 0.53[0m +[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m +[0;33m `- [warn] using weak cipher mode[0m +[0;33m `- [warn] using small 64-bit block size[0m + `- [info] available since OpenSSH 1.2.2, Dropbear SSH 0.28 +[0;31m(enc) cast128-cbc -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m +[0;33m `- [warn] using weak cipher mode[0m +[0;33m `- [warn] using small 64-bit block size[0m + `- [info] available since OpenSSH 2.1.0 +[0;31m(enc) aes192-cbc -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] using weak cipher mode[0m + `- [info] available since OpenSSH 2.3.0 +[0;31m(enc) aes256-cbc -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] using weak cipher mode[0m + `- [info] available since OpenSSH 2.3.0, Dropbear SSH 0.47 +[0;31m(enc) arcfour -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m +[0;33m `- [warn] using weak cipher[0m + `- [info] available since OpenSSH 2.1.0 +[0;31m(enc) rijndael-cbc@lysator.liu.se -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m +[0;33m `- [warn] using weak cipher mode[0m + `- [info] available since OpenSSH 2.3.0 + +[0;36m# message authentication code algorithms[0m +[0;31m(mac) hmac-md5 -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m +[0;33m `- [warn] using encrypt-and-MAC mode[0m +[0;33m `- [warn] using weak hashing algorithm[0m + `- [info] available since OpenSSH 2.1.0, Dropbear SSH 0.28 +[0;33m(mac) hmac-sha1 -- [warn] using encrypt-and-MAC mode[0m +[0;33m `- [warn] using weak hashing algorithm[0m + `- [info] available since OpenSSH 2.1.0, Dropbear SSH 0.28 +[0;33m(mac) umac-64@openssh.com -- [warn] using encrypt-and-MAC mode[0m +[0;33m `- [warn] using small 64-bit tag size[0m + `- [info] available since OpenSSH 4.7 +[0;31m(mac) hmac-ripemd160 -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m +[0;33m `- [warn] using encrypt-and-MAC mode[0m + `- [info] available since OpenSSH 2.5.0 +[0;31m(mac) hmac-ripemd160@openssh.com -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m +[0;33m `- [warn] using encrypt-and-MAC mode[0m + `- [info] available since OpenSSH 2.1.0 +[0;31m(mac) hmac-sha1-96 -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m +[0;33m `- [warn] using encrypt-and-MAC mode[0m +[0;33m `- [warn] using weak hashing algorithm[0m + `- [info] available since OpenSSH 2.5.0, Dropbear SSH 0.47 +[0;31m(mac) hmac-md5-96 -- [fail] removed (in server) since OpenSSH 6.7, unsafe algorithm[0m +[0;33m `- [warn] disabled (in client) since OpenSSH 7.2, legacy algorithm[0m +[0;33m `- [warn] using encrypt-and-MAC mode[0m +[0;33m `- [warn] using weak hashing algorithm[0m + `- [info] available since OpenSSH 2.5.0 + +[0;36m# fingerprints[0m +[0;32m(fin) ssh-rsa: SHA256:nsWtdJ9Z67Vrf7OsUzQov7esXhsWAfVppArGh25u244[0m + +[0;36m# algorithm recommendations (for OpenSSH 5.6)[0m +[0;31m(rec) !diffie-hellman-group-exchange-sha256 -- kex algorithm to change (increase modulus size to 2048 bits or larger) [0m +[0;31m(rec) -3des-cbc -- enc algorithm to remove [0m +[0;31m(rec) -aes128-cbc -- enc algorithm to remove [0m +[0;31m(rec) -aes192-cbc -- enc algorithm to remove [0m +[0;31m(rec) -aes256-cbc -- enc algorithm to remove [0m +[0;31m(rec) -arcfour -- enc algorithm to remove [0m +[0;31m(rec) -arcfour128 -- enc algorithm to remove [0m +[0;31m(rec) -arcfour256 -- enc algorithm to remove [0m +[0;31m(rec) -blowfish-cbc -- enc algorithm to remove [0m +[0;31m(rec) -cast128-cbc -- enc algorithm to remove [0m +[0;31m(rec) -diffie-hellman-group-exchange-sha1 -- kex algorithm to remove [0m +[0;31m(rec) -diffie-hellman-group1-sha1 -- kex algorithm to remove [0m +[0;31m(rec) -hmac-md5 -- mac algorithm to remove [0m +[0;31m(rec) -hmac-md5-96 -- mac algorithm to remove [0m +[0;31m(rec) -hmac-ripemd160 -- mac algorithm to remove [0m +[0;31m(rec) -hmac-ripemd160@openssh.com -- mac algorithm to remove [0m +[0;31m(rec) -hmac-sha1-96 -- mac algorithm to remove [0m +[0;31m(rec) -rijndael-cbc@lysator.liu.se -- enc algorithm to remove [0m +[0;31m(rec) -ssh-rsa -- key algorithm to remove [0m +[0;31m(rec) -ssh-rsa-cert-v01@openssh.com -- key algorithm to remove [0m +[0;33m(rec) -diffie-hellman-group14-sha1 -- kex algorithm to remove [0m +[0;33m(rec) -hmac-sha1 -- mac algorithm to remove [0m +[0;33m(rec) -umac-64@openssh.com -- mac algorithm to remove [0m + +[0;36m# additional info[0m +[0;33m(nfo) For hardening guides on common OSes, please see: <https://www.ssh-audit.com/hardening_guides.html>[0m + diff --git a/test/docker/expected_results/openssh_8.0p1_builtin_policy_test1.json b/test/docker/expected_results/openssh_8.0p1_builtin_policy_test1.json new file mode 100644 index 0000000..f907cde --- /dev/null +++ b/test/docker/expected_results/openssh_8.0p1_builtin_policy_test1.json @@ -0,0 +1 @@ +{"errors": [], "host": "localhost", "passed": true, "policy": "Hardened OpenSSH Server v8.0 (version 1)"} diff --git a/test/docker/expected_results/openssh_8.0p1_builtin_policy_test1.txt b/test/docker/expected_results/openssh_8.0p1_builtin_policy_test1.txt new file mode 100644 index 0000000..1b6ddee --- /dev/null +++ b/test/docker/expected_results/openssh_8.0p1_builtin_policy_test1.txt @@ -0,0 +1,3 @@ +Host: localhost:2222 +Policy: Hardened OpenSSH Server v8.0 (version 1) +Result: [0;32m✔ Passed[0m diff --git a/test/docker/expected_results/openssh_8.0p1_builtin_policy_test2.json b/test/docker/expected_results/openssh_8.0p1_builtin_policy_test2.json new file mode 100644 index 0000000..49a13bc --- /dev/null +++ b/test/docker/expected_results/openssh_8.0p1_builtin_policy_test2.json @@ -0,0 +1 @@ +{"errors": [{"actual": ["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"], "expected_optional": [""], "expected_required": ["hmac-sha2-256-etm@openssh.com", "hmac-sha2-512-etm@openssh.com", "umac-128-etm@openssh.com"], "mismatched_field": "MACs"}], "host": "localhost", "passed": false, "policy": "Hardened OpenSSH Server v8.0 (version 1)"} diff --git a/test/docker/expected_results/openssh_8.0p1_builtin_policy_test2.txt b/test/docker/expected_results/openssh_8.0p1_builtin_policy_test2.txt new file mode 100644 index 0000000..de1f3e7 --- /dev/null +++ b/test/docker/expected_results/openssh_8.0p1_builtin_policy_test2.txt @@ -0,0 +1,9 @@ +Host: localhost:2222 +Policy: Hardened OpenSSH Server v8.0 (version 1) +Result: [0;31m⌠Failed![0m +[0;33m +Errors: + * MACs did not match. + - Expected: hmac-sha2-256-etm@openssh.com, hmac-sha2-512-etm@openssh.com, umac-128-etm@openssh.com + - Actual: 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 +[0m diff --git a/test/docker/expected_results/openssh_8.0p1_custom_policy_test11.json b/test/docker/expected_results/openssh_8.0p1_custom_policy_test11.json new file mode 100644 index 0000000..2e105ff --- /dev/null +++ b/test/docker/expected_results/openssh_8.0p1_custom_policy_test11.json @@ -0,0 +1 @@ +{"errors": [], "host": "localhost", "passed": true, "policy": "Docker policy: test11 (version 1)"} diff --git a/test/docker/expected_results/openssh_8.0p1_custom_policy_test11.txt b/test/docker/expected_results/openssh_8.0p1_custom_policy_test11.txt new file mode 100644 index 0000000..024bcb9 --- /dev/null +++ b/test/docker/expected_results/openssh_8.0p1_custom_policy_test11.txt @@ -0,0 +1,3 @@ +Host: localhost:2222 +Policy: Docker policy: test11 (version 1) +Result: [0;32m✔ Passed[0m diff --git a/test/docker/expected_results/openssh_8.0p1_custom_policy_test12.json b/test/docker/expected_results/openssh_8.0p1_custom_policy_test12.json new file mode 100644 index 0000000..677fb96 --- /dev/null +++ b/test/docker/expected_results/openssh_8.0p1_custom_policy_test12.json @@ -0,0 +1 @@ +{"errors": [{"actual": ["3072"], "expected_optional": [""], "expected_required": ["4096"], "mismatched_field": "RSA host key (rsa-sha2-256) sizes"}, {"actual": ["3072"], "expected_optional": [""], "expected_required": ["4096"], "mismatched_field": "RSA host key (rsa-sha2-512) sizes"}, {"actual": ["3072"], "expected_optional": [""], "expected_required": ["4096"], "mismatched_field": "RSA host key (ssh-rsa) sizes"}], "host": "localhost", "passed": false, "policy": "Docker policy: test12 (version 1)"} diff --git a/test/docker/expected_results/openssh_8.0p1_custom_policy_test12.txt b/test/docker/expected_results/openssh_8.0p1_custom_policy_test12.txt new file mode 100644 index 0000000..6fb0561 --- /dev/null +++ b/test/docker/expected_results/openssh_8.0p1_custom_policy_test12.txt @@ -0,0 +1,17 @@ +Host: localhost:2222 +Policy: Docker policy: test12 (version 1) +Result: [0;31m⌠Failed![0m +[0;33m +Errors: + * RSA host key (rsa-sha2-256) sizes did not match. + - Expected: 4096 + - Actual: 3072 + + * RSA host key (rsa-sha2-512) sizes did not match. + - Expected: 4096 + - Actual: 3072 + + * RSA host key (ssh-rsa) sizes did not match. + - Expected: 4096 + - Actual: 3072 +[0m diff --git a/test/docker/expected_results/openssh_8.0p1_custom_policy_test13.json b/test/docker/expected_results/openssh_8.0p1_custom_policy_test13.json new file mode 100644 index 0000000..e412128 --- /dev/null +++ b/test/docker/expected_results/openssh_8.0p1_custom_policy_test13.json @@ -0,0 +1 @@ +{"errors": [], "host": "localhost", "passed": true, "policy": "Docker policy: test13 (version 1)"} diff --git a/test/docker/expected_results/openssh_8.0p1_custom_policy_test13.txt b/test/docker/expected_results/openssh_8.0p1_custom_policy_test13.txt new file mode 100644 index 0000000..b8b4b25 --- /dev/null +++ b/test/docker/expected_results/openssh_8.0p1_custom_policy_test13.txt @@ -0,0 +1,3 @@ +Host: localhost:2222 +Policy: Docker policy: test13 (version 1) +Result: [0;32m✔ Passed[0m diff --git a/test/docker/expected_results/openssh_8.0p1_custom_policy_test14.json b/test/docker/expected_results/openssh_8.0p1_custom_policy_test14.json new file mode 100644 index 0000000..e7a39f8 --- /dev/null +++ b/test/docker/expected_results/openssh_8.0p1_custom_policy_test14.json @@ -0,0 +1 @@ +{"errors": [{"actual": ["2048"], "expected_optional": [""], "expected_required": ["4096"], "mismatched_field": "Group exchange (diffie-hellman-group-exchange-sha256) modulus sizes"}], "host": "localhost", "passed": false, "policy": "Docker policy: test14 (version 1)"} diff --git a/test/docker/expected_results/openssh_8.0p1_custom_policy_test14.txt b/test/docker/expected_results/openssh_8.0p1_custom_policy_test14.txt new file mode 100644 index 0000000..2bb59fb --- /dev/null +++ b/test/docker/expected_results/openssh_8.0p1_custom_policy_test14.txt @@ -0,0 +1,9 @@ +Host: localhost:2222 +Policy: Docker policy: test14 (version 1) +Result: [0;31m⌠Failed![0m +[0;33m +Errors: + * Group exchange (diffie-hellman-group-exchange-sha256) modulus sizes did not match. + - Expected: 4096 + - Actual: 2048 +[0m diff --git a/test/docker/expected_results/openssh_8.0p1_custom_policy_test6.json b/test/docker/expected_results/openssh_8.0p1_custom_policy_test6.json new file mode 100644 index 0000000..04620b2 --- /dev/null +++ b/test/docker/expected_results/openssh_8.0p1_custom_policy_test6.json @@ -0,0 +1 @@ +{"errors": [], "host": "localhost", "passed": true, "policy": "Docker policy: test6 (version 1)"} diff --git a/test/docker/expected_results/openssh_8.0p1_custom_policy_test6.txt b/test/docker/expected_results/openssh_8.0p1_custom_policy_test6.txt new file mode 100644 index 0000000..b0e9441 --- /dev/null +++ b/test/docker/expected_results/openssh_8.0p1_custom_policy_test6.txt @@ -0,0 +1,3 @@ +Host: localhost:2222 +Policy: Docker policy: test6 (version 1) +Result: [0;32m✔ Passed[0m diff --git a/test/docker/expected_results/openssh_8.0p1_test1.json b/test/docker/expected_results/openssh_8.0p1_test1.json new file mode 100644 index 0000000..cf610a3 --- /dev/null +++ b/test/docker/expected_results/openssh_8.0p1_test1.json @@ -0,0 +1 @@ +{"banner": {"comments": null, "protocol": [2, 0], "raw": "SSH-2.0-OpenSSH_8.0", "software": "OpenSSH_8.0"}, "compression": ["none", "zlib@openssh.com"], "enc": ["chacha20-poly1305@openssh.com", "aes128-ctr", "aes192-ctr", "aes256-ctr", "aes128-gcm@openssh.com", "aes256-gcm@openssh.com"], "fingerprints": [{"hash": "UrnXIVH+7dlw8UqYocl48yUEcKrthGDQG2CPCgp7MxU", "hash_alg": "SHA256", "hostkey": "ssh-ed25519"}, {"hash": "1e:0c:7b:34:73:bf:52:41:b0:f9:d1:a9:ab:98:c7:c9", "hash_alg": "MD5", "hostkey": "ssh-ed25519"}, {"hash": "nsWtdJ9Z67Vrf7OsUzQov7esXhsWAfVppArGh25u244", "hash_alg": "SHA256", "hostkey": "ssh-rsa"}, {"hash": "18:e2:51:fe:21:6c:78:d0:b8:cf:32:d4:bd:56:42:e1", "hash_alg": "MD5", "hostkey": "ssh-rsa"}], "kex": [{"algorithm": "curve25519-sha256"}, {"algorithm": "curve25519-sha256@libssh.org"}, {"algorithm": "ecdh-sha2-nistp256"}, {"algorithm": "ecdh-sha2-nistp384"}, {"algorithm": "ecdh-sha2-nistp521"}, {"algorithm": "diffie-hellman-group-exchange-sha256", "keysize": 2048}, {"algorithm": "diffie-hellman-group16-sha512"}, {"algorithm": "diffie-hellman-group18-sha512"}, {"algorithm": "diffie-hellman-group14-sha256"}, {"algorithm": "diffie-hellman-group14-sha1"}], "key": [{"algorithm": "rsa-sha2-512", "keysize": 3072}, {"algorithm": "rsa-sha2-256", "keysize": 3072}, {"algorithm": "ssh-rsa", "keysize": 3072}, {"algorithm": "ecdsa-sha2-nistp256"}, {"algorithm": "ssh-ed25519"}], "mac": ["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"], "target": "localhost"} diff --git a/test/docker/expected_results/openssh_8.0p1_test1.txt b/test/docker/expected_results/openssh_8.0p1_test1.txt new file mode 100644 index 0000000..d7e45b1 --- /dev/null +++ b/test/docker/expected_results/openssh_8.0p1_test1.txt @@ -0,0 +1,85 @@ +[0;36m# general[0m +[0;32m(gen) banner: SSH-2.0-OpenSSH_8.0[0m +[0;32m(gen) software: OpenSSH 8.0[0m +[0;32m(gen) compatibility: OpenSSH 7.4+, Dropbear SSH 2018.76+[0m +[0;32m(gen) compression: enabled (zlib@openssh.com)[0m + +[0;36m# key exchange algorithms[0m +[0;32m(kex) curve25519-sha256 -- [info] available since OpenSSH 7.4, Dropbear SSH 2018.76[0m +[0;32m(kex) curve25519-sha256@libssh.org -- [info] available since OpenSSH 6.5, Dropbear SSH 2013.62[0m +[0;31m(kex) ecdh-sha2-nistp256 -- [fail] using weak elliptic curves[0m + `- [info] available since OpenSSH 5.7, Dropbear SSH 2013.62 +[0;31m(kex) ecdh-sha2-nistp384 -- [fail] using weak elliptic curves[0m + `- [info] available since OpenSSH 5.7, Dropbear SSH 2013.62 +[0;31m(kex) ecdh-sha2-nistp521 -- [fail] using weak elliptic curves[0m + `- [info] available since OpenSSH 5.7, Dropbear SSH 2013.62 +[0;32m(kex) diffie-hellman-group-exchange-sha256 (2048-bit) -- [info] available since OpenSSH 4.4[0m +[0;32m(kex) diffie-hellman-group16-sha512 -- [info] available since OpenSSH 7.3, Dropbear SSH 2016.73[0m +[0;32m(kex) diffie-hellman-group18-sha512 -- [info] available since OpenSSH 7.3[0m +[0;32m(kex) diffie-hellman-group14-sha256 -- [info] available since OpenSSH 7.3, Dropbear SSH 2016.73[0m +[0;33m(kex) diffie-hellman-group14-sha1 -- [warn] using weak hashing algorithm[0m + `- [info] available since OpenSSH 3.9, Dropbear SSH 0.53 + +[0;36m# host-key algorithms[0m +[0;32m(key) rsa-sha2-512 (3072-bit) -- [info] available since OpenSSH 7.2[0m +[0;32m(key) rsa-sha2-256 (3072-bit) -- [info] available since OpenSSH 7.2[0m +[0;31m(key) ssh-rsa (3072-bit) -- [fail] using weak hashing algorithm[0m + `- [info] available since OpenSSH 2.5.0, Dropbear SSH 0.28 + `- [info] a future deprecation notice has been issued in OpenSSH 8.2: https://www.openssh.com/txt/release-8.2 +[0;31m(key) ecdsa-sha2-nistp256 -- [fail] using weak elliptic curves[0m +[0;33m `- [warn] using weak random number generator could reveal the key[0m + `- [info] available since OpenSSH 5.7, Dropbear SSH 2013.62 +[0;32m(key) ssh-ed25519 -- [info] available since OpenSSH 6.5[0m + +[0;36m# encryption algorithms (ciphers)[0m +[0;32m(enc) chacha20-poly1305@openssh.com -- [info] available since OpenSSH 6.5[0m + `- [info] default cipher since OpenSSH 6.9. +[0;32m(enc) aes128-ctr -- [info] available since OpenSSH 3.7, Dropbear SSH 0.52[0m +[0;32m(enc) aes192-ctr -- [info] available since OpenSSH 3.7[0m +[0;32m(enc) aes256-ctr -- [info] available since OpenSSH 3.7, Dropbear SSH 0.52[0m +[0;32m(enc) aes128-gcm@openssh.com -- [info] available since OpenSSH 6.2[0m +[0;32m(enc) aes256-gcm@openssh.com -- [info] available since OpenSSH 6.2[0m + +[0;36m# message authentication code algorithms[0m +[0;33m(mac) umac-64-etm@openssh.com -- [warn] using small 64-bit tag size[0m + `- [info] available since OpenSSH 6.2 +[0;32m(mac) umac-128-etm@openssh.com -- [info] available since OpenSSH 6.2[0m +[0;32m(mac) hmac-sha2-256-etm@openssh.com -- [info] available since OpenSSH 6.2[0m +[0;32m(mac) hmac-sha2-512-etm@openssh.com -- [info] available since OpenSSH 6.2[0m +[0;33m(mac) hmac-sha1-etm@openssh.com -- [warn] using weak hashing algorithm[0m + `- [info] available since OpenSSH 6.2 +[0;33m(mac) umac-64@openssh.com -- [warn] using encrypt-and-MAC mode[0m +[0;33m `- [warn] using small 64-bit tag size[0m + `- [info] available since OpenSSH 4.7 +[0;33m(mac) umac-128@openssh.com -- [warn] using encrypt-and-MAC mode[0m + `- [info] available since OpenSSH 6.2 +[0;33m(mac) hmac-sha2-256 -- [warn] using encrypt-and-MAC mode[0m + `- [info] available since OpenSSH 5.9, Dropbear SSH 2013.56 +[0;33m(mac) hmac-sha2-512 -- [warn] using encrypt-and-MAC mode[0m + `- [info] available since OpenSSH 5.9, Dropbear SSH 2013.56 +[0;33m(mac) hmac-sha1 -- [warn] using encrypt-and-MAC mode[0m +[0;33m `- [warn] using weak hashing algorithm[0m + `- [info] available since OpenSSH 2.1.0, Dropbear SSH 0.28 + +[0;36m# fingerprints[0m +[0;32m(fin) ssh-ed25519: SHA256:UrnXIVH+7dlw8UqYocl48yUEcKrthGDQG2CPCgp7MxU[0m +[0;32m(fin) ssh-rsa: SHA256:nsWtdJ9Z67Vrf7OsUzQov7esXhsWAfVppArGh25u244[0m + +[0;36m# algorithm recommendations (for OpenSSH 8.0)[0m +[0;31m(rec) -ecdh-sha2-nistp256 -- kex algorithm to remove [0m +[0;31m(rec) -ecdh-sha2-nistp384 -- kex algorithm to remove [0m +[0;31m(rec) -ecdh-sha2-nistp521 -- kex algorithm to remove [0m +[0;31m(rec) -ecdsa-sha2-nistp256 -- key algorithm to remove [0m +[0;31m(rec) -ssh-rsa -- key algorithm to remove [0m +[0;33m(rec) -diffie-hellman-group14-sha1 -- kex algorithm to remove [0m +[0;33m(rec) -hmac-sha1 -- mac algorithm to remove [0m +[0;33m(rec) -hmac-sha1-etm@openssh.com -- mac algorithm to remove [0m +[0;33m(rec) -hmac-sha2-256 -- mac algorithm to remove [0m +[0;33m(rec) -hmac-sha2-512 -- mac algorithm to remove [0m +[0;33m(rec) -umac-128@openssh.com -- mac algorithm to remove [0m +[0;33m(rec) -umac-64-etm@openssh.com -- mac algorithm to remove [0m +[0;33m(rec) -umac-64@openssh.com -- mac algorithm to remove [0m + +[0;36m# additional info[0m +[0;33m(nfo) For hardening guides on common OSes, please see: <https://www.ssh-audit.com/hardening_guides.html>[0m + diff --git a/test/docker/expected_results/openssh_8.0p1_test2.json b/test/docker/expected_results/openssh_8.0p1_test2.json new file mode 100644 index 0000000..fb323eb --- /dev/null +++ b/test/docker/expected_results/openssh_8.0p1_test2.json @@ -0,0 +1 @@ +{"banner": {"comments": null, "protocol": [2, 0], "raw": "SSH-2.0-OpenSSH_8.0", "software": "OpenSSH_8.0"}, "compression": ["none", "zlib@openssh.com"], "enc": ["chacha20-poly1305@openssh.com", "aes128-ctr", "aes192-ctr", "aes256-ctr", "aes128-gcm@openssh.com", "aes256-gcm@openssh.com"], "fingerprints": [{"hash": "UrnXIVH+7dlw8UqYocl48yUEcKrthGDQG2CPCgp7MxU", "hash_alg": "SHA256", "hostkey": "ssh-ed25519"}, {"hash": "1e:0c:7b:34:73:bf:52:41:b0:f9:d1:a9:ab:98:c7:c9", "hash_alg": "MD5", "hostkey": "ssh-ed25519"}], "kex": [{"algorithm": "curve25519-sha256"}, {"algorithm": "curve25519-sha256@libssh.org"}, {"algorithm": "ecdh-sha2-nistp256"}, {"algorithm": "ecdh-sha2-nistp384"}, {"algorithm": "ecdh-sha2-nistp521"}, {"algorithm": "diffie-hellman-group-exchange-sha256", "keysize": 2048}, {"algorithm": "diffie-hellman-group16-sha512"}, {"algorithm": "diffie-hellman-group18-sha512"}, {"algorithm": "diffie-hellman-group14-sha256"}, {"algorithm": "diffie-hellman-group14-sha1"}], "key": [{"algorithm": "ssh-ed25519"}, {"algorithm": "ssh-ed25519-cert-v01@openssh.com"}], "mac": ["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"], "target": "localhost"} diff --git a/test/docker/expected_results/openssh_8.0p1_test2.txt b/test/docker/expected_results/openssh_8.0p1_test2.txt new file mode 100644 index 0000000..a13be8a --- /dev/null +++ b/test/docker/expected_results/openssh_8.0p1_test2.txt @@ -0,0 +1,77 @@ +[0;36m# general[0m +[0;32m(gen) banner: SSH-2.0-OpenSSH_8.0[0m +[0;32m(gen) software: OpenSSH 8.0[0m +[0;32m(gen) compatibility: OpenSSH 7.4+, Dropbear SSH 2018.76+[0m +[0;32m(gen) compression: enabled (zlib@openssh.com)[0m + +[0;36m# key exchange algorithms[0m +[0;32m(kex) curve25519-sha256 -- [info] available since OpenSSH 7.4, Dropbear SSH 2018.76[0m +[0;32m(kex) curve25519-sha256@libssh.org -- [info] available since OpenSSH 6.5, Dropbear SSH 2013.62[0m +[0;31m(kex) ecdh-sha2-nistp256 -- [fail] using weak elliptic curves[0m + `- [info] available since OpenSSH 5.7, Dropbear SSH 2013.62 +[0;31m(kex) ecdh-sha2-nistp384 -- [fail] using weak elliptic curves[0m + `- [info] available since OpenSSH 5.7, Dropbear SSH 2013.62 +[0;31m(kex) ecdh-sha2-nistp521 -- [fail] using weak elliptic curves[0m + `- [info] available since OpenSSH 5.7, Dropbear SSH 2013.62 +[0;32m(kex) diffie-hellman-group-exchange-sha256 (2048-bit) -- [info] available since OpenSSH 4.4[0m +[0;32m(kex) diffie-hellman-group16-sha512 -- [info] available since OpenSSH 7.3, Dropbear SSH 2016.73[0m +[0;32m(kex) diffie-hellman-group18-sha512 -- [info] available since OpenSSH 7.3[0m +[0;32m(kex) diffie-hellman-group14-sha256 -- [info] available since OpenSSH 7.3, Dropbear SSH 2016.73[0m +[0;33m(kex) diffie-hellman-group14-sha1 -- [warn] using weak hashing algorithm[0m + `- [info] available since OpenSSH 3.9, Dropbear SSH 0.53 + +[0;36m# host-key algorithms[0m +[0;32m(key) ssh-ed25519 -- [info] available since OpenSSH 6.5[0m +[0;32m(key) ssh-ed25519-cert-v01@openssh.com -- [info] available since OpenSSH 6.5[0m + +[0;36m# encryption algorithms (ciphers)[0m +[0;32m(enc) chacha20-poly1305@openssh.com -- [info] available since OpenSSH 6.5[0m + `- [info] default cipher since OpenSSH 6.9. +[0;32m(enc) aes128-ctr -- [info] available since OpenSSH 3.7, Dropbear SSH 0.52[0m +[0;32m(enc) aes192-ctr -- [info] available since OpenSSH 3.7[0m +[0;32m(enc) aes256-ctr -- [info] available since OpenSSH 3.7, Dropbear SSH 0.52[0m +[0;32m(enc) aes128-gcm@openssh.com -- [info] available since OpenSSH 6.2[0m +[0;32m(enc) aes256-gcm@openssh.com -- [info] available since OpenSSH 6.2[0m + +[0;36m# message authentication code algorithms[0m +[0;33m(mac) umac-64-etm@openssh.com -- [warn] using small 64-bit tag size[0m + `- [info] available since OpenSSH 6.2 +[0;32m(mac) umac-128-etm@openssh.com -- [info] available since OpenSSH 6.2[0m +[0;32m(mac) hmac-sha2-256-etm@openssh.com -- [info] available since OpenSSH 6.2[0m +[0;32m(mac) hmac-sha2-512-etm@openssh.com -- [info] available since OpenSSH 6.2[0m +[0;33m(mac) hmac-sha1-etm@openssh.com -- [warn] using weak hashing algorithm[0m + `- [info] available since OpenSSH 6.2 +[0;33m(mac) umac-64@openssh.com -- [warn] using encrypt-and-MAC mode[0m +[0;33m `- [warn] using small 64-bit tag size[0m + `- [info] available since OpenSSH 4.7 +[0;33m(mac) umac-128@openssh.com -- [warn] using encrypt-and-MAC mode[0m + `- [info] available since OpenSSH 6.2 +[0;33m(mac) hmac-sha2-256 -- [warn] using encrypt-and-MAC mode[0m + `- [info] available since OpenSSH 5.9, Dropbear SSH 2013.56 +[0;33m(mac) hmac-sha2-512 -- [warn] using encrypt-and-MAC mode[0m + `- [info] available since OpenSSH 5.9, Dropbear SSH 2013.56 +[0;33m(mac) hmac-sha1 -- [warn] using encrypt-and-MAC mode[0m +[0;33m `- [warn] using weak hashing algorithm[0m + `- [info] available since OpenSSH 2.1.0, Dropbear SSH 0.28 + +[0;36m# fingerprints[0m +[0;32m(fin) ssh-ed25519: SHA256:UrnXIVH+7dlw8UqYocl48yUEcKrthGDQG2CPCgp7MxU[0m + +[0;36m# algorithm recommendations (for OpenSSH 8.0)[0m +[0;31m(rec) -ecdh-sha2-nistp256 -- kex algorithm to remove [0m +[0;31m(rec) -ecdh-sha2-nistp384 -- kex algorithm to remove [0m +[0;31m(rec) -ecdh-sha2-nistp521 -- kex algorithm to remove [0m +[0;32m(rec) +rsa-sha2-256 -- key algorithm to append [0m +[0;32m(rec) +rsa-sha2-512 -- key algorithm to append [0m +[0;33m(rec) -diffie-hellman-group14-sha1 -- kex algorithm to remove [0m +[0;33m(rec) -hmac-sha1 -- mac algorithm to remove [0m +[0;33m(rec) -hmac-sha1-etm@openssh.com -- mac algorithm to remove [0m +[0;33m(rec) -hmac-sha2-256 -- mac algorithm to remove [0m +[0;33m(rec) -hmac-sha2-512 -- mac algorithm to remove [0m +[0;33m(rec) -umac-128@openssh.com -- mac algorithm to remove [0m +[0;33m(rec) -umac-64-etm@openssh.com -- mac algorithm to remove [0m +[0;33m(rec) -umac-64@openssh.com -- mac algorithm to remove [0m + +[0;36m# additional info[0m +[0;33m(nfo) For hardening guides on common OSes, please see: <https://www.ssh-audit.com/hardening_guides.html>[0m + diff --git a/test/docker/expected_results/openssh_8.0p1_test3.json b/test/docker/expected_results/openssh_8.0p1_test3.json new file mode 100644 index 0000000..5728136 --- /dev/null +++ b/test/docker/expected_results/openssh_8.0p1_test3.json @@ -0,0 +1 @@ +{"banner": {"comments": null, "protocol": [2, 0], "raw": "SSH-2.0-OpenSSH_8.0", "software": "OpenSSH_8.0"}, "compression": ["none", "zlib@openssh.com"], "enc": ["chacha20-poly1305@openssh.com", "aes256-gcm@openssh.com", "aes128-gcm@openssh.com", "aes256-ctr", "aes192-ctr", "aes128-ctr"], "fingerprints": [{"hash": "UrnXIVH+7dlw8UqYocl48yUEcKrthGDQG2CPCgp7MxU", "hash_alg": "SHA256", "hostkey": "ssh-ed25519"}, {"hash": "1e:0c:7b:34:73:bf:52:41:b0:f9:d1:a9:ab:98:c7:c9", "hash_alg": "MD5", "hostkey": "ssh-ed25519"}], "kex": [{"algorithm": "curve25519-sha256"}, {"algorithm": "curve25519-sha256@libssh.org"}, {"algorithm": "diffie-hellman-group-exchange-sha256", "keysize": 2048}], "key": [{"algorithm": "ssh-ed25519"}], "mac": ["hmac-sha2-256-etm@openssh.com", "hmac-sha2-512-etm@openssh.com", "umac-128-etm@openssh.com"], "target": "localhost"} diff --git a/test/docker/expected_results/openssh_8.0p1_test3.txt b/test/docker/expected_results/openssh_8.0p1_test3.txt new file mode 100644 index 0000000..5b20c3f --- /dev/null +++ b/test/docker/expected_results/openssh_8.0p1_test3.txt @@ -0,0 +1,38 @@ +[0;36m# general[0m +[0;32m(gen) banner: SSH-2.0-OpenSSH_8.0[0m +[0;32m(gen) software: OpenSSH 8.0[0m +[0;32m(gen) compatibility: OpenSSH 7.4+, Dropbear SSH 2018.76+[0m +[0;32m(gen) compression: enabled (zlib@openssh.com)[0m + +[0;36m# key exchange algorithms[0m +[0;32m(kex) curve25519-sha256 -- [info] available since OpenSSH 7.4, Dropbear SSH 2018.76[0m +[0;32m(kex) curve25519-sha256@libssh.org -- [info] available since OpenSSH 6.5, Dropbear SSH 2013.62[0m +[0;32m(kex) diffie-hellman-group-exchange-sha256 (2048-bit) -- [info] available since OpenSSH 4.4[0m + +[0;36m# host-key algorithms[0m +[0;32m(key) ssh-ed25519 -- [info] available since OpenSSH 6.5[0m + +[0;36m# encryption algorithms (ciphers)[0m +[0;32m(enc) chacha20-poly1305@openssh.com -- [info] available since OpenSSH 6.5[0m + `- [info] default cipher since OpenSSH 6.9. +[0;32m(enc) aes256-gcm@openssh.com -- [info] available since OpenSSH 6.2[0m +[0;32m(enc) aes128-gcm@openssh.com -- [info] available since OpenSSH 6.2[0m +[0;32m(enc) aes256-ctr -- [info] available since OpenSSH 3.7, Dropbear SSH 0.52[0m +[0;32m(enc) aes192-ctr -- [info] available since OpenSSH 3.7[0m +[0;32m(enc) aes128-ctr -- [info] available since OpenSSH 3.7, Dropbear SSH 0.52[0m + +[0;36m# message authentication code algorithms[0m +[0;32m(mac) hmac-sha2-256-etm@openssh.com -- [info] available since OpenSSH 6.2[0m +[0;32m(mac) hmac-sha2-512-etm@openssh.com -- [info] available since OpenSSH 6.2[0m +[0;32m(mac) umac-128-etm@openssh.com -- [info] available since OpenSSH 6.2[0m + +[0;36m# fingerprints[0m +[0;32m(fin) ssh-ed25519: SHA256:UrnXIVH+7dlw8UqYocl48yUEcKrthGDQG2CPCgp7MxU[0m + +[0;36m# algorithm recommendations (for OpenSSH 8.0)[0m +[0;32m(rec) +diffie-hellman-group14-sha256 -- kex algorithm to append [0m +[0;32m(rec) +diffie-hellman-group16-sha512 -- kex algorithm to append [0m +[0;32m(rec) +diffie-hellman-group18-sha512 -- kex algorithm to append [0m +[0;32m(rec) +rsa-sha2-256 -- key algorithm to append [0m +[0;32m(rec) +rsa-sha2-512 -- key algorithm to append [0m + diff --git a/test/docker/expected_results/tinyssh_20190101_test1.json b/test/docker/expected_results/tinyssh_20190101_test1.json new file mode 100644 index 0000000..6bf8f24 --- /dev/null +++ b/test/docker/expected_results/tinyssh_20190101_test1.json @@ -0,0 +1 @@ +{"banner": {"comments": "", "protocol": [2, 0], "raw": "", "software": "tinyssh_noversion"}, "compression": ["none"], "enc": ["chacha20-poly1305@openssh.com"], "fingerprints": [{"hash": "89ocln1x7KNqnMgWffGoYtD70ksJ4FrH7BMJHa7SrwU", "hash_alg": "SHA256", "hostkey": "ssh-ed25519"}, {"hash": "dd:9c:6d:f9:b0:8c:af:fa:c2:65:81:5d:5d:56:f8:21", "hash_alg": "MD5", "hostkey": "ssh-ed25519"}], "kex": [{"algorithm": "curve25519-sha256"}, {"algorithm": "curve25519-sha256@libssh.org"}, {"algorithm": "sntrup4591761x25519-sha512@tinyssh.org"}], "key": [{"algorithm": "ssh-ed25519"}], "mac": ["hmac-sha2-256"], "target": "localhost"} diff --git a/test/docker/expected_results/tinyssh_20190101_test1.txt b/test/docker/expected_results/tinyssh_20190101_test1.txt new file mode 100644 index 0000000..9e833c6 --- /dev/null +++ b/test/docker/expected_results/tinyssh_20190101_test1.txt @@ -0,0 +1,25 @@ +[0;36m# general[0m +[0;32m(gen) software: TinySSH noversion[0m +[0;32m(gen) compatibility: OpenSSH 8.0-8.4, Dropbear SSH 2018.76+[0m +[0;32m(gen) compression: disabled[0m + +[0;36m# key exchange algorithms[0m +[0;32m(kex) curve25519-sha256 -- [info] available since OpenSSH 7.4, Dropbear SSH 2018.76[0m +[0;32m(kex) curve25519-sha256@libssh.org -- [info] available since OpenSSH 6.5, Dropbear SSH 2013.62[0m +[0;33m(kex) sntrup4591761x25519-sha512@tinyssh.org -- [warn] using experimental algorithm[0m + `- [info] available since OpenSSH 8.0 + +[0;36m# host-key algorithms[0m +[0;32m(key) ssh-ed25519 -- [info] available since OpenSSH 6.5[0m + +[0;36m# encryption algorithms (ciphers)[0m +[0;32m(enc) chacha20-poly1305@openssh.com -- [info] available since OpenSSH 6.5[0m + `- [info] default cipher since OpenSSH 6.9. + +[0;36m# message authentication code algorithms[0m +[0;33m(mac) hmac-sha2-256 -- [warn] using encrypt-and-MAC mode[0m + `- [info] available since OpenSSH 5.9, Dropbear SSH 2013.56 + +[0;36m# fingerprints[0m +[0;32m(fin) ssh-ed25519: SHA256:89ocln1x7KNqnMgWffGoYtD70ksJ4FrH7BMJHa7SrwU[0m + diff --git a/test/docker/host_ca_ed25519 b/test/docker/host_ca_ed25519 new file mode 100644 index 0000000..7b8c41b --- /dev/null +++ b/test/docker/host_ca_ed25519 @@ -0,0 +1,7 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW +QyNTUxOQAAACAbM9Wp3ZPcC8Ifhu6GjNDJaoMg7KxO0el2+r9J35TltQAAAKAa0zr8GtM6 +/AAAAAtzc2gtZWQyNTUxOQAAACAbM9Wp3ZPcC8Ifhu6GjNDJaoMg7KxO0el2+r9J35TltQ +AAAEC/j/BpfmgaZqNMTkJXO4cKZBr31N5z33IRFjh5m6IDDhsz1andk9wLwh+G7oaM0Mlq +gyDsrE7R6Xb6v0nflOW1AAAAHWpkb2dAbG9jYWxob3N0LndvbmRlcmxhbmQubG9s +-----END OPENSSH PRIVATE KEY----- diff --git a/test/docker/host_ca_ed25519.pub b/test/docker/host_ca_ed25519.pub new file mode 100644 index 0000000..01e745f --- /dev/null +++ b/test/docker/host_ca_ed25519.pub @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBsz1andk9wLwh+G7oaM0MlqgyDsrE7R6Xb6v0nflOW1 jdog@localhost.wonderland.lol diff --git a/test/docker/host_ca_rsa_1024 b/test/docker/host_ca_rsa_1024 new file mode 100644 index 0000000..337b777 --- /dev/null +++ b/test/docker/host_ca_rsa_1024 @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXgIBAAKBgQDnRlN3AFnUe2lFf5XG9UhXLr/9POruNTFbMt0zrjOUSjmAS7hS +6pDv5VEToT6DaR1EQUYaqSMpHYzZhuCK52vrydOm5XFbJ7712r9MyZQUhoVZx8Su +dBHzVDIVO3jcMMWIlrfWBMnUaUHEqpmy88Y7gKDa2TWxJg1+hg51KqHrUQIDAQAB +AoGBANALOUXRcP1tTtOP4+In/709dsONKyDBhPavGMFGsWtyIavBcbxU+bBzrq1j +3WJFCmi99xxAjjqMNInxhMgvSaoJtsiY0/FFxqRy6l/ZnRjI6hrVKR8whrPKVgBF +pvbjeQIn9txeCYA8kwl/Si762u7byq+qvupE53xMP94J02KBAkEA/Q4+Hn1Rjblw +VXynF+oXIq6iZy+8PW+Y/FIL8d31ehzfcssCMdFV6S3/wBoQkWby30oGC/xGmHGR +6ffXGilByQJBAOn3NMrBPXNkaPeQtgV3tk4s1dRDQYhbqGNz6tcgThyyPdhJCmCy +jgUEhLwAetsDI8/+3avWbo6/csOV+BvpYUkCQQDQyEp6L1z0+FV1QqY99dZmt/yn +89t0OLnZG/xc7osU1/OHq3TBE3y1KU2D+j1HKdAiZ9l7VAYOykzf46qmG/n5AkEA +2kWjfcjcIIw7lULvXZh6fuI7NwTr3V/Nb8MUA1EDLqhnJCG4SdAqyKmXf6Fe/HYo +cgKPIaIykIAxfCCsULXg6QJAOxB0CKYJlopVBdjGMlGqOEneWTmb1A2INQDE2Una +LkSd0Rr8OiEzDeemV7j3Ec4BH0HxGMnHDxMybZwoZRnRPw== +-----END RSA PRIVATE KEY----- diff --git a/test/docker/host_ca_rsa_1024.pub b/test/docker/host_ca_rsa_1024.pub new file mode 100644 index 0000000..6d861d6 --- /dev/null +++ b/test/docker/host_ca_rsa_1024.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDnRlN3AFnUe2lFf5XG9UhXLr/9POruNTFbMt0zrjOUSjmAS7hS6pDv5VEToT6DaR1EQUYaqSMpHYzZhuCK52vrydOm5XFbJ7712r9MyZQUhoVZx8SudBHzVDIVO3jcMMWIlrfWBMnUaUHEqpmy88Y7gKDa2TWxJg1+hg51KqHrUQ== jdog@localhost.wonderland.lol diff --git a/test/docker/host_ca_rsa_3072 b/test/docker/host_ca_rsa_3072 new file mode 100644 index 0000000..dd04653 --- /dev/null +++ b/test/docker/host_ca_rsa_3072 @@ -0,0 +1,39 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIG4wIBAAKCAYEAqxQEIbj8w0TrBY1fDO81curijQrdLOUr8Vl8XECWc5QGd1Lk +AG80NgdcCBPvjWxZSmYrKeqA78GUdN+KgycE0ztpxYSXKHZMaIM5Xe94BB+BocH9 +1vd/2iBzGeed1nV/zfAdq2AEHQj1TpII+a+z25yxv2PuwVTTwwo9I/6JgNq3evH4 +Hbwgr3SRfEEYZQ+YL8cOpBuNg1YZOR0k1yk23ZqAd92JybxZ4iCtOt7rcj2sFHzN +u1U544wWBwIL5yZZKTgBhY4dqfT2Ep7IzR5HdsdrvQV9qC92GM1zDE+U3AwrVKjH +s0YZq3jzcq/yvFDCcMMRz4/0pGFFU26oWma+n3vbAxKJoL+rhG8QM9+l2qFlLGsn +M0kUXAJXsPKbygpaP8Z3U4eKgTuJ2GuS9eLIFnB7mrwD75V6GgN9q5mY89DfkVSk +HaoqpY8pPdRkz9QAmMEuLtHmv29CVOpfX5v/rsm7wASAZqtUlmFu4rFGBLwvZbUl +Wu02HmgBT47g6EIfAgMBAAECggGAKVCdKtO03yd+pomcodAHFWiaK7uq7FOwCAo3 +WUQT0Xe3FAwFmgFBF6cxV5YQ7RN0gN4poGbMmpoiUxNFLSU4KhcYFSZPJutiyn6e +VQwm7L/7G2hw+AAvdSsPAPuJh6g6pC5Py/pVI/ns2/uyhTIkem3eEz18BF6LAXgw +icfHx0GKu/tBk1TCg/zfwaUq0gUxGKC27XTl+QjK8JsUMY33fQ755Xiv9PMytcR0 +cVoyfBVewFffi1UqtMQ48ZpR65G743RxrP4/wcwsfD7n5LJLdyxQkh3gIMTJ8dd/ +R5V4FlueorRgjTbLTjGDxNrCAJ+locezhEEPXsPh2q0KiIXGyz2AMxaOqFmhU8oK +aVVt8pWJ+YsrKIgc/A3s18ezO8uO5ZdtjQ+CWguduUGY7YgWezGLO1LPxhJC4d7b +Q/xpeKveTRlcScAqOUzKgSuEhcvPgj8paUcRUoiXm4qiJBY5sXJks+YGp8BGksH0 +O94no+Ns2G58MlL+RyXk3JWrc6zRAoHBANdPplY2sIuIiiEBu95f1Qar1nCBHhB2 +i+HpnsUOdSlbxwMxoF8ffeN9N+DQqaqPu1RhFa5xbB2EUSujvOnL7b/RWqe1X9Po +UIt5UjXctNP/HYcQDyjXY+rV5SZhHDyv6TBYurNZlvlBivliDz82THPRtqVxed3B +w2MeaSkKAQ8rA7PE+0j3TG+YtIij0mHOhNPJgEZ/XZ9MIQOGMycRJhwOlclBI5NP +Ak6p30ArnU2fX4qMkU3i+wqUfXS1hhDihwKBwQDLaHWPIWPVbWdcCbYQTcUmFC3i +xkxd0UuLcfS9csk61nvdFj7m8tMExX+3fIo/fHEtzDd98Alc1i6/f6ePl0CX6NDu +QIWLryI1QQRQidHCdw0wQ3N3VD4ZXJHDeqBxogVAkA7A/1QeXwcXE/Xj2ZgyDwhL +3+myjmvWtw9zJsXL0F3tpPzn+Mrf0KRkWOaluOw7hMMjVjrgu6g24HMWbHHVLRTx +dlAI7tgxCAPe2SEi+1mzaVUZ8cfgqYqC3X66UakCgcEAopxtK7+yJi/A4pzEnnYS +FS/CjMV3R0fA7aXbW0hIBCxkaW0Zib3m/eCcSxZMjZxwBpIsJctTtBcylprbGlgB +/1TF+tNoxEo4Sp4eEL/XciTC0Da4vEewFrPklM/S26KfovvgRYPsGeP+aco9aahA +pVhFcT36pBiq0DkvgucjValO6n5iqgDboYzbDDdttKCcgLc2Qgf/VUfRxy+bgm3Z +MmdxiMXBcIfDXlW9XmGSNAWhyqnPM9uxbZQoC/Tsg+QRAoHANHMcFSsz9f2+8DGk +27FiC76aUmZ1nJ9yTmO1CwDFOMHDsK+iyqSEmy9eDm8zqsko2flVuciicWjdJw4A +o/sJceJbtYO3q9weAwNf3HCdQPq30OEjrfpwBNQk1fYR1xtDJXHADC4Kf8ZbKq0/ +81/Rad8McZwsQ5mL3xLXDgdKa5KwFa48dIhnr6y6JxHxb3wule5W7w62Ierhpjzc +EEUoWSLFyrmKS7Ni1cnOTbFJZR7Q831Or2Dz/E9bYwFAQ0T5AoHAM4/zU+8rsbdD +FvvhWsj7Ivfh6pxx1Tl1Wccaauea9AJayHht0FOzkycpJrH1E+6F5MzhkFFU1SUY +60NZxzSZgbU0HBrJRcRFyo510iMcnctdTdyh8p7nweGoD0oqXzf6cHqrUep8Y8rQ +gkSVhPE31+NGlPbwz+NOflcaaAWYiDC6wjVt1asaZq292SJD4DF1fAUkbQ2hxgyQ ++G/6y5ovrcGnh7q63RLhW1TRf8dD2D2Av9UgXDmWZAZ5n838FS+X +-----END RSA PRIVATE KEY----- diff --git a/test/docker/host_ca_rsa_3072.pub b/test/docker/host_ca_rsa_3072.pub new file mode 100644 index 0000000..b728ed7 --- /dev/null +++ b/test/docker/host_ca_rsa_3072.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCrFAQhuPzDROsFjV8M7zVy6uKNCt0s5SvxWXxcQJZzlAZ3UuQAbzQ2B1wIE++NbFlKZisp6oDvwZR034qDJwTTO2nFhJcodkxogzld73gEH4Ghwf3W93/aIHMZ553WdX/N8B2rYAQdCPVOkgj5r7PbnLG/Y+7BVNPDCj0j/omA2rd68fgdvCCvdJF8QRhlD5gvxw6kG42DVhk5HSTXKTbdmoB33YnJvFniIK063utyPawUfM27VTnjjBYHAgvnJlkpOAGFjh2p9PYSnsjNHkd2x2u9BX2oL3YYzXMMT5TcDCtUqMezRhmrePNyr/K8UMJwwxHPj/SkYUVTbqhaZr6fe9sDEomgv6uEbxAz36XaoWUsayczSRRcAlew8pvKClo/xndTh4qBO4nYa5L14sgWcHuavAPvlXoaA32rmZjz0N+RVKQdqiqljyk91GTP1ACYwS4u0ea/b0JU6l9fm/+uybvABIBmq1SWYW7isUYEvC9ltSVa7TYeaAFPjuDoQh8= jdog@localhost.wonderland.lol diff --git a/test/docker/moduli_1024 b/test/docker/moduli_1024 new file mode 100644 index 0000000..bd81dae --- /dev/null +++ b/test/docker/moduli_1024 @@ -0,0 +1,44 @@ +20190821035337 2 6 100 1023 2 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC08BE313B +20190821035338 2 6 100 1023 2 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC08C0B443 +20190821035338 2 6 100 1023 2 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC08D1AF8B +20190821035338 2 6 100 1023 2 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC08E76DDB +20190821035338 2 6 100 1023 2 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC08E8F5D3 +20190821035338 2 6 100 1023 2 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC08EE3F1B +20190821035338 2 6 100 1023 5 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC08F28387 +20190821035339 2 6 100 1023 5 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC08F69A57 +20190821035339 2 6 100 1023 5 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC0903B157 +20190821035339 2 6 100 1023 2 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC0905C973 +20190821035339 2 6 100 1023 2 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC0909BCD3 +20190821035339 2 6 100 1023 2 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC090F4A2B +20190821035340 2 6 100 1023 2 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC0933BC13 +20190821035340 2 6 100 1023 5 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC09395757 +20190821035340 2 6 100 1023 5 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC093F40D7 +20190821035340 2 6 100 1023 5 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC09478D4F +20190821035340 2 6 100 1023 5 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC0953A4D7 +20190821035340 2 6 100 1023 2 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC095B5C7B +20190821035341 2 6 100 1023 2 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC09696573 +20190821035341 2 6 100 1023 2 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC096BA243 +20190821035341 2 6 100 1023 2 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC096F3903 +20190821035341 2 6 100 1023 2 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC09850E4B +20190821035341 2 6 100 1023 2 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC098A1C23 +20190821035341 2 6 100 1023 5 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC098E08E7 +20190821035342 2 6 100 1023 5 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC09A4FF7F +20190821035342 2 6 100 1023 5 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC09AE4707 +20190821035342 2 6 100 1023 2 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC09B4CE73 +20190821035342 2 6 100 1023 5 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC09C60C6F +20190821035342 2 6 100 1023 5 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC09D2588F +20190821035343 2 6 100 1023 5 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC0A025067 +20190821035343 2 6 100 1023 2 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC0A0E38EB +20190821035343 2 6 100 1023 2 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC0A213923 +20190821035344 2 6 100 1023 5 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC0A390CA7 +20190821035344 2 6 100 1023 2 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC0A3C7ADB +20190821035344 2 6 100 1023 5 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC0A44D497 +20190821035344 2 6 100 1023 2 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC0A479B13 +20190821035345 2 6 100 1023 5 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC0A5EF01F +20190821035345 2 6 100 1023 2 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC0A615D43 +20190821035345 2 6 100 1023 2 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC0A6BEADB +20190821035345 2 6 100 1023 5 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC0A86309F +20190821035345 2 6 100 1023 5 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC0A991E8F +20190821035346 2 6 100 1023 2 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC0AA32C53 +20190821035346 2 6 100 1023 2 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC0AA9FAAB +20190821035346 2 6 100 1023 2 F0B5E9E385A451D4F46BD2E354B5FCAAC21CA960E5D3D11F877DD50541ED125161E4A5055D528D67E525115BBFAB0B2A4AB8CF5BA98A8BBA41803ED5D4CF766E9ECD39A8D8D914B6F346E0EB2BA6936082751676DCE5C4817EFC7A8105C2A094B22C25245BE13CA4085F2985D3B7A2636FF4018A7E4EA9840BF5FFBC0AAC42BB diff --git a/test/docker/policies/policy_test1.txt b/test/docker/policies/policy_test1.txt new file mode 100644 index 0000000..11d8e5c --- /dev/null +++ b/test/docker/policies/policy_test1.txt @@ -0,0 +1,10 @@ +# +# Docker policy: test1 +# + +name = "Docker policy: test1" +version = 1 +host keys = ssh-rsa, ssh-dss +key exchanges = diffie-hellman-group-exchange-sha256, diffie-hellman-group-exchange-sha1, diffie-hellman-group14-sha1, diffie-hellman-group1-sha1 +ciphers = aes128-ctr, aes192-ctr, aes256-ctr, arcfour256, arcfour128, aes128-cbc, 3des-cbc, blowfish-cbc, cast128-cbc, aes192-cbc, aes256-cbc, arcfour, rijndael-cbc@lysator.liu.se +macs = hmac-md5, hmac-sha1, umac-64@openssh.com, hmac-ripemd160, hmac-ripemd160@openssh.com, hmac-sha1-96, hmac-md5-96 diff --git a/test/docker/policies/policy_test10.txt b/test/docker/policies/policy_test10.txt new file mode 100644 index 0000000..82c821e --- /dev/null +++ b/test/docker/policies/policy_test10.txt @@ -0,0 +1,39 @@ +# +# Docker policy: test10 +# + +# The name of this policy (displayed in the output during scans). Must be in quotes. +name = "Docker poliicy: test10" + +# The version of this policy (displayed in the output during scans). Not parsed, and may be any value, including strings. +version = 1 + +# The banner that must match exactly. Commented out to ignore banners, since minor variability in the banner is sometimes normal. +# banner = "SSH-2.0-OpenSSH_5.6" + +# The header that must match exactly. Commented out to ignore headers, since variability in the header is sometimes normal. +# header = "[]" + +# The compression options that must match exactly (order matters). Commented out to ignore by default. +# compressions = none, zlib@openssh.com + +# RSA host key sizes. +hostkey_size_rsa-sha2-256 = 3072 +hostkey_size_rsa-sha2-512 = 3072 +hostkey_size_ssh-rsa = 3072 +hostkey_size_ssh-rsa-cert-v01@openssh.com = 4096 + +# RSA CA key sizes. +cakey_size_ssh-rsa-cert-v01@openssh.com = 4096 + +# The host key types that must match exactly (order matters). +host keys = ssh-rsa, ssh-rsa-cert-v01@openssh.com + +# The key exchange algorithms that must match exactly (order matters). +key exchanges = diffie-hellman-group-exchange-sha256, diffie-hellman-group-exchange-sha1, diffie-hellman-group14-sha1, diffie-hellman-group1-sha1 + +# The ciphers that must match exactly (order matters). +ciphers = aes128-ctr, aes192-ctr, aes256-ctr, arcfour256, arcfour128, aes128-cbc, 3des-cbc, blowfish-cbc, cast128-cbc, aes192-cbc, aes256-cbc, arcfour, rijndael-cbc@lysator.liu.se + +# The MACs that must match exactly (order matters). +macs = hmac-md5, hmac-sha1, umac-64@openssh.com, hmac-ripemd160, hmac-ripemd160@openssh.com, hmac-sha1-96, hmac-md5-96 diff --git a/test/docker/policies/policy_test11.txt b/test/docker/policies/policy_test11.txt new file mode 100644 index 0000000..d0fa4ae --- /dev/null +++ b/test/docker/policies/policy_test11.txt @@ -0,0 +1,35 @@ +# +# Docker policy: test11 +# + +# The name of this policy (displayed in the output during scans). Must be in quotes. +name = "Docker policy: test11" + +# The version of this policy (displayed in the output during scans). Not parsed, and may be any value, including strings. +version = 1 + +# The banner that must match exactly. Commented out to ignore banners, since minor variability in the banner is sometimes normal. +# banner = "SSH-2.0-OpenSSH_8.0" + +# The header that must match exactly. Commented out to ignore headers, since variability in the header is sometimes normal. +# header = "[]" + +# The compression options that must match exactly (order matters). Commented out to ignore by default. +# compressions = none, zlib@openssh.com + +# RSA host key sizes. +hostkey_size_rsa-sha2-256 = 3072 +hostkey_size_rsa-sha2-512 = 3072 +hostkey_size_ssh-rsa = 3072 + +# The host key types that must match exactly (order matters). +host keys = rsa-sha2-512, rsa-sha2-256, ssh-rsa, ecdsa-sha2-nistp256, ssh-ed25519 + +# The key exchange algorithms that must match exactly (order matters). +key exchanges = curve25519-sha256, curve25519-sha256@libssh.org, ecdh-sha2-nistp256, ecdh-sha2-nistp384, ecdh-sha2-nistp521, diffie-hellman-group-exchange-sha256, diffie-hellman-group16-sha512, diffie-hellman-group18-sha512, diffie-hellman-group14-sha256, diffie-hellman-group14-sha1 + +# The ciphers that must match exactly (order matters). +ciphers = chacha20-poly1305@openssh.com, aes128-ctr, aes192-ctr, aes256-ctr, aes128-gcm@openssh.com, aes256-gcm@openssh.com + +# The MACs that must match exactly (order matters). +macs = 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 diff --git a/test/docker/policies/policy_test12.txt b/test/docker/policies/policy_test12.txt new file mode 100644 index 0000000..0b8a30b --- /dev/null +++ b/test/docker/policies/policy_test12.txt @@ -0,0 +1,35 @@ +# +# Docker policy: test12 +# + +# The name of this policy (displayed in the output during scans). Must be in quotes. +name = "Docker policy: test12" + +# The version of this policy (displayed in the output during scans). Not parsed, and may be any value, including strings. +version = 1 + +# The banner that must match exactly. Commented out to ignore banners, since minor variability in the banner is sometimes normal. +# banner = "SSH-2.0-OpenSSH_8.0" + +# The header that must match exactly. Commented out to ignore headers, since variability in the header is sometimes normal. +# header = "[]" + +# The compression options that must match exactly (order matters). Commented out to ignore by default. +# compressions = none, zlib@openssh.com + +# RSA host key sizes. +hostkey_size_rsa-sha2-256 = 4096 +hostkey_size_rsa-sha2-512 = 4096 +hostkey_size_ssh-rsa = 4096 + +# The host key types that must match exactly (order matters). +host keys = rsa-sha2-512, rsa-sha2-256, ssh-rsa, ecdsa-sha2-nistp256, ssh-ed25519 + +# The key exchange algorithms that must match exactly (order matters). +key exchanges = curve25519-sha256, curve25519-sha256@libssh.org, ecdh-sha2-nistp256, ecdh-sha2-nistp384, ecdh-sha2-nistp521, diffie-hellman-group-exchange-sha256, diffie-hellman-group16-sha512, diffie-hellman-group18-sha512, diffie-hellman-group14-sha256, diffie-hellman-group14-sha1 + +# The ciphers that must match exactly (order matters). +ciphers = chacha20-poly1305@openssh.com, aes128-ctr, aes192-ctr, aes256-ctr, aes128-gcm@openssh.com, aes256-gcm@openssh.com + +# The MACs that must match exactly (order matters). +macs = 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 diff --git a/test/docker/policies/policy_test13.txt b/test/docker/policies/policy_test13.txt new file mode 100644 index 0000000..5e9bbd4 --- /dev/null +++ b/test/docker/policies/policy_test13.txt @@ -0,0 +1,38 @@ +# +# Docker policy: test13 +# + +# The name of this policy (displayed in the output during scans). Must be in quotes. +name = "Docker policy: test13" + +# The version of this policy (displayed in the output during scans). Not parsed, and may be any value, including strings. +version = 1 + +# The banner that must match exactly. Commented out to ignore banners, since minor variability in the banner is sometimes normal. +# banner = "SSH-2.0-OpenSSH_8.0" + +# The header that must match exactly. Commented out to ignore headers, since variability in the header is sometimes normal. +# header = "[]" + +# The compression options that must match exactly (order matters). Commented out to ignore by default. +# compressions = none, zlib@openssh.com + +# RSA host key sizes. +hostkey_size_rsa-sha2-256 = 3072 +hostkey_size_rsa-sha2-512 = 3072 +hostkey_size_ssh-rsa = 3072 + +# Group exchange DH modulus sizes. +dh_modulus_size_diffie-hellman-group-exchange-sha256 = 2048 + +# The host key types that must match exactly (order matters). +host keys = rsa-sha2-512, rsa-sha2-256, ssh-rsa, ecdsa-sha2-nistp256, ssh-ed25519 + +# The key exchange algorithms that must match exactly (order matters). +key exchanges = curve25519-sha256, curve25519-sha256@libssh.org, ecdh-sha2-nistp256, ecdh-sha2-nistp384, ecdh-sha2-nistp521, diffie-hellman-group-exchange-sha256, diffie-hellman-group16-sha512, diffie-hellman-group18-sha512, diffie-hellman-group14-sha256, diffie-hellman-group14-sha1 + +# The ciphers that must match exactly (order matters). +ciphers = chacha20-poly1305@openssh.com, aes128-ctr, aes192-ctr, aes256-ctr, aes128-gcm@openssh.com, aes256-gcm@openssh.com + +# The MACs that must match exactly (order matters). +macs = 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 diff --git a/test/docker/policies/policy_test14.txt b/test/docker/policies/policy_test14.txt new file mode 100644 index 0000000..ce1fec8 --- /dev/null +++ b/test/docker/policies/policy_test14.txt @@ -0,0 +1,38 @@ +# +# Docker policy: test14 +# + +# The name of this policy (displayed in the output during scans). Must be in quotes. +name = "Docker policy: test14" + +# The version of this policy (displayed in the output during scans). Not parsed, and may be any value, including strings. +version = 1 + +# The banner that must match exactly. Commented out to ignore banners, since minor variability in the banner is sometimes normal. +# banner = "SSH-2.0-OpenSSH_8.0" + +# The header that must match exactly. Commented out to ignore headers, since variability in the header is sometimes normal. +# header = "[]" + +# The compression options that must match exactly (order matters). Commented out to ignore by default. +# compressions = none, zlib@openssh.com + +# RSA host key sizes. +hostkey_size_rsa-sha2-256 = 3072 +hostkey_size_rsa-sha2-512 = 3072 +hostkey_size_ssh-rsa = 3072 + +# Group exchange DH modulus sizes. +dh_modulus_size_diffie-hellman-group-exchange-sha256 = 4096 + +# The host key types that must match exactly (order matters). +host keys = rsa-sha2-512, rsa-sha2-256, ssh-rsa, ecdsa-sha2-nistp256, ssh-ed25519 + +# The key exchange algorithms that must match exactly (order matters). +key exchanges = curve25519-sha256, curve25519-sha256@libssh.org, ecdh-sha2-nistp256, ecdh-sha2-nistp384, ecdh-sha2-nistp521, diffie-hellman-group-exchange-sha256, diffie-hellman-group16-sha512, diffie-hellman-group18-sha512, diffie-hellman-group14-sha256, diffie-hellman-group14-sha1 + +# The ciphers that must match exactly (order matters). +ciphers = chacha20-poly1305@openssh.com, aes128-ctr, aes192-ctr, aes256-ctr, aes128-gcm@openssh.com, aes256-gcm@openssh.com + +# The MACs that must match exactly (order matters). +macs = 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 diff --git a/test/docker/policies/policy_test2.txt b/test/docker/policies/policy_test2.txt new file mode 100644 index 0000000..2b7821c --- /dev/null +++ b/test/docker/policies/policy_test2.txt @@ -0,0 +1,10 @@ +# +# Docker policy: test2 +# + +name = "Docker policy: test2" +version = 1 +host keys = ssh-rsa, ssh-dss +key exchanges = kex_alg1, kex_alg2 +ciphers = aes128-ctr, aes192-ctr, aes256-ctr, arcfour256, arcfour128, aes128-cbc, 3des-cbc, blowfish-cbc, cast128-cbc, aes192-cbc, aes256-cbc, arcfour, rijndael-cbc@lysator.liu.se +macs = hmac-md5, hmac-sha1, umac-64@openssh.com, hmac-ripemd160, hmac-ripemd160@openssh.com, hmac-sha1-96, hmac-md5-96 diff --git a/test/docker/policies/policy_test3.txt b/test/docker/policies/policy_test3.txt new file mode 100644 index 0000000..f4ff3a0 --- /dev/null +++ b/test/docker/policies/policy_test3.txt @@ -0,0 +1,10 @@ +# +# Docker policy: test3 +# + +name = "Docker policy: test3" +version = 1 +host keys = ssh-rsa, ssh-dss, key_alg1 +key exchanges = diffie-hellman-group-exchange-sha256, diffie-hellman-group-exchange-sha1, diffie-hellman-group14-sha1, diffie-hellman-group1-sha1 +ciphers = aes128-ctr, aes192-ctr, aes256-ctr, arcfour256, arcfour128, aes128-cbc, 3des-cbc, blowfish-cbc, cast128-cbc, aes192-cbc, aes256-cbc, arcfour, rijndael-cbc@lysator.liu.se +macs = hmac-md5, hmac-sha1, umac-64@openssh.com, hmac-ripemd160, hmac-ripemd160@openssh.com, hmac-sha1-96, hmac-md5-96 diff --git a/test/docker/policies/policy_test4.txt b/test/docker/policies/policy_test4.txt new file mode 100644 index 0000000..500d96f --- /dev/null +++ b/test/docker/policies/policy_test4.txt @@ -0,0 +1,10 @@ +# +# Docker policy: test4 +# + +name = "Docker policy: test4" +version = 1 +host keys = ssh-rsa, ssh-dss +key exchanges = diffie-hellman-group-exchange-sha256, diffie-hellman-group-exchange-sha1, diffie-hellman-group14-sha1, diffie-hellman-group1-sha1 +ciphers = cipher_alg1, cipher_alg2 +macs = hmac-md5, hmac-sha1, umac-64@openssh.com, hmac-ripemd160, hmac-ripemd160@openssh.com, hmac-sha1-96, hmac-md5-96 diff --git a/test/docker/policies/policy_test5.txt b/test/docker/policies/policy_test5.txt new file mode 100644 index 0000000..6285814 --- /dev/null +++ b/test/docker/policies/policy_test5.txt @@ -0,0 +1,10 @@ +# +# Docker policy: test5 +# + +name = "Docker policy: test5" +version = 1 +host keys = ssh-rsa, ssh-dss +key exchanges = diffie-hellman-group-exchange-sha256, diffie-hellman-group-exchange-sha1, diffie-hellman-group14-sha1, diffie-hellman-group1-sha1 +ciphers = aes128-ctr, aes192-ctr, aes256-ctr, arcfour256, arcfour128, aes128-cbc, 3des-cbc, blowfish-cbc, cast128-cbc, aes192-cbc, aes256-cbc, arcfour, rijndael-cbc@lysator.liu.se +macs = hmac-md5, hmac-sha1, umac-64@openssh.com, hmac-ripemd160, hmac-ripemd160@openssh.com, hmac_alg1, hmac-md5-96 diff --git a/test/docker/policies/policy_test6.txt b/test/docker/policies/policy_test6.txt new file mode 100644 index 0000000..0a4aacb --- /dev/null +++ b/test/docker/policies/policy_test6.txt @@ -0,0 +1,12 @@ +# +# Docker policy: test6 +# + +name = "Docker policy: test6" +version = 1 +banner = "SSH-2.0-OpenSSH_8.0" +compressions = none, zlib@openssh.com +host keys = rsa-sha2-512, rsa-sha2-256, ssh-rsa, ecdsa-sha2-nistp256, ssh-ed25519 +key exchanges = curve25519-sha256, curve25519-sha256@libssh.org, ecdh-sha2-nistp256, ecdh-sha2-nistp384, ecdh-sha2-nistp521, diffie-hellman-group-exchange-sha256, diffie-hellman-group16-sha512, diffie-hellman-group18-sha512, diffie-hellman-group14-sha256, diffie-hellman-group14-sha1 +ciphers = chacha20-poly1305@openssh.com, aes128-ctr, aes192-ctr, aes256-ctr, aes128-gcm@openssh.com, aes256-gcm@openssh.com +macs = 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 diff --git a/test/docker/policies/policy_test7.txt b/test/docker/policies/policy_test7.txt new file mode 100644 index 0000000..05cd27f --- /dev/null +++ b/test/docker/policies/policy_test7.txt @@ -0,0 +1,39 @@ +# +# Docker policy: test7 +# + +# The name of this policy (displayed in the output during scans). Must be in quotes. +name = "Docker poliicy: test7" + +# The version of this policy (displayed in the output during scans). Not parsed, and may be any value, including strings. +version = 1 + +# The banner that must match exactly. Commented out to ignore banners, since minor variability in the banner is sometimes normal. +# banner = "SSH-2.0-OpenSSH_5.6" + +# The header that must match exactly. Commented out to ignore headers, since variability in the header is sometimes normal. +# header = "[]" + +# The compression options that must match exactly (order matters). Commented out to ignore by default. +# compressions = none, zlib@openssh.com + +# RSA host key sizes. +hostkey_size_rsa-sha2-256 = 3072 +hostkey_size_rsa-sha2-512 = 3072 +hostkey_size_ssh-rsa = 3072 +hostkey_size_ssh-rsa-cert-v01@openssh.com = 3072 + +# RSA CA key sizes. +cakey_size_ssh-rsa-cert-v01@openssh.com = 1024 + +# The host key types that must match exactly (order matters). +host keys = ssh-rsa, ssh-rsa-cert-v01@openssh.com + +# The key exchange algorithms that must match exactly (order matters). +key exchanges = diffie-hellman-group-exchange-sha256, diffie-hellman-group-exchange-sha1, diffie-hellman-group14-sha1, diffie-hellman-group1-sha1 + +# The ciphers that must match exactly (order matters). +ciphers = aes128-ctr, aes192-ctr, aes256-ctr, arcfour256, arcfour128, aes128-cbc, 3des-cbc, blowfish-cbc, cast128-cbc, aes192-cbc, aes256-cbc, arcfour, rijndael-cbc@lysator.liu.se + +# The MACs that must match exactly (order matters). +macs = hmac-md5, hmac-sha1, umac-64@openssh.com, hmac-ripemd160, hmac-ripemd160@openssh.com, hmac-sha1-96, hmac-md5-96 diff --git a/test/docker/policies/policy_test8.txt b/test/docker/policies/policy_test8.txt new file mode 100644 index 0000000..6268585 --- /dev/null +++ b/test/docker/policies/policy_test8.txt @@ -0,0 +1,39 @@ +# +# Docker policy: test8 +# + +# The name of this policy (displayed in the output during scans). Must be in quotes. +name = "Docker poliicy: test8" + +# The version of this policy (displayed in the output during scans). Not parsed, and may be any value, including strings. +version = 1 + +# The banner that must match exactly. Commented out to ignore banners, since minor variability in the banner is sometimes normal. +# banner = "SSH-2.0-OpenSSH_5.6" + +# The header that must match exactly. Commented out to ignore headers, since variability in the header is sometimes normal. +# header = "[]" + +# The compression options that must match exactly (order matters). Commented out to ignore by default. +# compressions = none, zlib@openssh.com + +# RSA host key sizes. +hostkey_size_rsa-sha2-256 = 3072 +hostkey_size_rsa-sha2-512 = 3072 +hostkey_size_ssh-rsa = 3072 +hostkey_size_ssh-rsa-cert-v01@openssh.com = 3072 + +# RSA CA key sizes. +cakey_size_ssh-rsa-cert-v01@openssh.com = 2048 + +# The host key types that must match exactly (order matters). +host keys = ssh-rsa, ssh-rsa-cert-v01@openssh.com + +# The key exchange algorithms that must match exactly (order matters). +key exchanges = diffie-hellman-group-exchange-sha256, diffie-hellman-group-exchange-sha1, diffie-hellman-group14-sha1, diffie-hellman-group1-sha1 + +# The ciphers that must match exactly (order matters). +ciphers = aes128-ctr, aes192-ctr, aes256-ctr, arcfour256, arcfour128, aes128-cbc, 3des-cbc, blowfish-cbc, cast128-cbc, aes192-cbc, aes256-cbc, arcfour, rijndael-cbc@lysator.liu.se + +# The MACs that must match exactly (order matters). +macs = hmac-md5, hmac-sha1, umac-64@openssh.com, hmac-ripemd160, hmac-ripemd160@openssh.com, hmac-sha1-96, hmac-md5-96 diff --git a/test/docker/policies/policy_test9.txt b/test/docker/policies/policy_test9.txt new file mode 100644 index 0000000..63652ce --- /dev/null +++ b/test/docker/policies/policy_test9.txt @@ -0,0 +1,39 @@ +# +# Docker policy: test9 +# + +# The name of this policy (displayed in the output during scans). Must be in quotes. +name = "Docker poliicy: test9" + +# The version of this policy (displayed in the output during scans). Not parsed, and may be any value, including strings. +version = 1 + +# The banner that must match exactly. Commented out to ignore banners, since minor variability in the banner is sometimes normal. +# banner = "SSH-2.0-OpenSSH_5.6" + +# The header that must match exactly. Commented out to ignore headers, since variability in the header is sometimes normal. +# header = "[]" + +# The compression options that must match exactly (order matters). Commented out to ignore by default. +# compressions = none, zlib@openssh.com + +# RSA host key sizes. +hostkey_size_rsa-sha2-256 = 3072 +hostkey_size_rsa-sha2-512 = 3072 +hostkey_size_ssh-rsa = 3072 +hostkey_size_ssh-rsa-cert-v01@openssh.com = 4096 + +# RSA CA key sizes. +cakey_size_ssh-rsa-cert-v01@openssh.com = 1024 + +# The host key types that must match exactly (order matters). +host keys = ssh-rsa, ssh-rsa-cert-v01@openssh.com + +# The key exchange algorithms that must match exactly (order matters). +key exchanges = diffie-hellman-group-exchange-sha256, diffie-hellman-group-exchange-sha1, diffie-hellman-group14-sha1, diffie-hellman-group1-sha1 + +# The ciphers that must match exactly (order matters). +ciphers = aes128-ctr, aes192-ctr, aes256-ctr, arcfour256, arcfour128, aes128-cbc, 3des-cbc, blowfish-cbc, cast128-cbc, aes192-cbc, aes256-cbc, arcfour, rijndael-cbc@lysator.liu.se + +# The MACs that must match exactly (order matters). +macs = hmac-md5, hmac-sha1, umac-64@openssh.com, hmac-ripemd160, hmac-ripemd160@openssh.com, hmac-sha1-96, hmac-md5-96 diff --git a/test/docker/ssh1_host_key b/test/docker/ssh1_host_key Binary files differnew file mode 100644 index 0000000..c98971c --- /dev/null +++ b/test/docker/ssh1_host_key diff --git a/test/docker/ssh1_host_key.pub b/test/docker/ssh1_host_key.pub new file mode 100644 index 0000000..b66c66f --- /dev/null +++ b/test/docker/ssh1_host_key.pub @@ -0,0 +1 @@ +1024 35 150823875409720459951648542224727752099073441604930026287525797402159071426070997897033651155038337251362080634963146983947007228274330777134724953282680928153520263171933106732090266742784258910450489054624715996015082463159338507115031336180486071622718809324273851629938883104520608180885444242395900180011 root@ubuntu1604server diff --git a/test/docker/ssh_host_dsa_key b/test/docker/ssh_host_dsa_key new file mode 100644 index 0000000..ecd47f9 --- /dev/null +++ b/test/docker/ssh_host_dsa_key @@ -0,0 +1,12 @@ +-----BEGIN DSA PRIVATE KEY----- +MIIBugIBAAKBgQDth1eV+A8j191R0ey0dVXL2LGNGYM+a+PomSa7suK8xNCeVLKC +YpQ6VSWpAf6FbRWev1UVo8IpbglwFZPcyFPK2G1H7p45ows2SN4CleszDD56e6W0 +3Plc+qMqSJ6LTjr4M5+HqTDOM3CS72d7MXUkfHQiagyrWQhXyc0kFsNJLwIVAKg7 +b5+NiIZzpg5IEH0tlYFQpuhBAoGAGcbq79QqNNZRuPCE/F05sCoTRGCmFnDjCuCg +WN7wNRotjMz/S3pHtCCeuTT1jT6Hy0ZFHftv0t/GF8GBRgeokUbS4ytHpOkFWcTz +8oFguDL44nq8eNfSY6bzEl84qsgEe4HP93mB4FR1ZUUgI4b7gCBOYEFl3yPiH7H1 +p7Z9E1oCgYAl1UPQkeRhElz+AgEbNsnMKu1+6O3/z95D1Wvv4OEwAImbytlBaC7p +kwJElJNsMMfGqCC8OHdJ0e4VQQUwk/GOhD0MFhVQHBtVZYbiWmVkpfHf1ouUQg3f +1IZmz2SSt6cPPEu+BEQ/Sn3mFRJ5XSTHLtnI0HJeDND5u1+6p1nXawIURv3Maige +oxmfqC24VoROJEq+sew= +-----END DSA PRIVATE KEY----- diff --git a/test/docker/ssh_host_dsa_key.pub b/test/docker/ssh_host_dsa_key.pub new file mode 100644 index 0000000..a32a5a0 --- /dev/null +++ b/test/docker/ssh_host_dsa_key.pub @@ -0,0 +1 @@ +ssh-dss AAAAB3NzaC1kc3MAAACBAO2HV5X4DyPX3VHR7LR1VcvYsY0Zgz5r4+iZJruy4rzE0J5UsoJilDpVJakB/oVtFZ6/VRWjwiluCXAVk9zIU8rYbUfunjmjCzZI3gKV6zMMPnp7pbTc+Vz6oypInotOOvgzn4epMM4zcJLvZ3sxdSR8dCJqDKtZCFfJzSQWw0kvAAAAFQCoO2+fjYiGc6YOSBB9LZWBUKboQQAAAIAZxurv1Co01lG48IT8XTmwKhNEYKYWcOMK4KBY3vA1Gi2MzP9Leke0IJ65NPWNPofLRkUd+2/S38YXwYFGB6iRRtLjK0ek6QVZxPPygWC4Mvjierx419JjpvMSXziqyAR7gc/3eYHgVHVlRSAjhvuAIE5gQWXfI+IfsfWntn0TWgAAAIAl1UPQkeRhElz+AgEbNsnMKu1+6O3/z95D1Wvv4OEwAImbytlBaC7pkwJElJNsMMfGqCC8OHdJ0e4VQQUwk/GOhD0MFhVQHBtVZYbiWmVkpfHf1ouUQg3f1IZmz2SSt6cPPEu+BEQ/Sn3mFRJ5XSTHLtnI0HJeDND5u1+6p1nXaw== diff --git a/test/docker/ssh_host_ecdsa_key b/test/docker/ssh_host_ecdsa_key new file mode 100644 index 0000000..69eea7b --- /dev/null +++ b/test/docker/ssh_host_ecdsa_key @@ -0,0 +1,5 @@ +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEICq/YV5QenL0uW5g5tCjY3EWs+UBFmskY+Jjt2vd2aEmoAoGCCqGSM49 +AwEHoUQDQgAEdYSxDVUjOpW479L/nRDiAdxRB5Kuy2bgkP/LA2pnWPcGIWmFa4QU +YN2U3JsFKcLIcx5cvTehQfgrHDnaSKVdKA== +-----END EC PRIVATE KEY----- diff --git a/test/docker/ssh_host_ecdsa_key.pub b/test/docker/ssh_host_ecdsa_key.pub new file mode 100644 index 0000000..4e17058 --- /dev/null +++ b/test/docker/ssh_host_ecdsa_key.pub @@ -0,0 +1 @@ +ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBHWEsQ1VIzqVuO/S/50Q4gHcUQeSrstm4JD/ywNqZ1j3BiFphWuEFGDdlNybBSnCyHMeXL03oUH4Kxw52kilXSg= diff --git a/test/docker/ssh_host_ed25519_key b/test/docker/ssh_host_ed25519_key new file mode 100644 index 0000000..3388574 --- /dev/null +++ b/test/docker/ssh_host_ed25519_key @@ -0,0 +1,7 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW +QyNTUxOQAAACC/9RD2Ao95ODDIH8i11ekTALut8AUNqWoQx0jHlP4xygAAAKDiqVOs4qlT +rAAAAAtzc2gtZWQyNTUxOQAAACC/9RD2Ao95ODDIH8i11ekTALut8AUNqWoQx0jHlP4xyg +AAAECTmHGkq0Qea0QqTJYMXL0bpxVU7mhgwYninfVWxrA017/1EPYCj3k4MMgfyLXV6RMA +u63wBQ2pahDHSMeU/jHKAAAAHWpkb2dAbG9jYWxob3N0LndvbmRlcmxhbmQubG9s +-----END OPENSSH PRIVATE KEY----- diff --git a/test/docker/ssh_host_ed25519_key-cert.pub b/test/docker/ssh_host_ed25519_key-cert.pub new file mode 100644 index 0000000..8eef563 --- /dev/null +++ b/test/docker/ssh_host_ed25519_key-cert.pub @@ -0,0 +1 @@ +ssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIO1W0I8tD0c4LypvHY1XNch3BQCw9Yy28/4KmAYql80DAAAAIL/1EPYCj3k4MMgfyLXV6RMAu63wBQ2pahDHSMeU/jHKAAAAAAAAAAAAAAACAAAABHRlc3QAAAAIAAAABHRlc3QAAAAAXV7hvAAAAACBa2YhAAAAAAAAAAAAAAAAAAAAMwAAAAtzc2gtZWQyNTUxOQAAACAbM9Wp3ZPcC8Ifhu6GjNDJaoMg7KxO0el2+r9J35TltQAAAFMAAAALc3NoLWVkMjU1MTkAAABAW60bCSeIG4Ta+57zgkSbW4LIGCxtOuJJ+pP3i3S0xJJfHGnOtXbg0NQm7pulNl/wd01kgJO9A7RjbhTh7TV1AA== ssh_host_ed25519_key.pub diff --git a/test/docker/ssh_host_ed25519_key.pub b/test/docker/ssh_host_ed25519_key.pub new file mode 100644 index 0000000..e56a56a --- /dev/null +++ b/test/docker/ssh_host_ed25519_key.pub @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIL/1EPYCj3k4MMgfyLXV6RMAu63wBQ2pahDHSMeU/jHK diff --git a/test/docker/ssh_host_rsa_key_1024 b/test/docker/ssh_host_rsa_key_1024 new file mode 100644 index 0000000..e9023b6 --- /dev/null +++ b/test/docker/ssh_host_rsa_key_1024 @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXgIBAAKBgQDeCC1U7VqVg9AfrfWrXACiW6pzYOuP8tim68z+YN/dUU7JhFZ4 +0toteQkLcJBAD2miQ6ZJYkjVfhQ4FRFeOW5vcN0UYHn8ttb2mKdGJdt24ZYY5Z6J +WHQhPOpSgtWyUv6RnxU2ligEeaoPaiepUUOhoyLf4WcF7voVCAKZNqeTtQIDAQAB +AoGATGZ16s5NqDsWJ4B9k3xx/2wZZ+BGzl6a7D0habq97XLn8HGoK6UqTBFk6lnO +WSy0hZBPrNq0AzqCDJY7RrfuZqgVAu/+HEFuXencgt8Z//ueYBaGK8yAC+OrMnDG +LbSoIGRq8saaFtCzt47c+uSVsrhJ4TvK5gbceZuD/2uw10ECQQD79T0j+YWsLISK +PKvYHqEXSMPN6b+lK9hRPLoF9NMksNLSjuxxhkYHz+hJPVNT+wPtRMAYmMdPXfKa +FjuErXVFAkEA4ZgJIOeJ7OHfqGEgd29m36yFy0UaUJ+cmYuJzHAYWgW3TOanqpZm +A8EENuXvH0DtYRVytv4m/cIRVVPxWtXzsQJBALXlQUOEc0VuSi1GScVXr3KQ3JL+ +ipWixqM3VRDRw9D8Ouc5uWbnygz/wrGFLXA2ioozlP7s5Q7eQzOMk2FgnIUCQQCz +j5QUgLcjuVWQbF6vMhisCGImPUaIzcKT5KE1/DMl1E7mAuGJwlRIwKVeHP6L3d4T +3EKGrRzT9lhdlocRSiLBAkEAi3xI0MOZp4xGviPc1C1TKuqdJSr8fHwbtLozwNQO +nnF6m5S72JzZEThDBZS9zcdBp9EFpTvUGzx/O0GI454eoA== +-----END RSA PRIVATE KEY----- diff --git a/test/docker/ssh_host_rsa_key_1024-cert_1024.pub b/test/docker/ssh_host_rsa_key_1024-cert_1024.pub new file mode 100644 index 0000000..17c7738 --- /dev/null +++ b/test/docker/ssh_host_rsa_key_1024-cert_1024.pub @@ -0,0 +1 @@ +ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgFqxXSa9HTqCw5YW3DdIwVREPGxI+i56w32RnHWRg0NoAAAADAQABAAAAgQDeCC1U7VqVg9AfrfWrXACiW6pzYOuP8tim68z+YN/dUU7JhFZ40toteQkLcJBAD2miQ6ZJYkjVfhQ4FRFeOW5vcN0UYHn8ttb2mKdGJdt24ZYY5Z6JWHQhPOpSgtWyUv6RnxU2ligEeaoPaiepUUOhoyLf4WcF7voVCAKZNqeTtQAAAAAAAAAAAAAAAgAAAAR0ZXN0AAAACAAAAAR0ZXN0AAAAAF1evHgAAAAAgWtAtQAAAAAAAAAAAAAAAAAAAJcAAAAHc3NoLXJzYQAAAAMBAAEAAACBAOdGU3cAWdR7aUV/lcb1SFcuv/086u41MVsy3TOuM5RKOYBLuFLqkO/lUROhPoNpHURBRhqpIykdjNmG4Irna+vJ06blcVsnvvXav0zJlBSGhVnHxK50EfNUMhU7eNwwxYiWt9YEydRpQcSqmbLzxjuAoNrZNbEmDX6GDnUqoetRAAAAjwAAAAdzc2gtcnNhAAAAgFRc2g0eWXGmqSa6Z8rcMPHf4rNMornEHSnTzZ8Rdh4YBhDa9xMRRy6puaWPDzXxOfZh7eSjCwrzUMEXTgCIO4oX62xm/6kUnAmKhXle0+inR/hdPg03daE0SBJ4spBT49lJ4WIW38RKFNzjmYg70rTPAnP8oM/F3CC1GV117/Vv ssh_host_rsa_key_1024.pub diff --git a/test/docker/ssh_host_rsa_key_1024-cert_3072.pub b/test/docker/ssh_host_rsa_key_1024-cert_3072.pub new file mode 100644 index 0000000..ea0160a --- /dev/null +++ b/test/docker/ssh_host_rsa_key_1024-cert_3072.pub @@ -0,0 +1 @@ +ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgrJGcfyW8V6VWGT7lD1ardj2RtTP8TOjmLRNbuoGkyZQAAAADAQABAAAAgQDeCC1U7VqVg9AfrfWrXACiW6pzYOuP8tim68z+YN/dUU7JhFZ40toteQkLcJBAD2miQ6ZJYkjVfhQ4FRFeOW5vcN0UYHn8ttb2mKdGJdt24ZYY5Z6JWHQhPOpSgtWyUv6RnxU2ligEeaoPaiepUUOhoyLf4WcF7voVCAKZNqeTtQAAAAAAAAAAAAAAAgAAAAR0ZXN0AAAACAAAAAR0ZXN0AAAAAF1evHgAAAAAgWtA7gAAAAAAAAAAAAAAAAAAAZcAAAAHc3NoLXJzYQAAAAMBAAEAAAGBAKsUBCG4/MNE6wWNXwzvNXLq4o0K3SzlK/FZfFxAlnOUBndS5ABvNDYHXAgT741sWUpmKynqgO/BlHTfioMnBNM7acWElyh2TGiDOV3veAQfgaHB/db3f9ogcxnnndZ1f83wHatgBB0I9U6SCPmvs9ucsb9j7sFU08MKPSP+iYDat3rx+B28IK90kXxBGGUPmC/HDqQbjYNWGTkdJNcpNt2agHfdicm8WeIgrTre63I9rBR8zbtVOeOMFgcCC+cmWSk4AYWOHan09hKeyM0eR3bHa70FfagvdhjNcwxPlNwMK1Sox7NGGat483Kv8rxQwnDDEc+P9KRhRVNuqFpmvp972wMSiaC/q4RvEDPfpdqhZSxrJzNJFFwCV7Dym8oKWj/Gd1OHioE7idhrkvXiyBZwe5q8A++VehoDfauZmPPQ35FUpB2qKqWPKT3UZM/UAJjBLi7R5r9vQlTqX1+b/67Ju8AEgGarVJZhbuKxRgS8L2W1JVrtNh5oAU+O4OhCHwAAAY8AAAAHc3NoLXJzYQAAAYCO78ONpHp+EGWDqDLb/GPFDH32o6oaRRrIH/Bhvg1FOi5XngnHTdU7xWdnJqNE2Sl6VOrg0sTCMYcX9fZ8tVREnCo3aF7Iwow5Br67QYKayRzHANQqHaVK46lpI1gz81V00u54tX1F8oEUqm6sRmFKFuklt6CjfbR+tnpj7DrfeOTKEBOGJP2uU0jMsJr2DrBeXrzONjIJtIJ1AxWjXd2LeIWO2C6yTkcN5ggThMMaeu6QuuBPpC2PN2COfu+Mgto9g103+/SS4Wa8CzinZZn2Xe1isUxI8QRNrShy4Hl/bIZQL7mi/0rxkfw+fA7IzMk462V99gPVSp+/jK0sbUJoC3QeeglS5hWodjW+VGZfgweGQ+AE/OxkNSv+kDPMYEkjfOf4qhxS5QFvButLt6zp2UNbE5+OWvYpdjO9/DOa0ro+wCw07+dVKIcDpU2csiCcJvQ/HmKAmhch7jOHa0WaxSX0tt0xTPJWTvr6E4WZOgEnk9AvWmrKjF5tEzGYwTU= ssh_host_rsa_key_1024.pub diff --git a/test/docker/ssh_host_rsa_key_1024.pub b/test/docker/ssh_host_rsa_key_1024.pub new file mode 100644 index 0000000..1da6065 --- /dev/null +++ b/test/docker/ssh_host_rsa_key_1024.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDeCC1U7VqVg9AfrfWrXACiW6pzYOuP8tim68z+YN/dUU7JhFZ40toteQkLcJBAD2miQ6ZJYkjVfhQ4FRFeOW5vcN0UYHn8ttb2mKdGJdt24ZYY5Z6JWHQhPOpSgtWyUv6RnxU2ligEeaoPaiepUUOhoyLf4WcF7voVCAKZNqeTtQ== diff --git a/test/docker/ssh_host_rsa_key_3072 b/test/docker/ssh_host_rsa_key_3072 new file mode 100644 index 0000000..3a2c719 --- /dev/null +++ b/test/docker/ssh_host_rsa_key_3072 @@ -0,0 +1,39 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIG5AIBAAKCAYEAzhHp7eFnrQAJqOd7aihyQyIDKgxCF7H51Q3Ft3+8af+lX3Ol +Ie77Gi5GNNM+eRB4OzG+CBslxN5I3pM//sZ+gyylA1VuWZZkOlgtbOHutIkO2ldk +XtoGidla0VAxLcUcUK6cCmqwBTT31Hp4Qimp2zyeg/l5q0DhWKguY13lrm5b3YZY +rj7CW3Ktzxf8SbYz6du8KF0dHCWilzq+FLeGzXr7Yul5njVF5njkGvZ9duQ0qiVR +zqZkrkLEWgQlCM0T+PyUbvedL1MfDZPHGh7ZhU0snOvJRsxAr31tlknq+WwauZYd +DzJf1g1URcM65UwEsPlfgOW3ZoZogR1v57Im+KdsKhq2B3snEtJgdQh06JyO0ur4 +uUXo1mMtvBFhiptUtwP4g9v/IN4neeK+wBRom46m2Q1bMUBPneBOa8r2SY/3ynrz +XuVIWFOQtF60aJ+BNqvgUVCKOmz1KzoJwTqGm+EFaKM5z+UQWjIbSE3Ge4X5hXtk +Ou52v+tyDUk6boZLAgMBAAECggGAdrhxWmA7N7tG1W2Pd6iXs7+brRTk2vvpYGqP +11kbNsJXBzf8EiG5vuqb/gEaA+uOKSRORCNHzjT2LG0POHwpFO+aneIRMkHnuolk +mk9ME+zGhtpEdDUOAUsc/GxD+QePeZgvQ/0VLdrHUT3BnPSd7DXvaT9IbnZxnX8/ +QnYtRiJEgMrOuoxjswXNxvsdmWYEYJ38uBB1Hes80f3A1vSpECbjP6gdLh2pCM/r +MvGBdQaipMfdar4IUTEcKHQs1fY3mlAxnWRjYCqJPmq10d3NrdUrHb2zBE1HCC4h +aj2ycTxFhDJqGV6Y2AboHqh2c7lPJ+R2UjI9mIpALZSviHB1POcpWCAGA3NKjri9 +8jgxl3bj03ikJNfCuvlqRTa8at63W2zZTMRsxamoiO023uUOEMNBPwWXP/rVhQ8g +ufih0SY44j0EMPIuu2PoQV4ZSOtDw8xdPrchVCa078/pP5cRa4uV0bl2K4as+cYC +BhjEq2Org3ulDW2n6Mz5ZS7NbAkxAoHBAP/bgPGKX7rfrHa5MRHIgbLSmZtUoF51 +YGelc8ytRx6UT6wriJ1jQRXiI5mZlIXyVxMpIz9s4+h59kF+LpZuNLc3vTYpPOQn +RUDBVY6+SPC5MancL7bfBoHahpWEJuJB/WUE7eWvQM03/LsBtU6Nq+R632t5KdqF +A4y86qgD1vIjcBWvySLFJZGOCoNbj7ZinoBUO3ueYK6SUj8xH6TAqOJsTPvquRT3 +AFBpFBmrVc24wW7wTiLkQOhkIQs1J/ZhYwKBwQDOL07qF8wsoQBBTTXkZ59BCauz +R8kfqe5oUBwsmGJdiIHX6gutBA07sSwzVekIvCCkJFXk3TxLoBSMHEZEIdnS+HVt +gMIacYuhbh+XztdY0kadH/SMbVQD/2LZcL99vcZPq1QF3cHb0Buip5+fyAYjoEc7 +oVgvewD/TwdNcMjos/kMNh6l04kLi6vQG3WhoSBPWaoB669ppBNXSrWKe43nXVi6 +EvjGEiL+HCCnmD6LiD6p797Owu9AChP6fXInD/kCgcEAiLP3SRbt3yLzOtvn4+CF +q83qVJv6s31zbO1x2cIbZbNIfm0kKTOG6vJQoxjzyj2ZWJt6QcEkZGoFsSiCK83m +TJ5zciTGbACvd9HUrNfukO/iISeMNuEi0O65Sdm6DNnFUdw4X6grr3pihmh7PuVj +GkisZvft7Nt08hVeKzch+W4FzRCHHxTG5eZGp7icKI64sUhQH9SXQ67aUvkkNxrZ +IWFMIK1hBlqSyGPcYXqx9aDpeSTcGrhqFcCqBxr3pySRAoHAfJNO3delEC3yxoHN +FwSYzyX1rOuplE0K89G7RCKKBDNPKFKL3Wx+Rluk9htpIlLwcdxWXWJiZNsCrykC +N3YwcuyVnqTWIj4KfG3Z/tIFgPADpDnDevkvcv7iDbi2qlV4NXix2p2C3LnfiKY4 +psSnGO1lPJ0eeAmcr6VjJyIG8bqTthIY8F5gBi7Mj3+X0iFVMTxeoKxzHqP435wP +Fe3S7kCTNFH0J1Cb/eamwDwXRhz6p5h7iXd0MMAmFAmpZ/qZAoHBAPDSIvk2ocf1 +FVW8pKtKOJFIs8iQVIaOLKwPJVP8/JsB1+7mQx5KMoROb5pNpX2edN4vvG0CgqpJ +KekleqpH6nQCqYGFZ1BDhORElNILxeJHcNl0eAG++IJ2PfIpTZV30edDqMm0x7EI +8POZWAx809VzcYbE2jsgpN/EuiaG30EAI5yNvyzmZRCyQykH+eltHlCx17MWBxRQ +bb2UUfpdInTMS2vyrvkeUACkC1DGYdBVVBqqPTkHZg+Kcbs8ntQqEQ== +-----END RSA PRIVATE KEY----- diff --git a/test/docker/ssh_host_rsa_key_3072-cert_1024.pub b/test/docker/ssh_host_rsa_key_3072-cert_1024.pub new file mode 100644 index 0000000..da6b9ec --- /dev/null +++ b/test/docker/ssh_host_rsa_key_3072-cert_1024.pub @@ -0,0 +1 @@ +ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgGHz1JwF/1IcxW3pdQtpqbUjIHaFuk0cR/+l50vG+9hIAAAADAQABAAABgQDOEent4WetAAmo53tqKHJDIgMqDEIXsfnVDcW3f7xp/6Vfc6Uh7vsaLkY00z55EHg7Mb4IGyXE3kjekz/+xn6DLKUDVW5ZlmQ6WC1s4e60iQ7aV2Re2gaJ2VrRUDEtxRxQrpwKarAFNPfUenhCKanbPJ6D+XmrQOFYqC5jXeWublvdhliuPsJbcq3PF/xJtjPp27woXR0cJaKXOr4Ut4bNevti6XmeNUXmeOQa9n125DSqJVHOpmSuQsRaBCUIzRP4/JRu950vUx8Nk8caHtmFTSyc68lGzECvfW2WSer5bBq5lh0PMl/WDVRFwzrlTASw+V+A5bdmhmiBHW/nsib4p2wqGrYHeycS0mB1CHTonI7S6vi5RejWYy28EWGKm1S3A/iD2/8g3id54r7AFGibjqbZDVsxQE+d4E5ryvZJj/fKevNe5UhYU5C0XrRon4E2q+BRUIo6bPUrOgnBOoab4QVooznP5RBaMhtITcZ7hfmFe2Q67na/63INSTpuhksAAAAAAAAAAAAAAAIAAAAEdGVzdAAAAAgAAAAEdGVzdAAAAABdXry0AAAAAIFrQR8AAAAAAAAAAAAAAAAAAACXAAAAB3NzaC1yc2EAAAADAQABAAAAgQDnRlN3AFnUe2lFf5XG9UhXLr/9POruNTFbMt0zrjOUSjmAS7hS6pDv5VEToT6DaR1EQUYaqSMpHYzZhuCK52vrydOm5XFbJ7712r9MyZQUhoVZx8SudBHzVDIVO3jcMMWIlrfWBMnUaUHEqpmy88Y7gKDa2TWxJg1+hg51KqHrUQAAAI8AAAAHc3NoLXJzYQAAAIB4HaEexgQ9T6rScEbiHZx+suCaYXI7ywLYyoSEO48K8o+MmO83UTLtpPa3DXlT8hSYL8Aq6Bb5AMkDawsgsC484owPqObT/5ndLG/fctNBFcCTSL0ftte+A8xH0pZaGRoKbdxxgMqX4ubrCXpbMLGF9aAeh7MRa756XzqGlsCiSA== ssh_host_rsa_key_3072.pub diff --git a/test/docker/ssh_host_rsa_key_3072-cert_3072.pub b/test/docker/ssh_host_rsa_key_3072-cert_3072.pub new file mode 100644 index 0000000..78f49ea --- /dev/null +++ b/test/docker/ssh_host_rsa_key_3072-cert_3072.pub @@ -0,0 +1 @@ +ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAg9MVX4OlkEy3p9eC+JJp8h7j76EmI46EY/RXxCGSWTC0AAAADAQABAAABgQDOEent4WetAAmo53tqKHJDIgMqDEIXsfnVDcW3f7xp/6Vfc6Uh7vsaLkY00z55EHg7Mb4IGyXE3kjekz/+xn6DLKUDVW5ZlmQ6WC1s4e60iQ7aV2Re2gaJ2VrRUDEtxRxQrpwKarAFNPfUenhCKanbPJ6D+XmrQOFYqC5jXeWublvdhliuPsJbcq3PF/xJtjPp27woXR0cJaKXOr4Ut4bNevti6XmeNUXmeOQa9n125DSqJVHOpmSuQsRaBCUIzRP4/JRu950vUx8Nk8caHtmFTSyc68lGzECvfW2WSer5bBq5lh0PMl/WDVRFwzrlTASw+V+A5bdmhmiBHW/nsib4p2wqGrYHeycS0mB1CHTonI7S6vi5RejWYy28EWGKm1S3A/iD2/8g3id54r7AFGibjqbZDVsxQE+d4E5ryvZJj/fKevNe5UhYU5C0XrRon4E2q+BRUIo6bPUrOgnBOoab4QVooznP5RBaMhtITcZ7hfmFe2Q67na/63INSTpuhksAAAAAAAAAAAAAAAIAAAAEdGVzdAAAAAgAAAAEdGVzdAAAAABdXr0sAAAAAIFrQWwAAAAAAAAAAAAAAAAAAAGXAAAAB3NzaC1yc2EAAAADAQABAAABgQCrFAQhuPzDROsFjV8M7zVy6uKNCt0s5SvxWXxcQJZzlAZ3UuQAbzQ2B1wIE++NbFlKZisp6oDvwZR034qDJwTTO2nFhJcodkxogzld73gEH4Ghwf3W93/aIHMZ553WdX/N8B2rYAQdCPVOkgj5r7PbnLG/Y+7BVNPDCj0j/omA2rd68fgdvCCvdJF8QRhlD5gvxw6kG42DVhk5HSTXKTbdmoB33YnJvFniIK063utyPawUfM27VTnjjBYHAgvnJlkpOAGFjh2p9PYSnsjNHkd2x2u9BX2oL3YYzXMMT5TcDCtUqMezRhmrePNyr/K8UMJwwxHPj/SkYUVTbqhaZr6fe9sDEomgv6uEbxAz36XaoWUsayczSRRcAlew8pvKClo/xndTh4qBO4nYa5L14sgWcHuavAPvlXoaA32rmZjz0N+RVKQdqiqljyk91GTP1ACYwS4u0ea/b0JU6l9fm/+uybvABIBmq1SWYW7isUYEvC9ltSVa7TYeaAFPjuDoQh8AAAGPAAAAB3NzaC1yc2EAAAGAG8tCiBMSq3Of3Gmcrid2IfPmaaemYivgEEuK8ubq1rznF0vtR07/NUQ7WVzfJhUSeG0gtJ3A1ey60NjcBn0DHao4Q3ATIXnkSOIKjNolZ2urqYv9fT1LAC4I5XWGzK2aKK0NEqAYr06YPtcGOBQk5+3GPAWSJ4eQycKRz5BSuMYbKaVxU0kGSvbavG07ZntMQhia/lILyq84PjXh/JlRVpIqY+LAS0qwqkUR3gWMTmvYvYI7fXU84ReVB1ut75bY7Xx0DXHPl1Zc2MNDLGcKsByZtoO9ueZRyOlZMUJcVP5fK+OUuZKjMbCaaJnV55BQ78/rftIPYsTEEO2Sf9WT86ADa3k4S0pyWqlTxBzZcDWNt+fZFNm9wcqcYS32nDKtfixcDN8E/IJIWY7aoabPqoYnKUVQBOcIEnZf1HqsKUVmF44Dp9mKhefUs3BtcdK63j/lNXzzMrPwZQAreJqH/uV3TgYBLjMPl++ctX6tCe6Hv5zFKNhnOCSBSzcsCgIU ssh_host_rsa_key_3072.pub diff --git a/test/docker/ssh_host_rsa_key_3072.pub b/test/docker/ssh_host_rsa_key_3072.pub new file mode 100644 index 0000000..ad83cd1 --- /dev/null +++ b/test/docker/ssh_host_rsa_key_3072.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDOEent4WetAAmo53tqKHJDIgMqDEIXsfnVDcW3f7xp/6Vfc6Uh7vsaLkY00z55EHg7Mb4IGyXE3kjekz/+xn6DLKUDVW5ZlmQ6WC1s4e60iQ7aV2Re2gaJ2VrRUDEtxRxQrpwKarAFNPfUenhCKanbPJ6D+XmrQOFYqC5jXeWublvdhliuPsJbcq3PF/xJtjPp27woXR0cJaKXOr4Ut4bNevti6XmeNUXmeOQa9n125DSqJVHOpmSuQsRaBCUIzRP4/JRu950vUx8Nk8caHtmFTSyc68lGzECvfW2WSer5bBq5lh0PMl/WDVRFwzrlTASw+V+A5bdmhmiBHW/nsib4p2wqGrYHeycS0mB1CHTonI7S6vi5RejWYy28EWGKm1S3A/iD2/8g3id54r7AFGibjqbZDVsxQE+d4E5ryvZJj/fKevNe5UhYU5C0XrRon4E2q+BRUIo6bPUrOgnBOoab4QVooznP5RBaMhtITcZ7hfmFe2Q67na/63INSTpuhks= diff --git a/test/stubs/colorama.pyi b/test/stubs/colorama.pyi new file mode 100644 index 0000000..cd5a50a --- /dev/null +++ b/test/stubs/colorama.pyi @@ -0,0 +1,4 @@ +from typing import Optional + +def init(autoreset: bool = False, convert: Optional[bool] = None, strip: Optional[bool] = None, wrap: bool = True) -> None: ... + diff --git a/test/test_algorithm.py b/test/test_algorithm.py new file mode 100644 index 0000000..8003616 --- /dev/null +++ b/test/test_algorithm.py @@ -0,0 +1,166 @@ +import pytest + +from ssh_audit.algorithm import Algorithm +from ssh_audit.timeframe import Timeframe + + +# pylint: disable=attribute-defined-outside-init +class TestAlgorithm: + @pytest.fixture(autouse=True) + def init(self, ssh_audit): + self.algorithm = Algorithm + self.timeframe = Timeframe + + def _tf(self, v, s=None): + return self.timeframe().update(v, s) + + def test_get_ssh_version(self): + def ver(v): + return self.algorithm.get_ssh_version(v) + + assert ver('7.5') == ('OpenSSH', '7.5', False) + assert ver('7.5C') == ('OpenSSH', '7.5', True) + assert ver('d2016.74') == ('Dropbear SSH', '2016.74', False) + assert ver('l10.7.4') == ('libssh', '0.7.4', False) + assert ver('')[1] == '' + + def test_get_since_text(self): + def gst(v): + return self.algorithm.get_since_text(v) + + assert gst(['7.5']) == 'available since OpenSSH 7.5' + assert gst(['7.5C']) == 'available since OpenSSH 7.5 (client only)' + assert gst(['7.5,']) == 'available since OpenSSH 7.5' + assert gst(['d2016.73']) == 'available since Dropbear SSH 2016.73' + assert gst(['7.5,d2016.73']) == 'available since OpenSSH 7.5, Dropbear SSH 2016.73' + assert gst(['l10.7.4']) is None + assert gst([]) is None + + def test_timeframe_creation(self): + # pylint: disable=line-too-long,too-many-statements + def cmp_tf(v, s, r): + assert str(self._tf(v, s)) == str(r) + + cmp_tf(['6.2'], None, {'OpenSSH': ['6.2', None, '6.2', None]}) + cmp_tf(['6.2'], True, {'OpenSSH': ['6.2', None, None, None]}) + cmp_tf(['6.2'], False, {'OpenSSH': [None, None, '6.2', None]}) + cmp_tf(['6.2C'], None, {'OpenSSH': [None, None, '6.2', None]}) + cmp_tf(['6.2C'], True, {}) + cmp_tf(['6.2C'], False, {'OpenSSH': [None, None, '6.2', None]}) + cmp_tf(['6.1,6.2C'], None, {'OpenSSH': ['6.1', None, '6.2', None]}) + cmp_tf(['6.1,6.2C'], True, {'OpenSSH': ['6.1', None, None, None]}) + cmp_tf(['6.1,6.2C'], False, {'OpenSSH': [None, None, '6.2', None]}) + cmp_tf(['6.2C,6.1'], None, {'OpenSSH': ['6.1', None, '6.2', None]}) + cmp_tf(['6.2C,6.1'], True, {'OpenSSH': ['6.1', None, None, None]}) + cmp_tf(['6.2C,6.1'], False, {'OpenSSH': [None, None, '6.2', None]}) + cmp_tf(['6.3,6.2C'], None, {'OpenSSH': ['6.3', None, '6.2', None]}) + cmp_tf(['6.3,6.2C'], True, {'OpenSSH': ['6.3', None, None, None]}) + cmp_tf(['6.3,6.2C'], False, {'OpenSSH': [None, None, '6.2', None]}) + cmp_tf(['6.2C,6.3'], None, {'OpenSSH': ['6.3', None, '6.2', None]}) + cmp_tf(['6.2C,6.3'], True, {'OpenSSH': ['6.3', None, None, None]}) + cmp_tf(['6.2C,6.3'], False, {'OpenSSH': [None, None, '6.2', None]}) + + cmp_tf(['6.2', '6.6'], None, {'OpenSSH': ['6.2', '6.6', '6.2', '6.6']}) + cmp_tf(['6.2', '6.6'], True, {'OpenSSH': ['6.2', '6.6', None, None]}) + cmp_tf(['6.2', '6.6'], False, {'OpenSSH': [None, None, '6.2', '6.6']}) + cmp_tf(['6.2C', '6.6'], None, {'OpenSSH': [None, '6.6', '6.2', '6.6']}) + cmp_tf(['6.2C', '6.6'], True, {'OpenSSH': [None, '6.6', None, None]}) + cmp_tf(['6.2C', '6.6'], False, {'OpenSSH': [None, None, '6.2', '6.6']}) + cmp_tf(['6.1,6.2C', '6.6'], None, {'OpenSSH': ['6.1', '6.6', '6.2', '6.6']}) + cmp_tf(['6.1,6.2C', '6.6'], True, {'OpenSSH': ['6.1', '6.6', None, None]}) + cmp_tf(['6.1,6.2C', '6.6'], False, {'OpenSSH': [None, None, '6.2', '6.6']}) + cmp_tf(['6.2C,6.1', '6.6'], None, {'OpenSSH': ['6.1', '6.6', '6.2', '6.6']}) + cmp_tf(['6.2C,6.1', '6.6'], True, {'OpenSSH': ['6.1', '6.6', None, None]}) + cmp_tf(['6.2C,6.1', '6.6'], False, {'OpenSSH': [None, None, '6.2', '6.6']}) + cmp_tf(['6.3,6.2C', '6.6'], None, {'OpenSSH': ['6.3', '6.6', '6.2', '6.6']}) + cmp_tf(['6.3,6.2C', '6.6'], True, {'OpenSSH': ['6.3', '6.6', None, None]}) + cmp_tf(['6.3,6.2C', '6.6'], False, {'OpenSSH': [None, None, '6.2', '6.6']}) + cmp_tf(['6.2C,6.3', '6.6'], None, {'OpenSSH': ['6.3', '6.6', '6.2', '6.6']}) + cmp_tf(['6.2C,6.3', '6.6'], True, {'OpenSSH': ['6.3', '6.6', None, None]}) + cmp_tf(['6.2C,6.3', '6.6'], False, {'OpenSSH': [None, None, '6.2', '6.6']}) + + cmp_tf(['6.2', '6.6', None], None, {'OpenSSH': ['6.2', '6.6', '6.2', None]}) + cmp_tf(['6.2', '6.6', None], True, {'OpenSSH': ['6.2', '6.6', None, None]}) + cmp_tf(['6.2', '6.6', None], False, {'OpenSSH': [None, None, '6.2', None]}) + cmp_tf(['6.2C', '6.6', None], None, {'OpenSSH': [None, '6.6', '6.2', None]}) + cmp_tf(['6.2C', '6.6', None], True, {'OpenSSH': [None, '6.6', None, None]}) + cmp_tf(['6.2C', '6.6', None], False, {'OpenSSH': [None, None, '6.2', None]}) + cmp_tf(['6.1,6.2C', '6.6', None], None, {'OpenSSH': ['6.1', '6.6', '6.2', None]}) + cmp_tf(['6.1,6.2C', '6.6', None], True, {'OpenSSH': ['6.1', '6.6', None, None]}) + cmp_tf(['6.1,6.2C', '6.6', None], False, {'OpenSSH': [None, None, '6.2', None]}) + cmp_tf(['6.2C,6.1', '6.6', None], None, {'OpenSSH': ['6.1', '6.6', '6.2', None]}) + cmp_tf(['6.2C,6.1', '6.6', None], True, {'OpenSSH': ['6.1', '6.6', None, None]}) + cmp_tf(['6.2C,6.1', '6.6', None], False, {'OpenSSH': [None, None, '6.2', None]}) + cmp_tf(['6.2,6.3C', '6.6', None], None, {'OpenSSH': ['6.2', '6.6', '6.3', None]}) + cmp_tf(['6.2,6.3C', '6.6', None], True, {'OpenSSH': ['6.2', '6.6', None, None]}) + cmp_tf(['6.2,6.3C', '6.6', None], False, {'OpenSSH': [None, None, '6.3', None]}) + cmp_tf(['6.3C,6.2', '6.6', None], None, {'OpenSSH': ['6.2', '6.6', '6.3', None]}) + cmp_tf(['6.3C,6.2', '6.6', None], True, {'OpenSSH': ['6.2', '6.6', None, None]}) + cmp_tf(['6.3C,6.2', '6.6', None], False, {'OpenSSH': [None, None, '6.3', None]}) + + cmp_tf(['6.2', '6.6', '7.1'], None, {'OpenSSH': ['6.2', '6.6', '6.2', '7.1']}) + cmp_tf(['6.2', '6.6', '7.1'], True, {'OpenSSH': ['6.2', '6.6', None, None]}) + cmp_tf(['6.2', '6.6', '7.1'], False, {'OpenSSH': [None, None, '6.2', '7.1']}) + cmp_tf(['6.1,6.2C', '6.6', '7.1'], None, {'OpenSSH': ['6.1', '6.6', '6.2', '7.1']}) + cmp_tf(['6.1,6.2C', '6.6', '7.1'], True, {'OpenSSH': ['6.1', '6.6', None, None]}) + cmp_tf(['6.1,6.2C', '6.6', '7.1'], False, {'OpenSSH': [None, None, '6.2', '7.1']}) + cmp_tf(['6.2C,6.1', '6.6', '7.1'], None, {'OpenSSH': ['6.1', '6.6', '6.2', '7.1']}) + cmp_tf(['6.2C,6.1', '6.6', '7.1'], True, {'OpenSSH': ['6.1', '6.6', None, None]}) + cmp_tf(['6.2C,6.1', '6.6', '7.1'], False, {'OpenSSH': [None, None, '6.2', '7.1']}) + cmp_tf(['6.2,6.3C', '6.6', '7.1'], None, {'OpenSSH': ['6.2', '6.6', '6.3', '7.1']}) + cmp_tf(['6.2,6.3C', '6.6', '7.1'], True, {'OpenSSH': ['6.2', '6.6', None, None]}) + cmp_tf(['6.2,6.3C', '6.6', '7.1'], False, {'OpenSSH': [None, None, '6.3', '7.1']}) + cmp_tf(['6.3C,6.2', '6.6', '7.1'], None, {'OpenSSH': ['6.2', '6.6', '6.3', '7.1']}) + cmp_tf(['6.3C,6.2', '6.6', '7.1'], True, {'OpenSSH': ['6.2', '6.6', None, None]}) + cmp_tf(['6.3C,6.2', '6.6', '7.1'], False, {'OpenSSH': [None, None, '6.3', '7.1']}) + + tf1 = self._tf(['6.1,d2016.72,6.2C', '6.6,d2016.73', '7.1,d2016.74']) + tf2 = self._tf(['d2016.72,6.2C,6.1', 'd2016.73,6.6', 'd2016.74,7.1']) + tf3 = self._tf(['d2016.72,6.2C,6.1', '6.6,d2016.73', '7.1,d2016.74']) + # check without caring for output order + ov = "'OpenSSH': ['6.1', '6.6', '6.2', '7.1']" + dv = "'Dropbear SSH': ['2016.72', '2016.73', '2016.72', '2016.74']" + assert len(str(tf1)) == len(str(tf2)) == len(str(tf3)) + assert ov in str(tf1) and ov in str(tf2) and ov in str(tf3) + assert dv in str(tf1) and dv in str(tf2) and dv in str(tf3) + assert ov in repr(tf1) and ov in repr(tf2) and ov in repr(tf3) + assert dv in repr(tf1) and dv in repr(tf2) and dv in repr(tf3) + + def test_timeframe_object(self): + tf = self._tf(['6.1,6.2C', '6.6', '7.1']) + assert 'OpenSSH' in tf + assert 'Dropbear SSH' not in tf + assert 'libssh' not in tf + assert 'unknown' not in tf + assert tf['OpenSSH'] == ('6.1', '6.6', '6.2', '7.1') + assert tf['Dropbear SSH'] == (None, None, None, None) + assert tf['libssh'] == (None, None, None, None) + assert tf['unknown'] == (None, None, None, None) + assert tf.get_from('OpenSSH', True) == '6.1' + assert tf.get_till('OpenSSH', True) == '6.6' + assert tf.get_from('OpenSSH', False) == '6.2' + assert tf.get_till('OpenSSH', False) == '7.1' + + tf = self._tf(['6.1,d2016.72,6.2C', '6.6,d2016.73', '7.1,d2016.74']) + assert 'OpenSSH' in tf + assert 'Dropbear SSH' in tf + assert 'libssh' not in tf + assert 'unknown' not in tf + assert tf['OpenSSH'] == ('6.1', '6.6', '6.2', '7.1') + assert tf['Dropbear SSH'] == ('2016.72', '2016.73', '2016.72', '2016.74') + assert tf['libssh'] == (None, None, None, None) + assert tf['unknown'] == (None, None, None, None) + assert tf.get_from('OpenSSH', True) == '6.1' + assert tf.get_till('OpenSSH', True) == '6.6' + assert tf.get_from('OpenSSH', False) == '6.2' + assert tf.get_till('OpenSSH', False) == '7.1' + assert tf.get_from('Dropbear SSH', True) == '2016.72' + assert tf.get_till('Dropbear SSH', True) == '2016.73' + assert tf.get_from('Dropbear SSH', False) == '2016.72' + assert tf.get_till('Dropbear SSH', False) == '2016.74' + ov = "'OpenSSH': ['6.1', '6.6', '6.2', '7.1']" + dv = "'Dropbear SSH': ['2016.72', '2016.73', '2016.72', '2016.74']" + assert ov in str(tf) + assert dv in str(tf) + assert ov in repr(tf) + assert dv in repr(tf) diff --git a/test/test_auditconf.py b/test/test_auditconf.py new file mode 100644 index 0000000..05e7089 --- /dev/null +++ b/test/test_auditconf.py @@ -0,0 +1,178 @@ +import pytest +from ssh_audit.ssh_audit import process_commandline + + +# pylint: disable=attribute-defined-outside-init +class TestAuditConf: + @pytest.fixture(autouse=True) + def init(self, ssh_audit): + self.AuditConf = ssh_audit.AuditConf + self.OutputBuffer = ssh_audit.OutputBuffer + self.usage = ssh_audit.usage + self.process_commandline = process_commandline + + @staticmethod + def _test_conf(conf, **kwargs): + options = { + 'host': '', + 'port': 22, + 'ssh1': True, + 'ssh2': True, + 'batch': False, + 'colors': True, + 'verbose': False, + 'level': 'info', + 'ipv4': False, + 'ipv6': False + } + for k, v in kwargs.items(): + options[k] = v + assert conf.host == options['host'] + assert conf.port == options['port'] + assert conf.ssh1 is options['ssh1'] + assert conf.ssh2 is options['ssh2'] + assert conf.batch is options['batch'] + assert conf.colors is options['colors'] + assert conf.verbose is options['verbose'] + assert conf.level == options['level'] + assert conf.ipv4 == options['ipv4'] + assert conf.ipv6 == options['ipv6'] + + def test_audit_conf_defaults(self): + conf = self.AuditConf() + self._test_conf(conf) + + def test_audit_conf_booleans(self): + conf = self.AuditConf() + for p in ['ssh1', 'ssh2', 'batch', 'colors', 'verbose']: + for v in [True, 1]: + setattr(conf, p, v) + assert getattr(conf, p) is True + for v in [False, 0]: + setattr(conf, p, v) + assert getattr(conf, p) is False + + def test_audit_conf_port(self): + conf = self.AuditConf() + for port in [22, 2222]: + conf.port = port + assert conf.port == port + for port in [-1, 0, 65536, 99999]: + with pytest.raises(ValueError) as excinfo: + conf.port = port + excinfo.match(r'.*invalid port.*') + + def test_audit_conf_ip_version_preference(self): + # ipv4-only + conf = self.AuditConf() + conf.ipv4 = True + assert conf.ipv4 is True + assert conf.ipv6 is False + assert conf.ip_version_preference == [4] + # ipv6-only + conf = self.AuditConf() + conf.ipv6 = True + assert conf.ipv4 is False + assert conf.ipv6 is True + assert conf.ip_version_preference == [6] + # ipv4-preferred + conf = self.AuditConf() + conf.ipv4 = True + conf.ipv6 = True + assert conf.ipv4 is True + assert conf.ipv6 is True + assert conf.ip_version_preference == [4, 6] + # ipv6-preferred + conf = self.AuditConf() + conf.ipv6 = True + conf.ipv4 = True + assert conf.ipv4 is True + assert conf.ipv6 is True + assert conf.ip_version_preference == [6, 4] + # defaults + conf = self.AuditConf() + assert conf.ipv4 is False + assert conf.ipv6 is False + assert conf.ip_version_preference == [] + + def test_audit_conf_level(self): + conf = self.AuditConf() + for level in ['info', 'warn', 'fail']: + conf.level = level + assert conf.level == level + for level in ['head', 'good', 'unknown', None]: + with pytest.raises(ValueError) as excinfo: + conf.level = level + excinfo.match(r'.*invalid level.*') + + def test_audit_conf_process_commandline(self): + # pylint: disable=too-many-statements + c = lambda x: self.process_commandline(self.OutputBuffer, x.split(), self.usage) # noqa + with pytest.raises(SystemExit): + conf = c('') + with pytest.raises(SystemExit): + conf = c('-x') + with pytest.raises(SystemExit): + conf = c('-h') + with pytest.raises(SystemExit): + conf = c('--help') + with pytest.raises(SystemExit): + conf = c(':') + with pytest.raises(SystemExit): + conf = c(':22') + conf = c('localhost') + self._test_conf(conf, host='localhost') + conf = c('github.com') + self._test_conf(conf, host='github.com') + conf = c('localhost:2222') + self._test_conf(conf, host='localhost', port=2222) + conf = c('-p 2222 localhost') + self._test_conf(conf, host='localhost', port=2222) + conf = c('2001:4860:4860::8888') + self._test_conf(conf, host='2001:4860:4860::8888') + conf = c('[2001:4860:4860::8888]:22') + self._test_conf(conf, host='2001:4860:4860::8888') + conf = c('[2001:4860:4860::8888]:2222') + self._test_conf(conf, host='2001:4860:4860::8888', port=2222) + conf = c('-p 2222 2001:4860:4860::8888') + self._test_conf(conf, host='2001:4860:4860::8888', port=2222) + with pytest.raises(ValueError): + conf = c('localhost:abc') + with pytest.raises(SystemExit): + conf = c('-p abc localhost') + with pytest.raises(ValueError): + conf = c('localhost:-22') + with pytest.raises(SystemExit): + conf = c('-p -22 localhost') + with pytest.raises(ValueError): + conf = c('localhost:99999') + with pytest.raises(SystemExit): + conf = c('-p 99999 localhost') + conf = c('-1 localhost') + self._test_conf(conf, host='localhost', ssh1=True, ssh2=False) + conf = c('-2 localhost') + self._test_conf(conf, host='localhost', ssh1=False, ssh2=True) + conf = c('-12 localhost') + self._test_conf(conf, host='localhost', ssh1=True, ssh2=True) + conf = c('-4 localhost') + self._test_conf(conf, host='localhost', ipv4=True, ipv6=False, ipvo=(4,)) + conf = c('-6 localhost') + self._test_conf(conf, host='localhost', ipv4=False, ipv6=True, ipvo=(6,)) + conf = c('-46 localhost') + self._test_conf(conf, host='localhost', ipv4=True, ipv6=True, ipvo=(4, 6)) + conf = c('-64 localhost') + self._test_conf(conf, host='localhost', ipv4=True, ipv6=True, ipvo=(6, 4)) + conf = c('-b localhost') + self._test_conf(conf, host='localhost', batch=True, verbose=True) + conf = c('-n localhost') + self._test_conf(conf, host='localhost', colors=False) + conf = c('-v localhost') + self._test_conf(conf, host='localhost', verbose=True) + conf = c('-l info localhost') + self._test_conf(conf, host='localhost', level='info') + conf = c('-l warn localhost') + self._test_conf(conf, host='localhost', level='warn') + conf = c('-l fail localhost') + self._test_conf(conf, host='localhost', level='fail') + with pytest.raises(SystemExit): + conf = c('-l something localhost') diff --git a/test/test_banner.py b/test/test_banner.py new file mode 100644 index 0000000..e514134 --- /dev/null +++ b/test/test_banner.py @@ -0,0 +1,69 @@ +import pytest + +from ssh_audit.banner import Banner + + +# pylint: disable=line-too-long,attribute-defined-outside-init +class TestBanner: + @pytest.fixture(autouse=True) + def init(self, ssh_audit): + self.banner = Banner + + def test_simple_banners(self): + banner = lambda x: self.banner.parse(x) # noqa + b = banner('SSH-2.0-OpenSSH_7.3') + assert b.protocol == (2, 0) + assert b.software == 'OpenSSH_7.3' + assert b.comments is None + assert str(b) == 'SSH-2.0-OpenSSH_7.3' + b = banner('SSH-1.99-Sun_SSH_1.1.3') + assert b.protocol == (1, 99) + assert b.software == 'Sun_SSH_1.1.3' + assert b.comments is None + assert str(b) == 'SSH-1.99-Sun_SSH_1.1.3' + b = banner('SSH-1.5-Cisco-1.25') + assert b.protocol == (1, 5) + assert b.software == 'Cisco-1.25' + assert b.comments is None + assert str(b) == 'SSH-1.5-Cisco-1.25' + + def test_invalid_banners(self): + b = lambda x: self.banner.parse(x) # noqa + assert b('Something') is None + assert b('SSH-XXX-OpenSSH_7.3') is None + + def test_banners_with_spaces(self): + b = lambda x: self.banner.parse(x) # noqa + s = 'SSH-2.0-OpenSSH_4.3p2' + assert str(b('SSH-2.0-OpenSSH_4.3p2 ')) == s + assert str(b('SSH-2.0- OpenSSH_4.3p2')) == s + assert str(b('SSH-2.0- OpenSSH_4.3p2 ')) == s + s = 'SSH-2.0-OpenSSH_4.3p2 Debian-9etch3 on i686-pc-linux-gnu' + assert str(b('SSH-2.0- OpenSSH_4.3p2 Debian-9etch3 on i686-pc-linux-gnu')) == s + assert str(b('SSH-2.0-OpenSSH_4.3p2 Debian-9etch3 on i686-pc-linux-gnu ')) == s + assert str(b('SSH-2.0- OpenSSH_4.3p2 Debian-9etch3 on i686-pc-linux-gnu ')) == s + + def test_banners_without_software(self): + b = lambda x: self.banner.parse(x) # noqa + assert b('SSH-2.0').protocol == (2, 0) + assert b('SSH-2.0').software is None + assert b('SSH-2.0').comments is None + assert str(b('SSH-2.0')) == 'SSH-2.0' + assert b('SSH-2.0-').protocol == (2, 0) + assert b('SSH-2.0-').software == '' + assert b('SSH-2.0-').comments is None + assert str(b('SSH-2.0-')) == 'SSH-2.0-' + + def test_banners_with_comments(self): + b = lambda x: self.banner.parse(x) # noqa + assert repr(b('SSH-2.0-OpenSSH_7.2p2 Ubuntu-1')) == '<Banner(protocol=2.0, software=OpenSSH_7.2p2, comments=Ubuntu-1)>' + assert repr(b('SSH-1.99-OpenSSH_3.4p1 Debian 1:3.4p1-1.woody.3')) == '<Banner(protocol=1.99, software=OpenSSH_3.4p1, comments=Debian 1:3.4p1-1.woody.3)>' + assert repr(b('SSH-1.5-1.3.7 F-SECURE SSH')) == '<Banner(protocol=1.5, software=1.3.7, comments=F-SECURE SSH)>' + + def test_banners_with_multiple_protocols(self): + b = lambda x: self.banner.parse(x) # noqa + assert str(b('SSH-1.99-SSH-1.99-OpenSSH_3.6.1p2')) == 'SSH-1.99-OpenSSH_3.6.1p2' + assert str(b('SSH-2.0-SSH-2.0-OpenSSH_4.3p2 Debian-9')) == 'SSH-2.0-OpenSSH_4.3p2 Debian-9' + assert str(b('SSH-1.99-SSH-2.0-dropbear_0.5')) == 'SSH-1.99-dropbear_0.5' + assert str(b('SSH-2.0-SSH-1.99-OpenSSH_4.2p1 SSH Secure Shell (non-commercial)')) == 'SSH-1.99-OpenSSH_4.2p1 SSH Secure Shell (non-commercial)' + assert str(b('SSH-1.99-SSH-1.99-SSH-1.99-OpenSSH_3.9p1')) == 'SSH-1.99-OpenSSH_3.9p1' diff --git a/test/test_buffer.py b/test/test_buffer.py new file mode 100644 index 0000000..499dfd9 --- /dev/null +++ b/test/test_buffer.py @@ -0,0 +1,145 @@ +import re +import pytest + +from ssh_audit.readbuf import ReadBuf +from ssh_audit.writebuf import WriteBuf + + +# pylint: disable=attribute-defined-outside-init,bad-whitespace +class TestBuffer: + @pytest.fixture(autouse=True) + def init(self, ssh_audit): + self.rbuf = ReadBuf + self.wbuf = WriteBuf + self.utf8rchar = b'\xef\xbf\xbd' + + @classmethod + def _b(cls, v): + v = re.sub(r'\s', '', v) + data = [int(v[i * 2:i * 2 + 2], 16) for i in range(len(v) // 2)] + return bytes(bytearray(data)) + + def test_unread(self): + w = self.wbuf().write_byte(1).write_int(2).write_flush() + r = self.rbuf(w) + assert r.unread_len == 5 + r.read_byte() + assert r.unread_len == 4 + r.read_int() + assert r.unread_len == 0 + + def test_byte(self): + w = lambda x: self.wbuf().write_byte(x).write_flush() # noqa + r = lambda x: self.rbuf(x).read_byte() # noqa + tc = [(0x00, '00'), + (0x01, '01'), + (0x10, '10'), + (0xff, 'ff')] + for p in tc: + assert w(p[0]) == self._b(p[1]) + assert r(self._b(p[1])) == p[0] + + def test_bool(self): + w = lambda x: self.wbuf().write_bool(x).write_flush() # noqa + r = lambda x: self.rbuf(x).read_bool() # noqa + tc = [(True, '01'), + (False, '00')] + for p in tc: + assert w(p[0]) == self._b(p[1]) + assert r(self._b(p[1])) == p[0] + + def test_int(self): + w = lambda x: self.wbuf().write_int(x).write_flush() # noqa + r = lambda x: self.rbuf(x).read_int() # noqa + tc = [(0x00, '00 00 00 00'), + (0x01, '00 00 00 01'), + (0xabcd, '00 00 ab cd'), + (0xffffffff, 'ff ff ff ff')] + for p in tc: + assert w(p[0]) == self._b(p[1]) + assert r(self._b(p[1])) == p[0] + + def test_string(self): + w = lambda x: self.wbuf().write_string(x).write_flush() # noqa + r = lambda x: self.rbuf(x).read_string() # noqa + tc = [('abc1', '00 00 00 04 61 62 63 31'), + (b'abc2', '00 00 00 04 61 62 63 32')] + for p in tc: + v = p[0] + assert w(v) == self._b(p[1]) + if not isinstance(v, bytes): + v = bytes(bytearray(v, 'utf-8')) + assert r(self._b(p[1])) == v + + def test_list(self): + w = lambda x: self.wbuf().write_list(x).write_flush() # noqa + r = lambda x: self.rbuf(x).read_list() # noqa + tc = [(['d', 'ef', 'ault'], '00 00 00 09 64 2c 65 66 2c 61 75 6c 74')] + for p in tc: + assert w(p[0]) == self._b(p[1]) + assert r(self._b(p[1])) == p[0] + + def test_list_nonutf8(self): + r = lambda x: self.rbuf(x).read_list() # noqa + src = self._b('00 00 00 04 de ad be ef') + dst = [(b'\xde\xad' + self.utf8rchar + self.utf8rchar).decode('utf-8')] + assert r(src) == dst + + def test_line(self): + w = lambda x: self.wbuf().write_line(x).write_flush() # noqa + r = lambda x: self.rbuf(x).read_line() # noqa + tc = [('example line', '65 78 61 6d 70 6c 65 20 6c 69 6e 65 0d 0a')] + for p in tc: + assert w(p[0]) == self._b(p[1]) + assert r(self._b(p[1])) == p[0] + + def test_line_nonutf8(self): + r = lambda x: self.rbuf(x).read_line() # noqa + src = self._b('de ad be af') + dst = (b'\xde\xad' + self.utf8rchar + self.utf8rchar).decode('utf-8') + assert r(src) == dst + + def test_bitlen(self): + # pylint: disable=protected-access + class Py26Int(int): + def bit_length(self): + raise AttributeError + assert self.wbuf._bitlength(42) == 6 + assert self.wbuf._bitlength(Py26Int(42)) == 6 + + def test_mpint1(self): + mpint1w = lambda x: self.wbuf().write_mpint1(x).write_flush() # noqa + mpint1r = lambda x: self.rbuf(x).read_mpint1() # noqa + tc = [(0x0, '00 00'), + (0x1234, '00 0d 12 34'), + (0x12345, '00 11 01 23 45'), + (0xdeadbeef, '00 20 de ad be ef')] + for p in tc: + assert mpint1w(p[0]) == self._b(p[1]) + assert mpint1r(self._b(p[1])) == p[0] + + def test_mpint2(self): + mpint2w = lambda x: self.wbuf().write_mpint2(x).write_flush() # noqa + mpint2r = lambda x: self.rbuf(x).read_mpint2() # noqa + tc = [(0x0, '00 00 00 00'), + (0x80, '00 00 00 02 00 80'), + (0x9a378f9b2e332a7, '00 00 00 08 09 a3 78 f9 b2 e3 32 a7'), + (-0x1234, '00 00 00 02 ed cc'), + (-0xdeadbeef, '00 00 00 05 ff 21 52 41 11'), + (-0x8000, '00 00 00 02 80 00'), + (-0x80, '00 00 00 01 80')] + for p in tc: + assert mpint2w(p[0]) == self._b(p[1]) + assert mpint2r(self._b(p[1])) == p[0] + assert mpint2r(self._b('00 00 00 02 ff 80')) == -0x80 + + def test_reset(self): + w = self.wbuf() + w.write_int(7) + w.write_int(13) + assert len(w.write_flush()) == 8 + + w.write_int(7) + w.write_int(13) + w.reset() + assert len(w.write_flush()) == 0 diff --git a/test/test_build_struct.py b/test/test_build_struct.py new file mode 100644 index 0000000..6365019 --- /dev/null +++ b/test/test_build_struct.py @@ -0,0 +1,43 @@ +import os +import pytest + +from ssh_audit.ssh2_kex import SSH2_Kex +from ssh_audit.ssh2_kexparty import SSH2_KexParty + + +@pytest.fixture +def kex(ssh_audit): + kex_algs, key_algs = [], [] + enc, mac, compression, languages = [], [], ['none'], [] + cli = SSH2_KexParty(enc, mac, compression, languages) + enc, mac, compression, languages = [], [], ['none'], [] + srv = SSH2_KexParty(enc, mac, compression, languages) + cookie = os.urandom(16) + kex = SSH2_Kex(cookie, kex_algs, key_algs, cli, srv, 0) + return kex + + +def test_prevent_runtime_error_regression(ssh_audit, kex): + """Prevent a regression of https://github.com/jtesta/ssh-audit/issues/41 + + The following test setup does not contain any sensible data. + It was made up to reproduce a situation when there are several host + keys, and an error occurred when iterating and modifying them at the + same time. + """ + kex.set_host_key("ssh-rsa", b"\x00\x00\x00\x07ssh-rsa\x00\x00\x00") + kex.set_host_key("ssh-rsa1", b"\x00\x00\x00\x07ssh-rsa\x00\x00\x00") + kex.set_host_key("ssh-rsa2", b"\x00\x00\x00\x07ssh-rsa\x00\x00\x00") + kex.set_host_key("ssh-rsa3", b"\x00\x00\x00\x07ssh-rsa\x00\x00\x00") + kex.set_host_key("ssh-rsa4", b"\x00\x00\x00\x07ssh-rsa\x00\x00\x00") + kex.set_host_key("ssh-rsa5", b"\x00\x00\x00\x07ssh-rsa\x00\x00\x00") + kex.set_host_key("ssh-rsa6", b"\x00\x00\x00\x07ssh-rsa\x00\x00\x00") + kex.set_host_key("ssh-rsa7", b"\x00\x00\x00\x07ssh-rsa\x00\x00\x00") + kex.set_host_key("ssh-rsa8", b"\x00\x00\x00\x07ssh-rsa\x00\x00\x00") + + rv = ssh_audit.build_struct('localhost', banner=None, kex=kex) + + assert len(rv["fingerprints"]) == (9 * 2) # Each host key generates two hash fingerprints: one using SHA256, and one using MD5. + + for key in ['banner', 'compression', 'enc', 'fingerprints', 'kex', 'key', 'mac']: + assert key in rv diff --git a/test/test_errors.py b/test/test_errors.py new file mode 100644 index 0000000..90cfd1c --- /dev/null +++ b/test/test_errors.py @@ -0,0 +1,172 @@ +import socket +import errno +import pytest + +from ssh_audit.outputbuffer import OutputBuffer + + +# pylint: disable=attribute-defined-outside-init +class TestErrors: + @pytest.fixture(autouse=True) + def init(self, ssh_audit): + self.AuditConf = ssh_audit.AuditConf + self.OutputBuffer = ssh_audit.OutputBuffer + self.audit = ssh_audit.audit + + def _conf(self): + conf = self.AuditConf('localhost', 22) + conf.colors = False + conf.batch = True + return conf + + def _audit(self, spy, conf=None, exit_expected=False): + if conf is None: + conf = self._conf() + spy.begin() + + out = OutputBuffer() + if exit_expected: + with pytest.raises(SystemExit): + self.audit(out, conf) + else: + ret = self.audit(out, conf) + assert ret != 0 + + out.write() + lines = spy.flush() + + # If the last line is empty, delete it. + if len(lines) > 1 and lines[-1] == '': + del lines[-1] + + return lines + + def test_connection_unresolved(self, output_spy, virtual_socket): + vsocket = virtual_socket + vsocket.gsock.addrinfodata['localhost#22'] = [] + lines = self._audit(output_spy, exit_expected=True) + assert len(lines) == 1 + assert 'has no DNS records' in lines[-1] + + def test_connection_refused(self, output_spy, virtual_socket): + vsocket = virtual_socket + vsocket.errors['connect'] = socket.error(errno.ECONNREFUSED, 'Connection refused') + lines = self._audit(output_spy, exit_expected=True) + assert len(lines) == 1 + assert 'Connection refused' in lines[-1] + + def test_connection_timeout(self, output_spy, virtual_socket): + vsocket = virtual_socket + vsocket.errors['connect'] = socket.timeout('timed out') + lines = self._audit(output_spy, exit_expected=True) + assert len(lines) == 1 + assert 'timed out' in lines[-1] + + def test_recv_empty(self, output_spy, virtual_socket): + lines = self._audit(output_spy) + assert len(lines) == 1 + assert 'did not receive banner' in lines[-1] + + def test_recv_timeout(self, output_spy, virtual_socket): + vsocket = virtual_socket + vsocket.rdata.append(socket.timeout('timed out')) + lines = self._audit(output_spy) + assert len(lines) == 1 + assert 'did not receive banner' in lines[-1] + assert 'timed out' in lines[-1] + + def test_recv_retry_till_timeout(self, output_spy, virtual_socket): + vsocket = virtual_socket + vsocket.rdata.append(socket.error(errno.EAGAIN, 'Resource temporarily unavailable')) + vsocket.rdata.append(socket.error(errno.EWOULDBLOCK, 'Resource temporarily unavailable')) + vsocket.rdata.append(socket.error(errno.EAGAIN, 'Resource temporarily unavailable')) + vsocket.rdata.append(socket.timeout('timed out')) + lines = self._audit(output_spy) + assert len(lines) == 1 + assert 'did not receive banner' in lines[-1] + assert 'timed out' in lines[-1] + + def test_recv_retry_till_reset(self, output_spy, virtual_socket): + vsocket = virtual_socket + vsocket.rdata.append(socket.error(errno.EAGAIN, 'Resource temporarily unavailable')) + vsocket.rdata.append(socket.error(errno.EWOULDBLOCK, 'Resource temporarily unavailable')) + vsocket.rdata.append(socket.error(errno.EAGAIN, 'Resource temporarily unavailable')) + vsocket.rdata.append(socket.error(errno.ECONNRESET, 'Connection reset by peer')) + lines = self._audit(output_spy) + assert len(lines) == 1 + assert 'did not receive banner' in lines[-1] + assert 'reset by peer' in lines[-1] + + def test_connection_closed_before_banner(self, output_spy, virtual_socket): + vsocket = virtual_socket + vsocket.rdata.append(socket.error(errno.ECONNRESET, 'Connection reset by peer')) + lines = self._audit(output_spy) + assert len(lines) == 1 + assert 'did not receive banner' in lines[-1] + assert 'reset by peer' in lines[-1] + + def test_connection_closed_after_header(self, output_spy, virtual_socket): + vsocket = virtual_socket + vsocket.rdata.append(b'header line 1\n') + vsocket.rdata.append(b'\n') + vsocket.rdata.append(b'header line 2\n') + vsocket.rdata.append(socket.error(errno.ECONNRESET, 'Connection reset by peer')) + lines = self._audit(output_spy) + assert len(lines) == 3 + assert 'did not receive banner' in lines[-1] + assert 'reset by peer' in lines[-1] + + def test_connection_closed_after_banner(self, output_spy, virtual_socket): + vsocket = virtual_socket + vsocket.rdata.append(b'SSH-2.0-ssh-audit-test\r\n') + vsocket.rdata.append(socket.error(54, 'Connection reset by peer')) + lines = self._audit(output_spy) + assert len(lines) == 2 + assert 'error reading packet' in lines[-1] + assert 'reset by peer' in lines[-1] + + def test_empty_data_after_banner(self, output_spy, virtual_socket): + vsocket = virtual_socket + vsocket.rdata.append(b'SSH-2.0-ssh-audit-test\r\n') + lines = self._audit(output_spy) + assert len(lines) == 2 + assert 'error reading packet' in lines[-1] + assert 'empty' in lines[-1] + + def test_wrong_data_after_banner(self, output_spy, virtual_socket): + vsocket = virtual_socket + vsocket.rdata.append(b'SSH-2.0-ssh-audit-test\r\n') + vsocket.rdata.append(b'xxx\n') + lines = self._audit(output_spy) + assert len(lines) == 2 + assert 'error reading packet' in lines[-1] + assert 'xxx' in lines[-1] + + def test_non_ascii_banner(self, output_spy, virtual_socket): + vsocket = virtual_socket + vsocket.rdata.append(b'SSH-2.0-ssh-audit-test\xc3\xbc\r\n') + lines = self._audit(output_spy) + assert len(lines) == 3 + assert 'error reading packet' in lines[-1] + assert 'ASCII' in lines[-2] + assert lines[-3].endswith('SSH-2.0-ssh-audit-test?') + + def test_nonutf8_data_after_banner(self, output_spy, virtual_socket): + vsocket = virtual_socket + vsocket.rdata.append(b'SSH-2.0-ssh-audit-test\r\n') + vsocket.rdata.append(b'\x81\xff\n') + lines = self._audit(output_spy) + assert len(lines) == 2 + assert 'error reading packet' in lines[-1] + assert '\\x81\\xff' in lines[-1] + + def test_protocol_mismatch_by_conf(self, output_spy, virtual_socket): + vsocket = virtual_socket + vsocket.rdata.append(b'SSH-1.3-ssh-audit-test\r\n') + vsocket.rdata.append(b'Protocol major versions differ.\n') + conf = self._conf() + conf.ssh1, conf.ssh2 = True, False + lines = self._audit(output_spy, conf) + assert len(lines) == 4 + assert 'error reading packet' in lines[-1] + assert 'major versions differ' in lines[-1] diff --git a/test/test_outputbuffer.py b/test/test_outputbuffer.py new file mode 100644 index 0000000..d92d7bd --- /dev/null +++ b/test/test_outputbuffer.py @@ -0,0 +1,183 @@ +import pytest + + +# pylint: disable=attribute-defined-outside-init +class TestOutputBuffer: + @pytest.fixture(autouse=True) + def init(self, ssh_audit): + self.OutputBuffer = ssh_audit.OutputBuffer + + def test_outputbuffer_no_lines(self, output_spy): + output_spy.begin() + obuf = self.OutputBuffer() + obuf.write() + assert output_spy.flush() == [''] + output_spy.begin() + + def test_outputbuffer_defaults(self): + obuf = self.OutputBuffer() + # default: on + assert obuf.batch is False + assert obuf.use_colors is True + assert obuf.level == 'info' + + def test_outputbuffer_colors(self, output_spy): + out = self.OutputBuffer() + + # Test without colors. + out.use_colors = False + + output_spy.begin() + out.info('info color') + out.write() + assert output_spy.flush() == ['info color'] + + output_spy.begin() + out.head('head color') + out.write() + assert output_spy.flush() == ['head color'] + + output_spy.begin() + out.good('good color') + out.write() + assert output_spy.flush() == ['good color'] + + output_spy.begin() + out.warn('warn color') + out.write() + assert output_spy.flush() == ['warn color'] + + output_spy.begin() + out.fail('fail color') + out.write() + assert output_spy.flush() == ['fail color'] + + # If colors aren't supported by this system, skip the color tests. + if not out.colors_supported: + return + + # Test with colors. + out.use_colors = True + + output_spy.begin() + out.info('info color') + out.write() + assert output_spy.flush() == ['info color'] + + output_spy.begin() + out.head('head color') + out.write() + assert output_spy.flush() in [['\x1b[0;36mhead color\x1b[0m'], ['\x1b[0;96mhead color\x1b[0m']] + + output_spy.begin() + out.good('good color') + out.write() + assert output_spy.flush() in [['\x1b[0;32mgood color\x1b[0m'], ['\x1b[0;92mgood color\x1b[0m']] + + output_spy.begin() + out.warn('warn color') + out.write() + assert output_spy.flush() in [['\x1b[0;33mwarn color\x1b[0m'], ['\x1b[0;93mwarn color\x1b[0m']] + + output_spy.begin() + out.fail('fail color') + out.write() + assert output_spy.flush() in [['\x1b[0;31mfail color\x1b[0m'], ['\x1b[0;91mfail color\x1b[0m']] + + def test_outputbuffer_sep(self, output_spy): + out = self.OutputBuffer() + output_spy.begin() + out.sep() + out.sep() + out.sep() + out.write() + assert output_spy.flush() == ['', '', ''] + + def test_outputbuffer_levels(self): + out = self.OutputBuffer() + assert out.get_level('info') == 0 + assert out.get_level('good') == 0 + assert out.get_level('warn') == 1 + assert out.get_level('fail') == 2 + assert out.get_level('unknown') > 2 + + def test_outputbuffer_level_property(self): + out = self.OutputBuffer() + out.level = 'info' + assert out.level == 'info' + out.level = 'good' + assert out.level == 'info' + out.level = 'warn' + assert out.level == 'warn' + out.level = 'fail' + assert out.level == 'fail' + out.level = 'invalid level' + assert out.level == 'unknown' + + def test_outputbuffer_level(self, output_spy): + out = self.OutputBuffer() + # visible: all + out.level = 'info' + output_spy.begin() + out.info('info color') + out.head('head color') + out.good('good color') + out.warn('warn color') + out.fail('fail color') + out.write() + assert len(output_spy.flush()) == 5 + # visible: head, warn, fail + out.level = 'warn' + output_spy.begin() + out.info('info color') + out.head('head color') + out.good('good color') + out.warn('warn color') + out.fail('fail color') + out.write() + assert len(output_spy.flush()) == 3 + # visible: head, fail + out.level = 'fail' + output_spy.begin() + out.info('info color') + out.head('head color') + out.good('good color') + out.warn('warn color') + out.fail('fail color') + out.write() + assert len(output_spy.flush()) == 2 + # visible: head + out.level = 'invalid level' + output_spy.begin() + out.info('info color') + out.head('head color') + out.good('good color') + out.warn('warn color') + out.fail('fail color') + out.write() + assert len(output_spy.flush()) == 1 + + def test_outputbuffer_batch(self, output_spy): + out = self.OutputBuffer() + # visible: all + output_spy.begin() + out.level = 'info' + out.batch = False + out.info('info color') + out.head('head color') + out.good('good color') + out.warn('warn color') + out.fail('fail color') + out.write() + assert len(output_spy.flush()) == 5 + # visible: all except head + output_spy.begin() + out.level = 'info' + out.batch = True + out.info('info color') + out.head('head color') + out.good('good color') + out.warn('warn color') + out.fail('fail color') + out.write() + assert len(output_spy.flush()) == 4 diff --git a/test/test_policy.py b/test/test_policy.py new file mode 100644 index 0000000..b78fab2 --- /dev/null +++ b/test/test_policy.py @@ -0,0 +1,358 @@ +import hashlib +import pytest +from datetime import date + +from ssh_audit.policy import Policy +from ssh_audit.ssh2_kex import SSH2_Kex +from ssh_audit.writebuf import WriteBuf + + +class TestPolicy: + @pytest.fixture(autouse=True) + def init(self, ssh_audit): + self.Policy = Policy + self.wbuf = WriteBuf + self.ssh2_kex = SSH2_Kex + + + def _get_kex(self): + '''Returns an SSH2.Kex object to simulate a server connection.''' + + w = self.wbuf() + w.write(b'\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff') + w.write_list(['kex_alg1', 'kex_alg2']) + w.write_list(['key_alg1', 'key_alg2']) + w.write_list(['cipher_alg1', 'cipher_alg2', 'cipher_alg3']) + w.write_list(['cipher_alg1', 'cipher_alg2', 'cipher_alg3']) + w.write_list(['mac_alg1', 'mac_alg2', 'mac_alg3']) + w.write_list(['mac_alg1', 'mac_alg2', 'mac_alg3']) + w.write_list(['comp_alg1', 'comp_alg2']) + w.write_list(['comp_alg1', 'comp_alg2']) + w.write_list(['']) + w.write_list(['']) + w.write_byte(False) + w.write_int(0) + return self.ssh2_kex.parse(w.write_flush()) + + + def test_builtin_policy_consistency(self): + '''Ensure that the BUILTIN_POLICIES struct is consistent.''' + + for policy_name in Policy.BUILTIN_POLICIES: + # Ensure that the policy name ends with " (version X)", where X is the 'version' field. + version_str = " (version %s)" % Policy.BUILTIN_POLICIES[policy_name]['version'] + assert(policy_name.endswith(version_str)) + + # Ensure that each built-in policy can be loaded with Policy.load_builtin_policy(). + assert(Policy.load_builtin_policy(policy_name) is not None) + + # Ensure that both server and client policy names are returned. + server_policy_names, client_policy_names = Policy.list_builtin_policies() + assert(len(server_policy_names) > 0) + assert(len(client_policy_names) > 0) + + + def test_policy_basic(self): + '''Ensure that a basic policy can be parsed correctly.''' + + policy_data = '''# This is a comment +name = "Test Policy" +version = 1 + +compressions = comp_alg1 +host keys = key_alg1 +key exchanges = kex_alg1, kex_alg2 +ciphers = cipher_alg1, cipher_alg2, cipher_alg3 +macs = mac_alg1, mac_alg2, mac_alg3''' + + policy = self.Policy(policy_data=policy_data) + assert str(policy) == "Name: [Test Policy]\nVersion: [1]\nBanner: {undefined}\nCompressions: comp_alg1\nHost Keys: key_alg1\nOptional Host Keys: {undefined}\nKey Exchanges: kex_alg1, kex_alg2\nCiphers: cipher_alg1, cipher_alg2, cipher_alg3\nMACs: mac_alg1, mac_alg2, mac_alg3\nHost Key Sizes: {undefined}\nCA Key Sizes: {undefined}\nDH Modulus Sizes: {undefined}\nServer Policy: True" + + + def test_policy_invalid_1(self): + '''Basic policy, but with 'ciphersx' instead of 'ciphers'.''' + + policy_data = '''# This is a comment +name = "Test Policy" +version = 1 + +compressions = comp_alg1 +host keys = key_alg1 +key exchanges = kex_alg1, kex_alg2 +ciphersx = cipher_alg1, cipher_alg2, cipher_alg3 +macs = mac_alg1, mac_alg2, mac_alg3''' + + failed = False + try: + self.Policy(policy_data=policy_data) + except ValueError: + failed = True + + assert failed, "Invalid policy did not cause Policy object to throw exception" + + + def test_policy_invalid_2(self): + '''Basic policy, but is missing the required name field.''' + + policy_data = '''# This is a comment +#name = "Test Policy" +version = 1 + +compressions = comp_alg1 +host keys = key_alg1 +key exchanges = kex_alg1, kex_alg2 +ciphers = cipher_alg1, cipher_alg2, cipher_alg3 +macs = mac_alg1, mac_alg2, mac_alg3''' + + failed = False + try: + self.Policy(policy_data=policy_data) + except ValueError: + failed = True + + assert failed, "Invalid policy did not cause Policy object to throw exception" + + + def test_policy_invalid_3(self): + '''Basic policy, but is missing the required version field.''' + + policy_data = '''# This is a comment +name = "Test Policy" +#version = 1 + +compressions = comp_alg1 +host keys = key_alg1 +key exchanges = kex_alg1, kex_alg2 +ciphers = cipher_alg1, cipher_alg2, cipher_alg3 +macs = mac_alg1, mac_alg2, mac_alg3''' + + failed = False + try: + self.Policy(policy_data=policy_data) + except ValueError: + failed = True + + assert failed, "Invalid policy did not cause Policy object to throw exception" + + + def test_policy_invalid_4(self): + '''Basic policy, but is missing quotes in the name field.''' + + policy_data = '''# This is a comment +name = Test Policy +version = 1 + +compressions = comp_alg1 +host keys = key_alg1 +key exchanges = kex_alg1, kex_alg2 +ciphers = cipher_alg1, cipher_alg2, cipher_alg3 +macs = mac_alg1, mac_alg2, mac_alg3''' + + failed = False + try: + self.Policy(policy_data=policy_data) + except ValueError: + failed = True + + assert failed, "Invalid policy did not cause Policy object to throw exception" + + + def test_policy_invalid_5(self): + '''Basic policy, but is missing quotes in the banner field.''' + + policy_data = '''# This is a comment +name = "Test Policy" +version = 1 + +banner = 0mg +compressions = comp_alg1 +host keys = key_alg1 +key exchanges = kex_alg1, kex_alg2 +ciphers = cipher_alg1, cipher_alg2, cipher_alg3 +macs = mac_alg1, mac_alg2, mac_alg3''' + + failed = False + try: + self.Policy(policy_data=policy_data) + except ValueError: + failed = True + + assert failed, "Invalid policy did not cause Policy object to throw exception" + + + def test_policy_invalid_6(self): + '''Basic policy, but is missing quotes in the header field.''' + + policy_data = '''# This is a comment +name = "Test Policy" +version = 1 + +header = 0mg +compressions = comp_alg1 +host keys = key_alg1 +key exchanges = kex_alg1, kex_alg2 +ciphers = cipher_alg1, cipher_alg2, cipher_alg3 +macs = mac_alg1, mac_alg2, mac_alg3''' + + failed = False + try: + self.Policy(policy_data=policy_data) + except ValueError: + failed = True + + assert failed, "Invalid policy did not cause Policy object to throw exception" + + + def test_policy_create_1(self): + '''Creates a policy from a kex and ensures it is generated exactly as expected.''' + + kex = self._get_kex() + pol_data = self.Policy.create('www.l0l.com', 'bannerX', kex, False) + + # Today's date is embedded in the policy, so filter it out to get repeatable results. + pol_data = pol_data.replace(date.today().strftime('%Y/%m/%d'), '[todays date]') + + # Instead of writing out the entire expected policy--line by line--just check that it has the expected hash. + assert hashlib.sha256(pol_data.encode('ascii')).hexdigest() == '4af7777fb57a1dad0cf438c899a11d4f625fd9276ea3bb5ef5c9fe8806cb47dc' + + + def test_policy_evaluate_passing_1(self): + '''Creates a policy and evaluates it against the same server''' + + kex = self._get_kex() + policy_data = self.Policy.create('www.l0l.com', None, kex, False) + policy = self.Policy(policy_data=policy_data) + + ret, errors, error_str = policy.evaluate('SSH Server 1.0', kex) + assert ret is True + assert len(errors) == 0 + print(error_str) + assert len(error_str) == 0 + + + def test_policy_evaluate_failing_1(self): + '''Ensure that a policy with a specified banner fails against a server with a different banner''' + + policy_data = '''name = "Test Policy" +version = 1 +banner = "XXX mismatched banner XXX" +compressions = comp_alg1, comp_alg2 +host keys = key_alg1, key_alg2 +key exchanges = kex_alg1, kex_alg2 +ciphers = cipher_alg1, cipher_alg2, cipher_alg3 +macs = mac_alg1, mac_alg2, mac_alg3''' + + policy = self.Policy(policy_data=policy_data) + ret, errors, error_str = policy.evaluate('SSH Server 1.0', self._get_kex()) + assert ret is False + assert len(errors) == 1 + assert error_str.find('Banner did not match.') != -1 + + + def test_policy_evaluate_failing_2(self): + '''Ensure that a mismatched compressions list results in a failure''' + + policy_data = '''name = "Test Policy" +version = 1 +compressions = XXXmismatchedXXX, comp_alg1, comp_alg2 +host keys = key_alg1, key_alg2 +key exchanges = kex_alg1, kex_alg2 +ciphers = cipher_alg1, cipher_alg2, cipher_alg3 +macs = mac_alg1, mac_alg2, mac_alg3''' + + policy = self.Policy(policy_data=policy_data) + ret, errors, error_str = policy.evaluate('SSH Server 1.0', self._get_kex()) + assert ret is False + assert len(errors) == 1 + assert error_str.find('Compression did not match.') != -1 + + + def test_policy_evaluate_failing_3(self): + '''Ensure that a mismatched host keys results in a failure''' + + policy_data = '''name = "Test Policy" +version = 1 +compressions = comp_alg1, comp_alg2 +host keys = XXXmismatchedXXX, key_alg1, key_alg2 +key exchanges = kex_alg1, kex_alg2 +ciphers = cipher_alg1, cipher_alg2, cipher_alg3 +macs = mac_alg1, mac_alg2, mac_alg3''' + + policy = self.Policy(policy_data=policy_data) + ret, errors, error_str = policy.evaluate('SSH Server 1.0', self._get_kex()) + assert ret is False + assert len(errors) == 1 + assert error_str.find('Host keys did not match.') != -1 + + + def test_policy_evaluate_failing_4(self): + '''Ensure that a mismatched key exchange list results in a failure''' + + policy_data = '''name = "Test Policy" +version = 1 +compressions = comp_alg1, comp_alg2 +host keys = key_alg1, key_alg2 +key exchanges = XXXmismatchedXXX, kex_alg1, kex_alg2 +ciphers = cipher_alg1, cipher_alg2, cipher_alg3 +macs = mac_alg1, mac_alg2, mac_alg3''' + + policy = self.Policy(policy_data=policy_data) + ret, errors, error_str = policy.evaluate('SSH Server 1.0', self._get_kex()) + assert ret is False + assert len(errors) == 1 + assert error_str.find('Key exchanges did not match.') != -1 + + + def test_policy_evaluate_failing_5(self): + '''Ensure that a mismatched cipher list results in a failure''' + + policy_data = '''name = "Test Policy" +version = 1 +compressions = comp_alg1, comp_alg2 +host keys = key_alg1, key_alg2 +key exchanges = kex_alg1, kex_alg2 +ciphers = cipher_alg1, XXXmismatched, cipher_alg2, cipher_alg3 +macs = mac_alg1, mac_alg2, mac_alg3''' + + policy = self.Policy(policy_data=policy_data) + ret, errors, error_str = policy.evaluate('SSH Server 1.0', self._get_kex()) + assert ret is False + assert len(errors) == 1 + assert error_str.find('Ciphers did not match.') != -1 + + + def test_policy_evaluate_failing_6(self): + '''Ensure that a mismatched MAC list results in a failure''' + + policy_data = '''name = "Test Policy" +version = 1 +compressions = comp_alg1, comp_alg2 +host keys = key_alg1, key_alg2 +key exchanges = kex_alg1, kex_alg2 +ciphers = cipher_alg1, cipher_alg2, cipher_alg3 +macs = mac_alg1, mac_alg2, XXXmismatched, mac_alg3''' + + policy = self.Policy(policy_data=policy_data) + ret, errors, error_str = policy.evaluate('SSH Server 1.0', self._get_kex()) + assert ret is False + assert len(errors) == 1 + assert error_str.find('MACs did not match.') != -1 + + + def test_policy_evaluate_failing_7(self): + '''Ensure that a mismatched host keys and MACs results in a failure''' + + policy_data = '''name = "Test Policy" +version = 1 +compressions = comp_alg1, comp_alg2 +host keys = key_alg1, key_alg2, XXXmismatchedXXX +key exchanges = kex_alg1, kex_alg2 +ciphers = cipher_alg1, cipher_alg2, cipher_alg3 +macs = mac_alg1, mac_alg2, XXXmismatchedXXX, mac_alg3''' + + policy = self.Policy(policy_data=policy_data) + ret, errors, error_str = policy.evaluate('SSH Server 1.0', self._get_kex()) + assert ret is False + assert len(errors) == 2 + assert error_str.find('Host keys did not match.') != -1 + assert error_str.find('MACs did not match.') != -1 diff --git a/test/test_resolve.py b/test/test_resolve.py new file mode 100644 index 0000000..fbaa033 --- /dev/null +++ b/test/test_resolve.py @@ -0,0 +1,81 @@ +import socket +import pytest + + +# pylint: disable=attribute-defined-outside-init,protected-access +class TestResolve: + @pytest.fixture(autouse=True) + def init(self, ssh_audit): + self.AuditConf = ssh_audit.AuditConf + self.audit = ssh_audit.audit + self.OutputBuffer = ssh_audit.OutputBuffer + self.ssh_socket = ssh_audit.SSH_Socket + + def _conf(self): + conf = self.AuditConf('localhost', 22) + conf.colors = False + conf.batch = True + return conf + + def test_resolve_error(self, output_spy, virtual_socket): + vsocket = virtual_socket + vsocket.gsock.addrinfodata['localhost#22'] = socket.gaierror(8, 'hostname nor servname provided, or not known') + conf = self._conf() + s = self.ssh_socket(self.OutputBuffer(), 'localhost', 22, conf.ip_version_preference) + output_spy.begin() + with pytest.raises(SystemExit): + list(s._resolve()) + lines = output_spy.flush() + assert len(lines) == 1 + assert 'hostname nor servname provided' in lines[-1] + + def test_resolve_hostname_without_records(self, output_spy, virtual_socket): + vsocket = virtual_socket + vsocket.gsock.addrinfodata['localhost#22'] = [] + conf = self._conf() + s = self.ssh_socket(self.OutputBuffer(), 'localhost', 22, conf.ip_version_preference) + output_spy.begin() + r = list(s._resolve()) + assert len(r) == 0 + + def test_resolve_ipv4(self, virtual_socket): + conf = self._conf() + conf.ipv4 = True + s = self.ssh_socket(self.OutputBuffer(), 'localhost', 22, conf.ip_version_preference) + r = list(s._resolve()) + assert len(r) == 1 + assert r[0] == (socket.AF_INET, ('127.0.0.1', 22)) + + def test_resolve_ipv6(self, virtual_socket): + conf = self._conf() + conf.ipv6 = True + s = self.ssh_socket(self.OutputBuffer(), 'localhost', 22, conf.ip_version_preference) + r = list(s._resolve()) + assert len(r) == 1 + assert r[0] == (socket.AF_INET6, ('::1', 22)) + + def test_resolve_ipv46_both(self, virtual_socket): + conf = self._conf() + s = self.ssh_socket(self.OutputBuffer(), 'localhost', 22, conf.ip_version_preference) + r = list(s._resolve()) + assert len(r) == 2 + assert r[0] == (socket.AF_INET, ('127.0.0.1', 22)) + assert r[1] == (socket.AF_INET6, ('::1', 22)) + + def test_resolve_ipv46_order(self, virtual_socket): + conf = self._conf() + conf.ipv4 = True + conf.ipv6 = True + s = self.ssh_socket(self.OutputBuffer(), 'localhost', 22, conf.ip_version_preference) + r = list(s._resolve()) + assert len(r) == 2 + assert r[0] == (socket.AF_INET, ('127.0.0.1', 22)) + assert r[1] == (socket.AF_INET6, ('::1', 22)) + conf = self._conf() + conf.ipv6 = True + conf.ipv4 = True + s = self.ssh_socket(self.OutputBuffer(), 'localhost', 22, conf.ip_version_preference) + r = list(s._resolve()) + assert len(r) == 2 + assert r[0] == (socket.AF_INET6, ('::1', 22)) + assert r[1] == (socket.AF_INET, ('127.0.0.1', 22)) diff --git a/test/test_socket.py b/test/test_socket.py new file mode 100644 index 0000000..9569768 --- /dev/null +++ b/test/test_socket.py @@ -0,0 +1,42 @@ +import pytest + +from ssh_audit.outputbuffer import OutputBuffer +from ssh_audit.ssh_socket import SSH_Socket + + +# pylint: disable=attribute-defined-outside-init +class TestSocket: + @pytest.fixture(autouse=True) + def init(self, ssh_audit): + self.OutputBuffer = OutputBuffer + self.ssh_socket = SSH_Socket + + def test_invalid_host(self, virtual_socket): + with pytest.raises(ValueError): + self.ssh_socket(self.OutputBuffer(), None, 22) + + def test_invalid_port(self, virtual_socket): + with pytest.raises(ValueError): + self.ssh_socket(self.OutputBuffer(), 'localhost', 'abc') + with pytest.raises(ValueError): + self.ssh_socket(self.OutputBuffer(), 'localhost', -1) + with pytest.raises(ValueError): + self.ssh_socket(self.OutputBuffer(), 'localhost', 0) + with pytest.raises(ValueError): + self.ssh_socket(self.OutputBuffer(), 'localhost', 65536) + + def test_not_connected_socket(self, virtual_socket): + sock = self.ssh_socket(self.OutputBuffer(), 'localhost', 22) + banner, header, err = sock.get_banner() + assert banner is None + assert len(header) == 0 + assert err == 'not connected' + s, e = sock.recv() + assert s == -1 + assert e == 'not connected' + s, e = sock.send('nothing') + assert s == -1 + assert e == 'not connected' + s, e = sock.send_packet() + assert s == -1 + assert e == 'not connected' diff --git a/test/test_software.py b/test/test_software.py new file mode 100644 index 0000000..0240ffc --- /dev/null +++ b/test/test_software.py @@ -0,0 +1,289 @@ +import pytest + +from ssh_audit.banner import Banner +from ssh_audit.software import Software + + +# pylint: disable=line-too-long,attribute-defined-outside-init +class TestSoftware: + @pytest.fixture(autouse=True) + def init(self, ssh_audit): + self.software = Software + self.banner = Banner + + def test_unknown_software(self): + ps = lambda x: self.software.parse(self.banner.parse(x)) # noqa + assert ps('SSH-1.5') is None + assert ps('SSH-1.99-AlfaMegaServer') is None + assert ps('SSH-2.0-BetaMegaServer 0.0.1') is None + + def test_openssh_software(self): + # pylint: disable=too-many-statements + ps = lambda x: self.software.parse(self.banner.parse(x)) # noqa + # common + s = ps('SSH-2.0-OpenSSH_7.3') + assert s.vendor is None + assert s.product == 'OpenSSH' + assert s.version == '7.3' + assert s.patch is None + assert s.os is None + assert str(s) == 'OpenSSH 7.3' + assert str(s) == s.display() + assert s.display(True) == str(s) + assert s.display(False) == str(s) + assert repr(s) == '<Software(product=OpenSSH, version=7.3)>' + # common, portable + s = ps('SSH-2.0-OpenSSH_7.2p1') + assert s.vendor is None + assert s.product == 'OpenSSH' + assert s.version == '7.2' + assert s.patch == 'p1' + assert s.os is None + assert str(s) == 'OpenSSH 7.2p1' + assert str(s) == s.display() + assert s.display(True) == str(s) + assert s.display(False) == 'OpenSSH 7.2' + assert repr(s) == '<Software(product=OpenSSH, version=7.2, patch=p1)>' + # dot instead of underline + s = ps('SSH-2.0-OpenSSH.6.6') + assert s.vendor is None + assert s.product == 'OpenSSH' + assert s.version == '6.6' + assert s.patch is None + assert s.os is None + assert str(s) == 'OpenSSH 6.6' + assert str(s) == s.display() + assert s.display(True) == str(s) + assert s.display(False) == str(s) + assert repr(s) == '<Software(product=OpenSSH, version=6.6)>' + # dash instead of underline + s = ps('SSH-2.0-OpenSSH-3.9p1') + assert s.vendor is None + assert s.product == 'OpenSSH' + assert s.version == '3.9' + assert s.patch == 'p1' + assert s.os is None + assert str(s) == 'OpenSSH 3.9p1' + assert str(s) == s.display() + assert s.display(True) == str(s) + assert s.display(False) == 'OpenSSH 3.9' + assert repr(s) == '<Software(product=OpenSSH, version=3.9, patch=p1)>' + # patch prefix with dash + s = ps('SSH-2.0-OpenSSH_7.2-hpn14v5') + assert s.vendor is None + assert s.product == 'OpenSSH' + assert s.version == '7.2' + assert s.patch == 'hpn14v5' + assert s.os is None + assert str(s) == 'OpenSSH 7.2 (hpn14v5)' + assert str(s) == s.display() + assert s.display(True) == str(s) + assert s.display(False) == 'OpenSSH 7.2' + assert repr(s) == '<Software(product=OpenSSH, version=7.2, patch=hpn14v5)>' + # patch prefix with underline + s = ps('SSH-1.5-OpenSSH_6.6.1_hpn13v11') + assert s.vendor is None + assert s.product == 'OpenSSH' + assert s.version == '6.6.1' + assert s.patch == 'hpn13v11' + assert s.os is None + assert str(s) == 'OpenSSH 6.6.1 (hpn13v11)' + assert str(s) == s.display() + assert s.display(True) == str(s) + assert s.display(False) == 'OpenSSH 6.6.1' + assert repr(s) == '<Software(product=OpenSSH, version=6.6.1, patch=hpn13v11)>' + # patch prefix with dot + s = ps('SSH-2.0-OpenSSH_5.9.CASPUR') + assert s.vendor is None + assert s.product == 'OpenSSH' + assert s.version == '5.9' + assert s.patch == 'CASPUR' + assert s.os is None + assert str(s) == 'OpenSSH 5.9 (CASPUR)' + assert str(s) == s.display() + assert s.display(True) == str(s) + assert s.display(False) == 'OpenSSH 5.9' + assert repr(s) == '<Software(product=OpenSSH, version=5.9, patch=CASPUR)>' + + def test_dropbear_software(self): + ps = lambda x: self.software.parse(self.banner.parse(x)) # noqa + # common + s = ps('SSH-2.0-dropbear_2016.74') + assert s.vendor is None + assert s.product == 'Dropbear SSH' + assert s.version == '2016.74' + assert s.patch is None + assert s.os is None + assert str(s) == 'Dropbear SSH 2016.74' + assert str(s) == s.display() + assert s.display(True) == str(s) + assert s.display(False) == str(s) + assert repr(s) == '<Software(product=Dropbear SSH, version=2016.74)>' + # common, patch + s = ps('SSH-2.0-dropbear_0.44test4') + assert s.vendor is None + assert s.product == 'Dropbear SSH' + assert s.version == '0.44' + assert s.patch == 'test4' + assert s.os is None + assert str(s) == 'Dropbear SSH 0.44 (test4)' + assert str(s) == s.display() + assert s.display(True) == str(s) + assert s.display(False) == 'Dropbear SSH 0.44' + assert repr(s) == '<Software(product=Dropbear SSH, version=0.44, patch=test4)>' + # patch prefix with dash + s = ps('SSH-2.0-dropbear_0.44-Freesco-p49') + assert s.vendor is None + assert s.product == 'Dropbear SSH' + assert s.version == '0.44' + assert s.patch == 'Freesco-p49' + assert s.os is None + assert str(s) == 'Dropbear SSH 0.44 (Freesco-p49)' + assert str(s) == s.display() + assert s.display(True) == str(s) + assert s.display(False) == 'Dropbear SSH 0.44' + assert repr(s) == '<Software(product=Dropbear SSH, version=0.44, patch=Freesco-p49)>' + # patch prefix with underline + s = ps('SSH-2.0-dropbear_2014.66_agbn_1') + assert s.vendor is None + assert s.product == 'Dropbear SSH' + assert s.version == '2014.66' + assert s.patch == 'agbn_1' + assert s.os is None + assert str(s) == 'Dropbear SSH 2014.66 (agbn_1)' + assert str(s) == s.display() + assert s.display(True) == str(s) + assert s.display(False) == 'Dropbear SSH 2014.66' + assert repr(s) == '<Software(product=Dropbear SSH, version=2014.66, patch=agbn_1)>' + + def test_libssh_software(self): + ps = lambda x: self.software.parse(self.banner.parse(x)) # noqa + # common + s = ps('SSH-2.0-libssh-0.2') + assert s.vendor is None + assert s.product == 'libssh' + assert s.version == '0.2' + assert s.patch is None + assert s.os is None + assert str(s) == 'libssh 0.2' + assert str(s) == s.display() + assert s.display(True) == str(s) + assert s.display(False) == str(s) + assert repr(s) == '<Software(product=libssh, version=0.2)>' + s = ps('SSH-2.0-libssh-0.7.4') + assert s.vendor is None + assert s.product == 'libssh' + assert s.version == '0.7.4' + assert s.patch is None + assert s.os is None + assert str(s) == 'libssh 0.7.4' + assert str(s) == s.display() + assert s.display(True) == str(s) + assert s.display(False) == str(s) + assert repr(s) == '<Software(product=libssh, version=0.7.4)>' + + def test_romsshell_software(self): + ps = lambda x: self.software.parse(self.banner.parse(x)) # noqa + # common + s = ps('SSH-2.0-RomSShell_5.40') + assert s.vendor == 'Allegro Software' + assert s.product == 'RomSShell' + assert s.version == '5.40' + assert s.patch is None + assert s.os is None + assert str(s) == 'Allegro Software RomSShell 5.40' + assert str(s) == s.display() + assert s.display(True) == str(s) + assert s.display(False) == str(s) + assert repr(s) == '<Software(vendor=Allegro Software, product=RomSShell, version=5.40)>' + + def test_hp_ilo_software(self): + ps = lambda x: self.software.parse(self.banner.parse(x)) # noqa + # common + s = ps('SSH-2.0-mpSSH_0.2.1') + assert s.vendor == 'HP' + assert s.product == 'iLO (Integrated Lights-Out) sshd' + assert s.version == '0.2.1' + assert s.patch is None + assert s.os is None + assert str(s) == 'HP iLO (Integrated Lights-Out) sshd 0.2.1' + assert str(s) == s.display() + assert s.display(True) == str(s) + assert s.display(False) == str(s) + assert repr(s) == '<Software(vendor=HP, product=iLO (Integrated Lights-Out) sshd, version=0.2.1)>' + + def test_cisco_software(self): + ps = lambda x: self.software.parse(self.banner.parse(x)) # noqa + # common + s = ps('SSH-1.5-Cisco-1.25') + assert s.vendor == 'Cisco' + assert s.product == 'IOS/PIX sshd' + assert s.version == '1.25' + assert s.patch is None + assert s.os is None + assert str(s) == 'Cisco IOS/PIX sshd 1.25' + assert str(s) == s.display() + assert s.display(True) == str(s) + assert s.display(False) == str(s) + assert repr(s) == '<Software(vendor=Cisco, product=IOS/PIX sshd, version=1.25)>' + + def test_software_os(self): + ps = lambda x: self.software.parse(self.banner.parse(x)) # noqa + # unknown + s = ps('SSH-2.0-OpenSSH_3.7.1 MegaOperatingSystem 123') + assert s.os is None + # NetBSD + s = ps('SSH-1.99-OpenSSH_2.5.1 NetBSD_Secure_Shell-20010614') + assert s.os == 'NetBSD (2001-06-14)' + assert str(s) == 'OpenSSH 2.5.1 running on NetBSD (2001-06-14)' + assert repr(s) == '<Software(product=OpenSSH, version=2.5.1, os=NetBSD (2001-06-14))>' + s = ps('SSH-1.99-OpenSSH_5.0 NetBSD_Secure_Shell-20080403+-hpn13v1') + assert s.os == 'NetBSD (2008-04-03)' + assert str(s) == 'OpenSSH 5.0 running on NetBSD (2008-04-03)' + assert repr(s) == '<Software(product=OpenSSH, version=5.0, os=NetBSD (2008-04-03))>' + s = ps('SSH-2.0-OpenSSH_6.6.1_hpn13v11 NetBSD-20100308') + assert s.os == 'NetBSD (2010-03-08)' + assert str(s) == 'OpenSSH 6.6.1 (hpn13v11) running on NetBSD (2010-03-08)' + assert repr(s) == '<Software(product=OpenSSH, version=6.6.1, patch=hpn13v11, os=NetBSD (2010-03-08))>' + s = ps('SSH-2.0-OpenSSH_4.4 NetBSD') + assert s.os == 'NetBSD' + assert str(s) == 'OpenSSH 4.4 running on NetBSD' + assert repr(s) == '<Software(product=OpenSSH, version=4.4, os=NetBSD)>' + s = ps('SSH-2.0-OpenSSH_3.0.2 NetBSD Secure Shell') + assert s.os == 'NetBSD' + assert str(s) == 'OpenSSH 3.0.2 running on NetBSD' + assert repr(s) == '<Software(product=OpenSSH, version=3.0.2, os=NetBSD)>' + # FreeBSD + s = ps('SSH-2.0-OpenSSH_7.2 FreeBSD-20160310') + assert s.os == 'FreeBSD (2016-03-10)' + assert str(s) == 'OpenSSH 7.2 running on FreeBSD (2016-03-10)' + assert repr(s) == '<Software(product=OpenSSH, version=7.2, os=FreeBSD (2016-03-10))>' + s = ps('SSH-1.99-OpenSSH_2.9 FreeBSD localisations 20020307') + assert s.os == 'FreeBSD (2002-03-07)' + assert str(s) == 'OpenSSH 2.9 running on FreeBSD (2002-03-07)' + assert repr(s) == '<Software(product=OpenSSH, version=2.9, os=FreeBSD (2002-03-07))>' + s = ps('SSH-2.0-OpenSSH_2.3.0 green@FreeBSD.org 20010321') + assert s.os == 'FreeBSD (2001-03-21)' + assert str(s) == 'OpenSSH 2.3.0 running on FreeBSD (2001-03-21)' + assert repr(s) == '<Software(product=OpenSSH, version=2.3.0, os=FreeBSD (2001-03-21))>' + s = ps('SSH-1.99-OpenSSH_4.4p1 FreeBSD-openssh-portable-overwrite-base-4.4.p1_1,1') + assert s.os == 'FreeBSD' + assert str(s) == 'OpenSSH 4.4p1 running on FreeBSD' + assert repr(s) == '<Software(product=OpenSSH, version=4.4, patch=p1, os=FreeBSD)>' + s = ps('SSH-2.0-OpenSSH_7.2-OVH-rescue FreeBSD') + assert s.os == 'FreeBSD' + assert str(s) == 'OpenSSH 7.2 (OVH-rescue) running on FreeBSD' + assert repr(s) == '<Software(product=OpenSSH, version=7.2, patch=OVH-rescue, os=FreeBSD)>' + # Windows + s = ps('SSH-2.0-OpenSSH_3.7.1 in RemotelyAnywhere 5.21.422') + assert s.os == 'Microsoft Windows (RemotelyAnywhere 5.21.422)' + assert str(s) == 'OpenSSH 3.7.1 running on Microsoft Windows (RemotelyAnywhere 5.21.422)' + assert repr(s) == '<Software(product=OpenSSH, version=3.7.1, os=Microsoft Windows (RemotelyAnywhere 5.21.422))>' + s = ps('SSH-2.0-OpenSSH_3.8 in DesktopAuthority 7.1.091') + assert s.os == 'Microsoft Windows (DesktopAuthority 7.1.091)' + assert str(s) == 'OpenSSH 3.8 running on Microsoft Windows (DesktopAuthority 7.1.091)' + assert repr(s) == '<Software(product=OpenSSH, version=3.8, os=Microsoft Windows (DesktopAuthority 7.1.091))>' + s = ps('SSH-2.0-OpenSSH_3.8 in RemoteSupportManager 1.0.023') + assert s.os == 'Microsoft Windows (RemoteSupportManager 1.0.023)' + assert str(s) == 'OpenSSH 3.8 running on Microsoft Windows (RemoteSupportManager 1.0.023)' + assert repr(s) == '<Software(product=OpenSSH, version=3.8, os=Microsoft Windows (RemoteSupportManager 1.0.023))>' diff --git a/test/test_ssh1.py b/test/test_ssh1.py new file mode 100644 index 0000000..d40c157 --- /dev/null +++ b/test/test_ssh1.py @@ -0,0 +1,173 @@ +import struct +import pytest + +from ssh_audit.auditconf import AuditConf +from ssh_audit.fingerprint import Fingerprint +from ssh_audit.outputbuffer import OutputBuffer +from ssh_audit.protocol import Protocol +from ssh_audit.readbuf import ReadBuf +from ssh_audit.ssh1 import SSH1 +from ssh_audit.ssh1_publickeymessage import SSH1_PublicKeyMessage +from ssh_audit.ssh_audit import audit +from ssh_audit.writebuf import WriteBuf + + +# pylint: disable=line-too-long,attribute-defined-outside-init +class TestSSH1: + @pytest.fixture(autouse=True) + def init(self, ssh_audit): + self.OutputBuffer = OutputBuffer + self.protocol = Protocol + self.ssh1 = SSH1 + self.PublicKeyMessage = SSH1_PublicKeyMessage + self.rbuf = ReadBuf + self.wbuf = WriteBuf + self.audit = audit + self.AuditConf = AuditConf + self.fingerprint = Fingerprint + + def _conf(self): + conf = self.AuditConf('localhost', 22) + conf.colors = False + conf.batch = True + conf.verbose = True + conf.ssh1 = True + conf.ssh2 = False + return conf + + def _create_ssh1_packet(self, payload, valid_crc=True): + padding = -(len(payload) + 4) % 8 + plen = len(payload) + 4 + pad_bytes = b'\x00' * padding + cksum = self.ssh1.crc32(pad_bytes + payload) if valid_crc else 0 + data = struct.pack('>I', plen) + pad_bytes + payload + struct.pack('>I', cksum) + return data + + @classmethod + def _server_key(cls): + return (1024, 0x10001, 0xee6552da432e0ac2c422df1a51287507748bfe3b5e3e4fa989a8f49fdc163a17754939ef18ef8a667ea3b71036a151fcd7f5e01ceef1e4439864baf3ac569047582c69d6c128212e0980dcb3168f00d371004039983f6033cd785b8b8f85096c7d9405cbfdc664e27c966356a6b4eb6ee20ad43414b50de18b22829c1880b551) + + @classmethod + def _host_key(cls): + return (2048, 0x10001, 0xdfa20cd2a530ccc8c870aa60d9feb3b35deeab81c3215a96557abbd683d21f4600f38e475d87100da9a4404220eeb3bb5584e5a2b5b48ffda58530ea19104a32577d7459d91e76aa711b241050f4cc6d5327ccce254f371acad3be56d46eb5919b73f20dbdb1177b700f00891c5bf4ed128bb90ed541b778288285bcfa28432ab5cbcb8321b6e24760e998e0daa519f093a631e44276d7dd252ce0c08c75e2ab28a7349ead779f97d0f20a6d413bf3623cd216dc35375f6366690bcc41e3b2d5465840ec7ee0dc7e3f1c101d674a0c7dbccbc3942788b111396add2f8153b46a0e4b50d66e57ee92958f1c860dd97cc0e40e32febff915343ed53573142bdf4b) + + def _pkm_payload(self): + w = self.wbuf() + w.write(b'\x88\x99\xaa\xbb\xcc\xdd\xee\xff') + b, e, m = self._server_key() + w.write_int(b).write_mpint1(e).write_mpint1(m) + b, e, m = self._host_key() + w.write_int(b).write_mpint1(e).write_mpint1(m) + w.write_int(2) + w.write_int(72) + w.write_int(36) + return w.write_flush() + + def test_crc32(self): + assert self.ssh1.crc32(b'') == 0x00 + assert self.ssh1.crc32(b'The quick brown fox jumps over the lazy dog') == 0xb9c60808 + + def test_fingerprint(self): + # pylint: disable=protected-access + b, e, m = self._host_key() + fpd = self.wbuf._create_mpint(m, False) + fpd += self.wbuf._create_mpint(e, False) + fp = self.fingerprint(fpd) + assert b == 2048 + assert fp.md5 == 'MD5:9d:26:f8:39:fc:20:9d:9b:ca:cc:4a:0f:e1:93:f5:96' + assert fp.sha256 == 'SHA256:vZdx3mhzbvVJmn08t/ruv8WDhJ9jfKYsCTuSzot+QIs' + + def _assert_pkm_keys(self, pkm, skey, hkey): + b, e, m = skey + assert pkm.server_key_bits == b + assert pkm.server_key_public_exponent == e + assert pkm.server_key_public_modulus == m + b, e, m = hkey + assert pkm.host_key_bits == b + assert pkm.host_key_public_exponent == e + assert pkm.host_key_public_modulus == m + + def _assert_pkm_fields(self, pkm, skey, hkey): + assert pkm is not None + assert pkm.cookie == b'\x88\x99\xaa\xbb\xcc\xdd\xee\xff' + self._assert_pkm_keys(pkm, skey, hkey) + assert pkm.protocol_flags == 2 + assert pkm.supported_ciphers_mask == 72 + assert pkm.supported_ciphers == ['3des', 'blowfish'] + assert pkm.supported_authentications_mask == 36 + assert pkm.supported_authentications == ['rsa', 'tis'] + fp = self.fingerprint(pkm.host_key_fingerprint_data) + assert fp.md5 == 'MD5:9d:26:f8:39:fc:20:9d:9b:ca:cc:4a:0f:e1:93:f5:96' + assert fp.sha256 == 'SHA256:vZdx3mhzbvVJmn08t/ruv8WDhJ9jfKYsCTuSzot+QIs' + + def test_pkm_init(self): + cookie = b'\x88\x99\xaa\xbb\xcc\xdd\xee\xff' + pflags, cmask, amask = 2, 72, 36 + skey, hkey = self._server_key(), self._host_key() + pkm = self.PublicKeyMessage(cookie, skey, hkey, pflags, cmask, amask) + self._assert_pkm_fields(pkm, skey, hkey) + for skey2 in ([], [0], [0, 1], [0, 1, 2, 3]): + with pytest.raises(ValueError): + pkm = self.PublicKeyMessage(cookie, skey2, hkey, pflags, cmask, amask) + for hkey2 in ([], [0], [0, 1], [0, 1, 2, 3]): + with pytest.raises(ValueError): + print(hkey2) + pkm = self.PublicKeyMessage(cookie, skey, hkey2, pflags, cmask, amask) + + def test_pkm_read(self): + pkm = self.PublicKeyMessage.parse(self._pkm_payload()) + self._assert_pkm_fields(pkm, self._server_key(), self._host_key()) + + def test_pkm_payload(self): + cookie = b'\x88\x99\xaa\xbb\xcc\xdd\xee\xff' + skey, hkey = self._server_key(), self._host_key() + pflags, cmask, amask = 2, 72, 36 + pkm1 = self.PublicKeyMessage(cookie, skey, hkey, pflags, cmask, amask) + pkm2 = self.PublicKeyMessage.parse(self._pkm_payload()) + assert pkm1.payload == pkm2.payload + + def test_ssh1_server_simple(self, output_spy, virtual_socket): + vsocket = virtual_socket + w = self.wbuf() + w.write_byte(self.protocol.SMSG_PUBLIC_KEY) + w.write(self._pkm_payload()) + vsocket.rdata.append(b'SSH-1.5-OpenSSH_7.2 ssh-audit-test\r\n') + vsocket.rdata.append(self._create_ssh1_packet(w.write_flush())) + output_spy.begin() + out = self.OutputBuffer() + self.audit(out, self._conf()) + out.write() + lines = output_spy.flush() + assert len(lines) == 17 + + def test_ssh1_server_invalid_first_packet(self, output_spy, virtual_socket): + vsocket = virtual_socket + w = self.wbuf() + w.write_byte(self.protocol.SMSG_PUBLIC_KEY + 1) + w.write(self._pkm_payload()) + vsocket.rdata.append(b'SSH-1.5-OpenSSH_7.2 ssh-audit-test\r\n') + vsocket.rdata.append(self._create_ssh1_packet(w.write_flush())) + output_spy.begin() + out = self.OutputBuffer() + ret = self.audit(out, self._conf()) + out.write() + assert ret != 0 + lines = output_spy.flush() + assert len(lines) == 10 + assert 'unknown message' in lines[-1] + + def test_ssh1_server_invalid_checksum(self, output_spy, virtual_socket): + vsocket = virtual_socket + w = self.wbuf() + w.write_byte(self.protocol.SMSG_PUBLIC_KEY + 1) + w.write(self._pkm_payload()) + vsocket.rdata.append(b'SSH-1.5-OpenSSH_7.2 ssh-audit-test\r\n') + vsocket.rdata.append(self._create_ssh1_packet(w.write_flush(), False)) + output_spy.begin() + out = self.OutputBuffer() + with pytest.raises(SystemExit): + self.audit(out, self._conf()) + out.write() + lines = output_spy.flush() + assert len(lines) == 3 + assert ('checksum' in lines[0]) or ('checksum' in lines[1]) or ('checksum' in lines[2]) diff --git a/test/test_ssh2.py b/test/test_ssh2.py new file mode 100644 index 0000000..fc4c0fa --- /dev/null +++ b/test/test_ssh2.py @@ -0,0 +1,165 @@ +import os +import struct +import pytest + +from ssh_audit.auditconf import AuditConf +from ssh_audit.outputbuffer import OutputBuffer +from ssh_audit.protocol import Protocol +from ssh_audit.readbuf import ReadBuf +from ssh_audit.ssh2_kex import SSH2_Kex +from ssh_audit.ssh2_kexparty import SSH2_KexParty +from ssh_audit.ssh_audit import audit +from ssh_audit.writebuf import WriteBuf + + +# pylint: disable=line-too-long,attribute-defined-outside-init +class TestSSH2: + @pytest.fixture(autouse=True) + def init(self, ssh_audit): + self.OutputBuffer = OutputBuffer + self.protocol = Protocol + self.ssh2_kex = SSH2_Kex + self.ssh2_kexparty = SSH2_KexParty + self.rbuf = ReadBuf + self.wbuf = WriteBuf + self.audit = audit + self.AuditConf = AuditConf + + def _conf(self): + conf = self.AuditConf('localhost', 22) + conf.colors = False + conf.batch = True + conf.verbose = True + conf.ssh1 = False + conf.ssh2 = True + return conf + + @classmethod + def _create_ssh2_packet(cls, payload): + padding = -(len(payload) + 5) % 8 + if padding < 4: + padding += 8 + plen = len(payload) + padding + 1 + pad_bytes = b'\x00' * padding + data = struct.pack('>Ib', plen, padding) + payload + pad_bytes + return data + + def _kex_payload(self): + w = self.wbuf() + w.write(b'\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff') + w.write_list(['bogus_kex1', 'bogus_kex2']) # We use a bogus kex, otherwise the host key tests will kick off and fail. + w.write_list(['ssh-rsa', 'rsa-sha2-512', 'rsa-sha2-256', 'ssh-ed25519']) + w.write_list(['chacha20-poly1305@openssh.com', 'aes128-ctr', 'aes192-ctr', 'aes256-ctr', 'aes128-gcm@openssh.com', 'aes256-gcm@openssh.com', 'aes128-cbc', 'aes192-cbc', 'aes256-cbc']) + w.write_list(['chacha20-poly1305@openssh.com', 'aes128-ctr', 'aes192-ctr', 'aes256-ctr', 'aes128-gcm@openssh.com', 'aes256-gcm@openssh.com', 'aes128-cbc', 'aes192-cbc', 'aes256-cbc']) + w.write_list(['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']) + w.write_list(['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']) + w.write_list(['none', 'zlib@openssh.com']) + w.write_list(['none', 'zlib@openssh.com']) + w.write_list(['']) + w.write_list(['']) + w.write_byte(False) + w.write_int(0) + return w.write_flush() + + def test_kex_read(self): + kex = self.ssh2_kex.parse(self._kex_payload()) + assert kex is not None + assert kex.cookie == b'\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff' + assert kex.kex_algorithms == ['bogus_kex1', 'bogus_kex2'] + assert kex.key_algorithms == ['ssh-rsa', 'rsa-sha2-512', 'rsa-sha2-256', 'ssh-ed25519'] + assert kex.client is not None + assert kex.server is not None + assert kex.client.encryption == ['chacha20-poly1305@openssh.com', 'aes128-ctr', 'aes192-ctr', 'aes256-ctr', 'aes128-gcm@openssh.com', 'aes256-gcm@openssh.com', 'aes128-cbc', 'aes192-cbc', 'aes256-cbc'] + assert kex.server.encryption == ['chacha20-poly1305@openssh.com', 'aes128-ctr', 'aes192-ctr', 'aes256-ctr', 'aes128-gcm@openssh.com', 'aes256-gcm@openssh.com', 'aes128-cbc', 'aes192-cbc', 'aes256-cbc'] + assert kex.client.mac == ['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'] + assert kex.server.mac == ['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'] + assert kex.client.compression == ['none', 'zlib@openssh.com'] + assert kex.server.compression == ['none', 'zlib@openssh.com'] + assert kex.client.languages == [''] + assert kex.server.languages == [''] + assert kex.follows is False + assert kex.unused == 0 + + def _get_empty_kex(self, cookie=None): + kex_algs, key_algs = [], [] + enc, mac, compression, languages = [], [], ['none'], [] + cli = self.ssh2_kexparty(enc, mac, compression, languages) + enc, mac, compression, languages = [], [], ['none'], [] + srv = self.ssh2_kexparty(enc, mac, compression, languages) + if cookie is None: + cookie = os.urandom(16) + kex = self.ssh2_kex(cookie, kex_algs, key_algs, cli, srv, 0) + return kex + + def _get_kex_variat1(self): + cookie = b'\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff' + kex = self._get_empty_kex(cookie) + kex.kex_algorithms.append('bogus_kex1') + kex.kex_algorithms.append('bogus_kex2') + kex.key_algorithms.append('ssh-rsa') + kex.key_algorithms.append('rsa-sha2-512') + kex.key_algorithms.append('rsa-sha2-256') + kex.key_algorithms.append('ssh-ed25519') + kex.server.encryption.append('chacha20-poly1305@openssh.com') + kex.server.encryption.append('aes128-ctr') + kex.server.encryption.append('aes192-ctr') + kex.server.encryption.append('aes256-ctr') + kex.server.encryption.append('aes128-gcm@openssh.com') + kex.server.encryption.append('aes256-gcm@openssh.com') + kex.server.encryption.append('aes128-cbc') + kex.server.encryption.append('aes192-cbc') + kex.server.encryption.append('aes256-cbc') + kex.server.mac.append('umac-64-etm@openssh.com') + kex.server.mac.append('umac-128-etm@openssh.com') + kex.server.mac.append('hmac-sha2-256-etm@openssh.com') + kex.server.mac.append('hmac-sha2-512-etm@openssh.com') + kex.server.mac.append('hmac-sha1-etm@openssh.com') + kex.server.mac.append('umac-64@openssh.com') + kex.server.mac.append('umac-128@openssh.com') + kex.server.mac.append('hmac-sha2-256') + kex.server.mac.append('hmac-sha2-512') + kex.server.mac.append('hmac-sha1') + kex.server.compression.append('zlib@openssh.com') + for a in kex.server.encryption: + kex.client.encryption.append(a) + for a in kex.server.mac: + kex.client.mac.append(a) + for a in kex.server.compression: + if a == 'none': + continue + kex.client.compression.append(a) + return kex + + def test_key_payload(self): + kex1 = self._get_kex_variat1() + kex2 = self.ssh2_kex.parse(self._kex_payload()) + assert kex1.payload == kex2.payload + + def test_ssh2_server_simple(self, output_spy, virtual_socket): + vsocket = virtual_socket + w = self.wbuf() + w.write_byte(self.protocol.MSG_KEXINIT) + w.write(self._kex_payload()) + vsocket.rdata.append(b'SSH-2.0-OpenSSH_7.3 ssh-audit-test\r\n') + vsocket.rdata.append(self._create_ssh2_packet(w.write_flush())) + output_spy.begin() + out = self.OutputBuffer() + self.audit(out, self._conf()) + out.write() + lines = output_spy.flush() + assert len(lines) == 70 + + def test_ssh2_server_invalid_first_packet(self, output_spy, virtual_socket): + vsocket = virtual_socket + w = self.wbuf() + w.write_byte(self.protocol.MSG_KEXINIT + 1) + vsocket.rdata.append(b'SSH-2.0-OpenSSH_7.3 ssh-audit-test\r\n') + vsocket.rdata.append(self._create_ssh2_packet(w.write_flush())) + output_spy.begin() + out = self.OutputBuffer() + ret = self.audit(out, self._conf()) + out.write() + assert ret != 0 + lines = output_spy.flush() + assert len(lines) == 5 + assert 'unknown message' in lines[-1] diff --git a/test/test_utils.py b/test/test_utils.py new file mode 100644 index 0000000..d5251f7 --- /dev/null +++ b/test/test_utils.py @@ -0,0 +1,76 @@ +import pytest + + +# pylint: disable=attribute-defined-outside-init +class TestUtils: + @pytest.fixture(autouse=True) + def init(self, ssh_audit): + self.utils = ssh_audit.Utils + + def test_to_bytes(self): + assert self.utils.to_bytes(b'fran\xc3\xa7ais') == b'fran\xc3\xa7ais' + assert self.utils.to_bytes('fran\xe7ais') == b'fran\xc3\xa7ais' + # other + with pytest.raises(TypeError): + self.utils.to_bytes(123) + + def test_to_text(self): + assert self.utils.to_text(b'fran\xc3\xa7ais') == 'fran\xe7ais' + assert self.utils.to_text('fran\xe7ais') == 'fran\xe7ais' + # other + with pytest.raises(TypeError): + self.utils.to_text(123) + + def test_is_ascii(self): + assert self.utils.is_ascii('francais') is True + assert self.utils.is_ascii('fran\xe7ais') is False + # other + assert self.utils.is_ascii(123) is False + + def test_to_ascii(self): + assert self.utils.to_ascii('francais') == 'francais' + assert self.utils.to_ascii('fran\xe7ais') == 'fran?ais' + assert self.utils.to_ascii('fran\xe7ais', 'ignore') == 'franais' + with pytest.raises(TypeError): + self.utils.to_ascii(123) + + def test_is_print_ascii(self): + assert self.utils.is_print_ascii('francais') is True + assert self.utils.is_print_ascii('francais\n') is False + assert self.utils.is_print_ascii('fran\xe7ais') is False + # other + assert self.utils.is_print_ascii(123) is False + + def test_to_print_ascii(self): + assert self.utils.to_print_ascii('francais') == 'francais' + assert self.utils.to_print_ascii('francais\n') == 'francais?' + assert self.utils.to_print_ascii('fran\xe7ais') == 'fran?ais' + assert self.utils.to_print_ascii('fran\xe7ais\n') == 'fran?ais?' + assert self.utils.to_print_ascii('fran\xe7ais', 'ignore') == 'franais' + assert self.utils.to_print_ascii('fran\xe7ais\n', 'ignore') == 'franais' + with pytest.raises(TypeError): + self.utils.to_print_ascii(123) + + def test_ctoi(self): + assert self.utils.ctoi(123) == 123 + assert self.utils.ctoi('ABC') == 65 + + def test_parse_int(self): + assert self.utils.parse_int(123) == 123 + assert self.utils.parse_int('123') == 123 + assert self.utils.parse_int(-123) == -123 + assert self.utils.parse_int('-123') == -123 + assert self.utils.parse_int('abc') == 0 + + def test_unique_seq(self): + assert self.utils.unique_seq((1, 2, 2, 3, 3, 3)) == (1, 2, 3) + assert self.utils.unique_seq((3, 3, 3, 2, 2, 1)) == (3, 2, 1) + assert self.utils.unique_seq([1, 2, 2, 3, 3, 3]) == [1, 2, 3] + assert self.utils.unique_seq([3, 3, 3, 2, 2, 1]) == [3, 2, 1] + + def test_parse_float(self): + assert self.utils.parse_float('5.x') == -1.0 + + def test_ipv6address(self): + assert self.utils.is_ipv6_address('1.2.3.4') is False + assert self.utils.is_ipv6_address('2600:1f18:420a:b500:bc4:c9c6:1d6:e3e4') is True diff --git a/test/test_version_compare.py b/test/test_version_compare.py new file mode 100644 index 0000000..f6f0441 --- /dev/null +++ b/test/test_version_compare.py @@ -0,0 +1,219 @@ +import pytest + +from ssh_audit.banner import Banner +from ssh_audit.software import Software + + +# pylint: disable=attribute-defined-outside-init +class TestVersionCompare: + @pytest.fixture(autouse=True) + def init(self, ssh_audit): + self.software = Software + self.banner = Banner + + def get_dropbear_software(self, v): + b = self.banner.parse('SSH-2.0-dropbear_{}'.format(v)) + return self.software.parse(b) + + def get_openssh_software(self, v): + b = self.banner.parse('SSH-2.0-OpenSSH_{}'.format(v)) + return self.software.parse(b) + + def get_libssh_software(self, v): + b = self.banner.parse('SSH-2.0-libssh-{}'.format(v)) + return self.software.parse(b) + + def test_dropbear_compare_version_pre_years(self): + s = self.get_dropbear_software('0.44') + assert s.compare_version(None) == 1 + assert s.compare_version('') == 1 + assert s.compare_version('0.43') > 0 + assert s.compare_version('0.44') == 0 + assert s.compare_version(s) == 0 + assert s.compare_version('0.45') < 0 + assert s.between_versions('0.43', '0.45') + assert s.between_versions('0.43', '0.43') is False + assert s.between_versions('0.45', '0.43') is False + + def test_dropbear_compare_version_with_years(self): + s = self.get_dropbear_software('2015.71') + assert s.compare_version(None) == 1 + assert s.compare_version('') == 1 + assert s.compare_version('2014.66') > 0 + assert s.compare_version('2015.71') == 0 + assert s.compare_version(s) == 0 + assert s.compare_version('2016.74') < 0 + assert s.between_versions('2014.66', '2016.74') + assert s.between_versions('2014.66', '2015.69') is False + assert s.between_versions('2016.74', '2014.66') is False + + def test_dropbear_compare_version_mixed(self): + s = self.get_dropbear_software('0.53.1') + assert s.compare_version(None) == 1 + assert s.compare_version('') == 1 + assert s.compare_version('0.53') > 0 + assert s.compare_version('0.53.1') == 0 + assert s.compare_version(s) == 0 + assert s.compare_version('2011.54') < 0 + assert s.between_versions('0.53', '2011.54') + assert s.between_versions('0.53', '0.53') is False + assert s.between_versions('2011.54', '0.53') is False + + def test_dropbear_compare_version_patchlevel(self): + s1 = self.get_dropbear_software('0.44') + s2 = self.get_dropbear_software('0.44test3') + assert s1.compare_version(None) == 1 + assert s1.compare_version('') == 1 + assert s1.compare_version('0.44') == 0 + assert s1.compare_version(s1) == 0 + assert s1.compare_version('0.43') > 0 + assert s1.compare_version('0.44test4') > 0 + assert s1.between_versions('0.44test4', '0.45') + assert s1.between_versions('0.43', '0.44test4') is False + assert s1.between_versions('0.45', '0.44test4') is False + assert s2.compare_version(None) == 1 + assert s2.compare_version('') == 1 + assert s2.compare_version('0.44test3') == 0 + assert s2.compare_version(s2) == 0 + assert s2.compare_version('0.44') < 0 + assert s2.compare_version('0.44test4') < 0 + assert s2.between_versions('0.43', '0.44') + assert s2.between_versions('0.43', '0.44test2') is False + assert s2.between_versions('0.44', '0.43') is False + assert s1.compare_version(s2) > 0 + assert s2.compare_version(s1) < 0 + + def test_dropbear_compare_version_sequential(self): + versions = [] + for i in range(28, 44): + versions.append('0.{}'.format(i)) + for i in range(1, 5): + versions.append('0.44test{}'.format(i)) + for i in range(44, 49): + versions.append('0.{}'.format(i)) + versions.append('0.48.1') + for i in range(49, 54): + versions.append('0.{}'.format(i)) + versions.append('0.53.1') + for v in ['2011.54', '2012.55']: + versions.append(v) + for i in range(56, 61): + versions.append('2013.{}'.format(i)) + for v in ['2013.61test', '2013.62']: + versions.append(v) + for i in range(63, 67): + versions.append('2014.{}'.format(i)) + for i in range(67, 72): + versions.append('2015.{}'.format(i)) + for i in range(72, 75): + versions.append('2016.{}'.format(i)) + length = len(versions) + for i in range(length): + v = versions[i] + s = self.get_dropbear_software(v) + assert s.compare_version(v) == 0 + if i - 1 >= 0: + vbefore = versions[i - 1] + assert s.compare_version(vbefore) > 0 + if i + 1 < length: + vnext = versions[i + 1] + assert s.compare_version(vnext) < 0 + + def test_openssh_compare_version_simple(self): + s = self.get_openssh_software('3.7.1') + assert s.compare_version(None) == 1 + assert s.compare_version('') == 1 + assert s.compare_version('3.7') > 0 + assert s.compare_version('3.7.1') == 0 + assert s.compare_version(s) == 0 + assert s.compare_version('3.8') < 0 + assert s.between_versions('3.7', '3.8') + assert s.between_versions('3.6', '3.7') is False + assert s.between_versions('3.8', '3.7') is False + + def test_openssh_compare_version_patchlevel(self): + s1 = self.get_openssh_software('2.1.1') + s2 = self.get_openssh_software('2.1.1p2') + assert s1.compare_version(s1) == 0 + assert s2.compare_version(s2) == 0 + assert s1.compare_version('2.1.1') == 0 + assert s2.compare_version('2.1.1p2') == 0 + assert s1.compare_version('2.1.1p1') == 0 # OpenBSD version and p1 version should be the same. + assert s1.compare_version('2.1.1p2') != 0 + assert s2.compare_version('2.1.1') != 0 + assert s2.compare_version('2.1.1p1') > 0 + assert s2.compare_version('2.1.1p3') < 0 + assert s1.compare_version(s2) != 0 + assert s2.compare_version(s1) != 0 + + def test_openbsd_compare_version_sequential(self): + versions = [] + for v in ['1.2.3', '2.1.0', '2.1.1', '2.2.0', '2.3.0']: + versions.append(v) + for v in ['2.5.0', '2.5.1', '2.5.2', '2.9', '2.9.9']: + versions.append(v) + for v in ['3.0', '3.0.1', '3.0.2', '3.1', '3.2.2', '3.2.3']: + versions.append(v) + for i in range(3, 7): + versions.append('3.{}'.format(i)) + for v in ['3.6.1', '3.7.0', '3.7.1']: + versions.append(v) + for i in range(8, 10): + versions.append('3.{}'.format(i)) + for i in range(0, 10): + versions.append('4.{}'.format(i)) + for i in range(0, 10): + versions.append('5.{}'.format(i)) + for i in range(0, 10): + versions.append('6.{}'.format(i)) + for i in range(0, 4): + versions.append('7.{}'.format(i)) + length = len(versions) + for i in range(length): + v = versions[i] + s = self.get_openssh_software(v) + assert s.compare_version(v) == 0 + if i - 1 >= 0: + vbefore = versions[i - 1] + assert s.compare_version(vbefore) > 0 + if i + 1 < length: + vnext = versions[i + 1] + assert s.compare_version(vnext) < 0 + + def test_libssh_compare_version_simple(self): + s = self.get_libssh_software('0.3') + assert s.compare_version(None) == 1 + assert s.compare_version('') == 1 + assert s.compare_version('0.2') > 0 + assert s.compare_version('0.3') == 0 + assert s.compare_version(s) == 0 + assert s.compare_version('0.3.1') < 0 + assert s.between_versions('0.2', '0.3.1') + assert s.between_versions('0.1', '0.2') is False + assert s.between_versions('0.3.1', '0.2') is False + + def test_libssh_compare_version_sequential(self): + versions = [] + for v in ['0.2', '0.3']: + versions.append(v) + for i in range(1, 5): + versions.append('0.3.{}'.format(i)) + for i in range(0, 9): + versions.append('0.4.{}'.format(i)) + for i in range(0, 6): + versions.append('0.5.{}'.format(i)) + for i in range(0, 6): + versions.append('0.6.{}'.format(i)) + for i in range(0, 5): + versions.append('0.7.{}'.format(i)) + length = len(versions) + for i in range(length): + v = versions[i] + s = self.get_libssh_software(v) + assert s.compare_version(v) == 0 + if i - 1 >= 0: + vbefore = versions[i - 1] + assert s.compare_version(vbefore) > 0 + if i + 1 < length: + vnext = versions[i + 1] + assert s.compare_version(vnext) < 0 diff --git a/test/tools/ci-win.cmd b/test/tools/ci-win.cmd new file mode 100644 index 0000000..103036c --- /dev/null +++ b/test/tools/ci-win.cmd @@ -0,0 +1,131 @@ +@ECHO OFF + +IF "%PYTHON%" == "" ( + ECHO PYTHON environment variable not set + EXIT 1 +) +SET PATH=%PYTHON%;%PYTHON%\\Scripts;%PATH%" +FOR /F %%i IN ('python -c "import platform; print(platform.python_version());"') DO ( + SET PYTHON_VERSION=%%i +) +SET PYTHON_VERSION_MAJOR=%PYTHON_VERSION:~0,1% +IF "%PYTHON_VERSION:~3,1%" == "." ( + SET PYTHON_VERSION_MINOR=%PYTHON_VERSION:~2,1% +) ELSE ( + SET PYTHON_VERSION_MINOR=%PYTHON_VERSION:~2,2% +) +FOR /F %%i IN ('python -c "import struct; print(struct.calcsize(\"P\")*8)"') DO ( + SET PYTHON_ARCH=%%i +) +CALL :devenv + +IF /I "%1"=="" ( + SET target=test +) ELSE ( + SET target=%1 +) + +echo [CI] TARGET=%target% +GOTO %target% + +:devenv +SET WIN_SDK_ROOT=C:\Program Files\Microsoft SDKs\Windows +SET VS2015_ROOT=C:\Program Files (x86)\Microsoft Visual Studio 14.0 +IF %PYTHON_VERSION_MAJOR% == 2 ( + SET WINDOWS_SDK_VERSION="v7.0" +) ELSE IF %PYTHON_VERSION_MAJOR% == 3 ( + IF %PYTHON_VERSION_MAJOR% LEQ 4 ( + SET WINDOWS_SDK_VERSION="v7.1" + ) ELSE ( + SET WINDOWS_SDK_VERSION="2015" + ) +) ELSE ( + ECHO Unsupported Python version: "%PYTHON_VERSION%" + EXIT 1 +) +SETLOCAL ENABLEDELAYEDEXPANSION +IF %PYTHON_ARCH% == 32 (SET PYTHON_ARCHX=x86) ELSE (SET PYTHON_ARCHX=x64) +IF %WINDOWS_SDK_VERSION% == "2015" ( + "%VS2015_ROOT%\VC\vcvarsall.bat" %PYTHON_ARCHX% +) ELSE ( + SET DISTUTILS_USE_SDK=1 + SET MSSdk=1 + "%WIN_SDK_ROOT%\%WINDOWS_SDK_VERSION%\Setup\WindowsSdkVer.exe" -q -version:%WINDOWS_SDK_VERSION% + "%WIN_SDK_ROOT%\%WINDOWS_SDK_VERSION%\Bin\SetEnv.cmd" /%PYTHON_ARCHX% /release +) +GOTO :eof + +:install +pip install --user --upgrade pip virtualenv +SET VENV_DIR=.venv\%PYTHON_VERSION% +rmdir /s /q %VENV_DIR% > nul 2>nul +mkdir .venv > nul 2>nul +IF "%PYTHON_VERSION_MAJOR%%PYTHON_VERSION_MINOR%" == "26" ( + python -c "import virtualenv; virtualenv.main();" %VENV_DIR% +) ELSE ( + python -m virtualenv %VENV_DIR% +) +CALL %VENV_DIR%\Scripts\activate +python -V +pip install tox +deactivate +GOTO :eof + +:install_deps +SET LXML_FILE= +SET LXML_URL= +IF %PYTHON_VERSION_MAJOR% == 3 ( + IF %PYTHON_VERSION_MINOR% == 3 ( + IF %PYTHON_ARCH% == 32 ( + SET LXML_FILE=lxml-3.7.3.win32-py3.3.exe + SET LXML_URL=https://pypi.python.org/packages/66/fd/b82a54e7a15e91184efeef4b659379d0581a73cf78239d70feb0f0877841/lxml-3.7.3.win32-py3.3.exe + ) ELSE ( + SET LXML_FILE=lxml-3.7.3.win-amd64-py3.3.exe + SET LXML_URL=https://pypi.python.org/packages/dc/bc/4742b84793fa1fd991b5d2c6f2e5d32695659d6cfedf5c66aef9274a8723/lxml-3.7.3.win-amd64-py3.3.exe + ) + ) ELSE IF %PYTHON_VERSION_MINOR% == 4 ( + IF %PYTHON_ARCH% == 32 ( + SET LXML_FILE=lxml-3.7.3.win32-py3.4.exe + SET LXML_URL=https://pypi.python.org/packages/88/33/265459d68d465ddc707621e6471989f5c2cb0d43f230f516800ffd629af7/lxml-3.7.3.win32-py3.4.exe + ) ELSE ( + SET LXML_FILE=lxml-3.7.3.win-amd64-py3.4.exe + SET LXML_URL=https://pypi.python.org/packages/2d/65/e47db7f36a69a1b59b4f661e42d699d6c43e663b8fd91035e6f7681d017e/lxml-3.7.3.win-amd64-py3.4.exe + ) + ) +) +IF NOT "%LXML_FILE%" == "" ( + CALL :download %LXML_URL% .downloads\%LXML_FILE% + easy_install --user .downloads\%LXML_FILE% +) +GOTO :eof + +:test + SET VENV_DIR=.venv\%PYTHON_VERSION% + CALL %VENV_DIR%\Scripts\activate + IF "%TOXENV%" == "" ( + SET TOXENV=py%PYTHON_VERSION_MAJOR%%PYTHON_VERSION_MINOR% + ) + IF "%PYTHON_VERSION_MAJOR%%PYTHON_VERSION_MINOR%" == "26" ( + SET TOX=python -c "from tox import cmdline; cmdline()" + ) ELSE ( + SET TOX=python -m tox + ) + IF %PYTHON_VERSION_MAJOR% == 3 ( + IF %PYTHON_VERSION_MINOR% LEQ 4 ( + :: Python 3.3 and 3.4 does not support typed-ast (mypy dependency) + %TOX% --sitepackages -e %TOXENV%-test,%TOXENV%-lint,cov || EXIT 1 + ) ELSE ( + %TOX% --sitepackages -e %TOXENV%-test,%TOXENV%-type,%TOXENV%-lint,cov || EXIT 1 + ) + ) ELSE ( + %TOX% --sitepackages -e %TOXENV%-test,%TOXENV%-lint,cov || EXIT 1 + ) +GOTO :eof + +:download +IF NOT EXIST %2 ( + IF NOT EXIST .downloads\ mkdir .downloads + powershell -command "(new-object net.webclient).DownloadFile('%1', '%2')" || EXIT 1 + +) +GOTO :eof |