5 Commits

Author SHA1 Message Date
FlyingPhishy 5978bb2394 Merge b2e621cafc into 9049c8476a 2024-07-06 21:12:27 -04:00
Joe Testa 9049c8476a Updated README. 2024-07-06 21:01:19 -04:00
Daniel Lenski bbbdf71e50 Recognize LANcom LCOS software and support ed448 key extraction (#277)
* Include raw hostkey bytes in debug output

* Recognize LANcom LCOS software and support extraction of ssh-ed448 key type

LANcom router devices appear to be primarily used in Germany (see [1]
for examples on the public Internet), and they appear to support the
`ssh-ed448` key type which is documented in [2], but which has never
been supported by any as-yet-released version of OpenSSH.

[1] https://www.shodan.io/search?query=ssh+%22ed448%22
[2] https://datatracker.ietf.org/doc/html/rfc8709#name-public-key-format
2024-07-06 20:56:24 -04:00
Joe Testa 92db5f0138 Updated docker tests and README due to merge of PR #281. 2024-07-05 10:53:00 -04:00
dreizehnutters bc2a89eb11 fix for https://github.com/jtesta/ssh-audit/issues/280 (#281)
* fix for https://github.com/jtesta/ssh-audit/issues/280

* changed json format to min. the damage for a change
2024-07-05 10:49:16 -04:00
24 changed files with 52 additions and 20 deletions
+2
View File
@@ -216,6 +216,8 @@ 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).
- Added LANcom LCOS server recognition and Ed448 key extraction; credit [Daniel Lenski](https://github.com/dlenskiSB).
- 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). - 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).
+4
View File
@@ -52,6 +52,9 @@ class HostKeyTest:
'ssh-ed25519': {'cert': False, 'variable_key_len': False}, 'ssh-ed25519': {'cert': False, 'variable_key_len': False},
'ssh-ed25519-cert-v01@openssh.com': {'cert': True, 'variable_key_len': False}, 'ssh-ed25519-cert-v01@openssh.com': {'cert': True, 'variable_key_len': False},
'ssh-ed448': {'cert': False, 'variable_key_len': False},
# 'ssh-ed448-cert-v01@openssh.com': {'cert': True, 'variable_key_len': False},
} }
TWO2K_MODULUS_WARNING = '2048-bit modulus only provides 112-bits of symmetric strength' TWO2K_MODULUS_WARNING = '2048-bit modulus only provides 112-bits of symmetric strength'
@@ -158,6 +161,7 @@ class HostKeyTest:
ca_key_type = kex_group.get_ca_type() ca_key_type = kex_group.get_ca_type()
ca_modulus_size = kex_group.get_ca_size() ca_modulus_size = kex_group.get_ca_size()
out.d("Hostkey type: [%s]; hostkey size: %u; CA type: [%s]; CA modulus size: %u" % (host_key_type, hostkey_modulus_size, ca_key_type, ca_modulus_size), write_now=True) out.d("Hostkey type: [%s]; hostkey size: %u; CA type: [%s]; CA modulus size: %u" % (host_key_type, hostkey_modulus_size, ca_key_type, ca_modulus_size), write_now=True)
out.d("Raw hostkey bytes (%d): [%s]" % (len(raw_hostkey_bytes), raw_hostkey_bytes.hex()), write_now=True)
# Record all the host key info. # Record all the host key info.
server_kex.set_host_key(host_key_type, raw_hostkey_bytes, hostkey_modulus_size, ca_key_type, ca_modulus_size) server_kex.set_host_key(host_key_type, raw_hostkey_bytes, hostkey_modulus_size, ca_key_type, ca_modulus_size)
+3
View File
@@ -134,6 +134,9 @@ class KexDH: # pragma: nocover
if self.__hostkey_type == 'ssh-ed25519': if self.__hostkey_type == 'ssh-ed25519':
self.out.d("%s has a fixed host key modulus of 32." % self.__hostkey_type) self.out.d("%s has a fixed host key modulus of 32." % self.__hostkey_type)
self.__hostkey_n_len = 32 self.__hostkey_n_len = 32
elif self.__hostkey_type == 'ssh-ed448':
self.out.d("%s has a fixed host key modulus of 57." % self.__hostkey_type)
self.__hostkey_n_len = 57
else: else:
# Here is the modulus size & actual modulus of the host key public key. # Here is the modulus size & actual modulus of the host key public key.
hostkey_n, self.__hostkey_n_len, ptr = KexDH.__get_bytes(hostkey, ptr) hostkey_n, self.__hostkey_n_len, ptr = KexDH.__get_bytes(hostkey, ptr)
+4
View File
@@ -224,4 +224,8 @@ class Software:
mx = re.match(r'^PuTTY_Release_(.*)', software) mx = re.match(r'^PuTTY_Release_(.*)', software)
if mx: if mx:
return cls(None, Product.PuTTY, mx.group(1), None, None) return cls(None, Product.PuTTY, mx.group(1), None, None)
mx = re.match(r'^lancom(.*)', software)
if mx:
v, p = 'LANcom', 'LCOS sshd'
return cls(v, p, mx.group(1), None, None)
return None return None
+1 -1
View File
@@ -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
} }