mirror of
https://github.com/jtesta/ssh-audit.git
synced 2026-05-25 15:31:23 +02:00
Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 75edf850ff | |||
| c9769b3609 | |||
| 92db5f0138 | |||
| bc2a89eb11 | |||
| ea117b203b | |||
| d8f8b7c57c |
@@ -216,7 +216,9 @@ For convenience, a web front-end on top of the command-line tool is available at
|
|||||||
### v3.3.0-dev (???)
|
### v3.3.0-dev (???)
|
||||||
- Added built-in policies for Ubuntu 24.04 LTS server and client, and OpenSSH 9.8.
|
- Added built-in policies for Ubuntu 24.04 LTS server and client, and OpenSSH 9.8.
|
||||||
- Added IPv6 support for DHEat and connection rate tests.
|
- Added IPv6 support for DHEat and connection rate tests.
|
||||||
|
- Added TCP port information to JSON policy scan results; credit [Fabian Malte Kopp](https://github.com/dreizehnutters).
|
||||||
- Fixed crash when running with `-P` and `-T` options simultaneously.
|
- Fixed crash when running with `-P` and `-T` options simultaneously.
|
||||||
|
- Fixed host key tests from only reporting a key type at most once despite multiple hosts supporting it; credit [Daniel Lenski](https://github.com/dlenskiSB).
|
||||||
|
|
||||||
### v3.2.0 (2024-04-22)
|
### v3.2.0 (2024-04-22)
|
||||||
- Added implementation of the DHEat denial-of-service attack (see `--dheat` option; [CVE-2002-20001](https://nvd.nist.gov/vuln/detail/CVE-2002-20001)).
|
- Added implementation of the DHEat denial-of-service attack (see `--dheat` option; [CVE-2002-20001](https://nvd.nist.gov/vuln/detail/CVE-2002-20001)).
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ class HostKeyTest:
|
|||||||
# Tracks the RSA host key types. As of this writing, testing one in this family yields valid results for the rest.
|
# Tracks the RSA host key types. As of this writing, testing one in this family yields valid results for the rest.
|
||||||
RSA_FAMILY = ['ssh-rsa', 'rsa-sha2-256', 'rsa-sha2-512']
|
RSA_FAMILY = ['ssh-rsa', 'rsa-sha2-256', 'rsa-sha2-512']
|
||||||
|
|
||||||
# Dict holding the host key types we should extract & parse. 'cert' is True to denote that a host key type handles certificates (thus requires additional parsing). 'variable_key_len' is True for host key types that can have variable sizes (True only for RSA types, as the rest are of fixed-size). After the host key type is fully parsed, the key 'parsed' is added with a value of True.
|
# Dict holding the host key types we should extract & parse. 'cert' is True to denote that a host key type handles certificates (thus requires additional parsing). 'variable_key_len' is True for host key types that can have variable sizes (True only for RSA types, as the rest are of fixed-size).
|
||||||
HOST_KEY_TYPES = {
|
HOST_KEY_TYPES = {
|
||||||
'ssh-rsa': {'cert': False, 'variable_key_len': True},
|
'ssh-rsa': {'cert': False, 'variable_key_len': True},
|
||||||
'rsa-sha2-256': {'cert': False, 'variable_key_len': True},
|
'rsa-sha2-256': {'cert': False, 'variable_key_len': True},
|
||||||
@@ -96,6 +96,7 @@ class HostKeyTest:
|
|||||||
def perform_test(out: 'OutputBuffer', s: 'SSH_Socket', server_kex: 'SSH2_Kex', kex_str: str, kex_group: 'KexDH', host_key_types: Dict[str, Dict[str, bool]]) -> None:
|
def perform_test(out: 'OutputBuffer', s: 'SSH_Socket', server_kex: 'SSH2_Kex', kex_str: str, kex_group: 'KexDH', host_key_types: Dict[str, Dict[str, bool]]) -> None:
|
||||||
hostkey_modulus_size = 0
|
hostkey_modulus_size = 0
|
||||||
ca_modulus_size = 0
|
ca_modulus_size = 0
|
||||||
|
parsed_host_key_types = set()
|
||||||
|
|
||||||
# If the connection still exists, close it so we can test
|
# If the connection still exists, close it so we can test
|
||||||
# using a clean slate (otherwise it may exist in a non-testable
|
# using a clean slate (otherwise it may exist in a non-testable
|
||||||
@@ -109,7 +110,7 @@ class HostKeyTest:
|
|||||||
key_warn_comments = []
|
key_warn_comments = []
|
||||||
|
|
||||||
# Skip those already handled (i.e.: those in the RSA family, as testing one tests them all).
|
# Skip those already handled (i.e.: those in the RSA family, as testing one tests them all).
|
||||||
if 'parsed' in host_key_types[host_key_type] and host_key_types[host_key_type]['parsed']:
|
if host_key_type in parsed_host_key_types:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# If this host key type is supported by the server, we test it.
|
# If this host key type is supported by the server, we test it.
|
||||||
@@ -220,7 +221,7 @@ class HostKeyTest:
|
|||||||
# If this host key type is in the RSA family, then mark them all as parsed (since results in one are valid for them all).
|
# If this host key type is in the RSA family, then mark them all as parsed (since results in one are valid for them all).
|
||||||
if host_key_type in HostKeyTest.RSA_FAMILY:
|
if host_key_type in HostKeyTest.RSA_FAMILY:
|
||||||
for rsa_type in HostKeyTest.RSA_FAMILY:
|
for rsa_type in HostKeyTest.RSA_FAMILY:
|
||||||
host_key_types[rsa_type]['parsed'] = True
|
parsed_host_key_types.add(rsa_type)
|
||||||
|
|
||||||
# If the current key is a member of the RSA family, then populate all RSA family members with the same
|
# If the current key is a member of the RSA family, then populate all RSA family members with the same
|
||||||
# failure and/or warning comments.
|
# failure and/or warning comments.
|
||||||
@@ -232,7 +233,7 @@ class HostKeyTest:
|
|||||||
db['key'][rsa_type][2].extend(key_warn_comments)
|
db['key'][rsa_type][2].extend(key_warn_comments)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
host_key_types[host_key_type]['parsed'] = True
|
parsed_host_key_types.add(host_key_type)
|
||||||
db = SSH2_KexDB.get_db()
|
db = SSH2_KexDB.get_db()
|
||||||
while len(db['key'][host_key_type]) < 3:
|
while len(db['key'][host_key_type]) < 3:
|
||||||
db['key'][host_key_type].append([])
|
db['key'][host_key_type].append([])
|
||||||
|
|||||||
@@ -68,7 +68,6 @@ class SSH2_KexDB: # pylint: disable=too-few-public-methods
|
|||||||
INFO_DEPRECATED_IN_OPENSSH88 = 'deprecated in OpenSSH 8.8: https://www.openssh.com/txt/release-8.8'
|
INFO_DEPRECATED_IN_OPENSSH88 = 'deprecated in OpenSSH 8.8: https://www.openssh.com/txt/release-8.8'
|
||||||
INFO_DISABLED_IN_DBEAR67 = 'disabled in Dropbear SSH 2015.67'
|
INFO_DISABLED_IN_DBEAR67 = 'disabled in Dropbear SSH 2015.67'
|
||||||
INFO_DISABLED_IN_OPENSSH70 = 'disabled in OpenSSH 7.0: https://www.openssh.com/txt/release-7.0'
|
INFO_DISABLED_IN_OPENSSH70 = 'disabled in OpenSSH 7.0: https://www.openssh.com/txt/release-7.0'
|
||||||
INFO_RFC8709_NOT_OPENSSH = 'described in RFC8709 but never implemented in OpenSSH'
|
|
||||||
INFO_NEVER_IMPLEMENTED_IN_OPENSSH = 'despite the @openssh.com tag, this was never implemented in OpenSSH'
|
INFO_NEVER_IMPLEMENTED_IN_OPENSSH = 'despite the @openssh.com tag, this was never implemented in OpenSSH'
|
||||||
INFO_REMOVED_IN_OPENSSH61 = 'removed since OpenSSH 6.1, removed from specification'
|
INFO_REMOVED_IN_OPENSSH61 = 'removed since OpenSSH 6.1, removed from specification'
|
||||||
INFO_REMOVED_IN_OPENSSH69 = 'removed in OpenSSH 6.9: https://www.openssh.com/txt/release-6.9'
|
INFO_REMOVED_IN_OPENSSH69 = 'removed in OpenSSH 6.9: https://www.openssh.com/txt/release-6.9'
|
||||||
@@ -246,7 +245,7 @@ class SSH2_KexDB: # pylint: disable=too-few-public-methods
|
|||||||
'ssh-dss-sha512@ssh.com': [[], [FAIL_1024BIT_MODULUS]],
|
'ssh-dss-sha512@ssh.com': [[], [FAIL_1024BIT_MODULUS]],
|
||||||
'ssh-ed25519': [['6.5,d2020.79,l10.7.0']],
|
'ssh-ed25519': [['6.5,d2020.79,l10.7.0']],
|
||||||
'ssh-ed25519-cert-v01@openssh.com': [['6.5']],
|
'ssh-ed25519-cert-v01@openssh.com': [['6.5']],
|
||||||
'ssh-ed448': [[], [], [], [INFO_RFC8709_NOT_OPENSSH]],
|
'ssh-ed448': [[]],
|
||||||
'ssh-ed448-cert-v01@openssh.com': [[], [], [], [INFO_NEVER_IMPLEMENTED_IN_OPENSSH]],
|
'ssh-ed448-cert-v01@openssh.com': [[], [], [], [INFO_NEVER_IMPLEMENTED_IN_OPENSSH]],
|
||||||
'ssh-gost2001': [[], [FAIL_UNTRUSTED]],
|
'ssh-gost2001': [[], [FAIL_UNTRUSTED]],
|
||||||
'ssh-gost2012-256': [[], [FAIL_UNTRUSTED]],
|
'ssh-gost2012-256': [[], [FAIL_UNTRUSTED]],
|
||||||
|
|||||||
@@ -735,7 +735,7 @@ def evaluate_policy(out: OutputBuffer, aconf: AuditConf, banner: Optional['Banne
|
|||||||
|
|
||||||
passed, error_struct, error_str = aconf.policy.evaluate(banner, kex)
|
passed, error_struct, error_str = aconf.policy.evaluate(banner, kex)
|
||||||
if aconf.json:
|
if aconf.json:
|
||||||
json_struct = {'host': aconf.host, 'policy': aconf.policy.get_name_and_version(), 'passed': passed, 'errors': error_struct}
|
json_struct = {'host': aconf.host, 'port': aconf.port, 'policy': aconf.policy.get_name_and_version(), 'passed': passed, 'errors': error_struct}
|
||||||
out.info(json.dumps(json_struct, indent=4 if aconf.json_print_indent else None, sort_keys=True))
|
out.info(json.dumps(json_struct, indent=4 if aconf.json_print_indent else None, sort_keys=True))
|
||||||
else:
|
else:
|
||||||
spacing = ''
|
spacing = ''
|
||||||
|
|||||||
@@ -2,5 +2,6 @@
|
|||||||
"errors": [],
|
"errors": [],
|
||||||
"host": "localhost",
|
"host": "localhost",
|
||||||
"passed": true,
|
"passed": true,
|
||||||
"policy": "Docker policy: test1 (version 1)"
|
"policy": "Docker policy: test1 (version 1)",
|
||||||
|
"port": 2222
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,5 +27,6 @@
|
|||||||
],
|
],
|
||||||
"host": "localhost",
|
"host": "localhost",
|
||||||
"passed": false,
|
"passed": false,
|
||||||
"policy": "Docker poliicy: test10 (version 1)"
|
"policy": "Docker poliicy: test10 (version 1)",
|
||||||
|
"port": 2222
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,5 +19,6 @@
|
|||||||
],
|
],
|
||||||
"host": "localhost",
|
"host": "localhost",
|
||||||
"passed": false,
|
"passed": false,
|
||||||
"policy": "Docker policy: test2 (version 1)"
|
"policy": "Docker policy: test2 (version 1)",
|
||||||
|
"port": 2222
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,5 +18,6 @@
|
|||||||
],
|
],
|
||||||
"host": "localhost",
|
"host": "localhost",
|
||||||
"passed": false,
|
"passed": false,
|
||||||
"policy": "Docker policy: test3 (version 1)"
|
"policy": "Docker policy: test3 (version 1)",
|
||||||
|
"port": 2222
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,5 +28,6 @@
|
|||||||
],
|
],
|
||||||
"host": "localhost",
|
"host": "localhost",
|
||||||
"passed": false,
|
"passed": false,
|
||||||
"policy": "Docker policy: test4 (version 1)"
|
"policy": "Docker policy: test4 (version 1)",
|
||||||
|
"port": 2222
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,5 +27,6 @@
|
|||||||
],
|
],
|
||||||
"host": "localhost",
|
"host": "localhost",
|
||||||
"passed": false,
|
"passed": false,
|
||||||
"policy": "Docker policy: test5 (version 1)"
|
"policy": "Docker policy: test5 (version 1)",
|
||||||
|
"port": 2222
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,5 +2,6 @@
|
|||||||
"errors": [],
|
"errors": [],
|
||||||
"host": "localhost",
|
"host": "localhost",
|
||||||
"passed": true,
|
"passed": true,
|
||||||
"policy": "Docker poliicy: test7 (version 1)"
|
"policy": "Docker poliicy: test7 (version 1)",
|
||||||
|
"port": 2222
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,5 +15,6 @@
|
|||||||
],
|
],
|
||||||
"host": "localhost",
|
"host": "localhost",
|
||||||
"passed": false,
|
"passed": false,
|
||||||
"policy": "Docker poliicy: test8 (version 1)"
|
"policy": "Docker poliicy: test8 (version 1)",
|
||||||
|
"port": 2222
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,5 +15,6 @@
|
|||||||
],
|
],
|
||||||
"host": "localhost",
|
"host": "localhost",
|
||||||
"passed": false,
|
"passed": false,
|
||||||
"policy": "Docker poliicy: test9 (version 1)"
|
"policy": "Docker poliicy: test9 (version 1)",
|
||||||
|
"port": 2222
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,5 +39,6 @@
|
|||||||
],
|
],
|
||||||
"host": "localhost",
|
"host": "localhost",
|
||||||
"passed": false,
|
"passed": false,
|
||||||
"policy": "Hardened OpenSSH Server v8.0 (version 4)"
|
"policy": "Hardened OpenSSH Server v8.0 (version 4)",
|
||||||
|
"port": 2222
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,5 +62,6 @@
|
|||||||
],
|
],
|
||||||
"host": "localhost",
|
"host": "localhost",
|
||||||
"passed": false,
|
"passed": false,
|
||||||
"policy": "Hardened OpenSSH Server v8.0 (version 4)"
|
"policy": "Hardened OpenSSH Server v8.0 (version 4)",
|
||||||
|
"port": 2222
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,5 +2,6 @@
|
|||||||
"errors": [],
|
"errors": [],
|
||||||
"host": "localhost",
|
"host": "localhost",
|
||||||
"passed": true,
|
"passed": true,
|
||||||
"policy": "Docker policy: test11 (version 1)"
|
"policy": "Docker policy: test11 (version 1)",
|
||||||
|
"port": 2222
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,5 +39,6 @@
|
|||||||
],
|
],
|
||||||
"host": "localhost",
|
"host": "localhost",
|
||||||
"passed": false,
|
"passed": false,
|
||||||
"policy": "Docker policy: test12 (version 1)"
|
"policy": "Docker policy: test12 (version 1)",
|
||||||
|
"port": 2222
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,5 +2,6 @@
|
|||||||
"errors": [],
|
"errors": [],
|
||||||
"host": "localhost",
|
"host": "localhost",
|
||||||
"passed": true,
|
"passed": true,
|
||||||
"policy": "Docker policy: test13 (version 1)"
|
"policy": "Docker policy: test13 (version 1)",
|
||||||
|
"port": 2222
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,5 +15,6 @@
|
|||||||
],
|
],
|
||||||
"host": "localhost",
|
"host": "localhost",
|
||||||
"passed": false,
|
"passed": false,
|
||||||
"policy": "Docker policy: test14 (version 1)"
|
"policy": "Docker policy: test14 (version 1)",
|
||||||
|
"port": 2222
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,5 +2,6 @@
|
|||||||
"errors": [],
|
"errors": [],
|
||||||
"host": "localhost",
|
"host": "localhost",
|
||||||
"passed": true,
|
"passed": true,
|
||||||
"policy": "Docker policy: test15 (version 1)"
|
"policy": "Docker policy: test15 (version 1)",
|
||||||
|
"port": 2222
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -82,5 +82,6 @@
|
|||||||
],
|
],
|
||||||
"host": "localhost",
|
"host": "localhost",
|
||||||
"passed": false,
|
"passed": false,
|
||||||
"policy": "Docker policy: test16 (version 1)"
|
"policy": "Docker policy: test16 (version 1)",
|
||||||
|
"port": 2222
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,5 +2,6 @@
|
|||||||
"errors": [],
|
"errors": [],
|
||||||
"host": "localhost",
|
"host": "localhost",
|
||||||
"passed": true,
|
"passed": true,
|
||||||
"policy": "Docker policy: test17 (version 1)"
|
"policy": "Docker policy: test17 (version 1)",
|
||||||
|
"port": 2222
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,5 +2,6 @@
|
|||||||
"errors": [],
|
"errors": [],
|
||||||
"host": "localhost",
|
"host": "localhost",
|
||||||
"passed": true,
|
"passed": true,
|
||||||
"policy": "Docker policy: test6 (version 1)"
|
"policy": "Docker policy: test6 (version 1)",
|
||||||
|
"port": 2222
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user