Skip to content

Commit 8e972c5

Browse files
committed
Added test for the Terrapin vulnerability (CVE-2023-48795) (#227).
1 parent 46eb970 commit 8e972c5

File tree

4 files changed

+49
-5
lines changed

4 files changed

+49
-5
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@ For convenience, a web front-end on top of the command-line tool is available at
184184
- In Ubuntu 22.04 client policy, moved host key types `sk-ssh-ed25519@openssh.com` and `ssh-ed25519` to the end of all certificate types.
185185
- Re-organized option host key types for OpenSSH 9.2 server policy to correspond with updated Debian 12 hardening guide.
186186
- Dropped support for Python 3.7 (EOL was reached in June 2023).
187+
- Added test for the Terrapin message prefix truncation vulnerability ([CVE-2023-48795](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2023-48795)).
187188

188189
### v3.0.0 (2023-09-07)
189190
- Results from concurrent scans against multiple hosts are no longer improperly combined; bug discovered by [Adam Russell](https://github.com/thecliguy).

src/ssh_audit/ssh2_kexdb.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ class SSH2_KexDB: # pylint: disable=too-few-public-methods
7171
INFO_REMOVED_IN_OPENSSH69 = 'removed in OpenSSH 6.9: https://www.openssh.com/txt/release-6.9'
7272
INFO_REMOVED_IN_OPENSSH70 = 'removed in OpenSSH 7.0: https://www.openssh.com/txt/release-7.0'
7373
INFO_WITHDRAWN_PQ_ALG = 'the sntrup4591761 algorithm was withdrawn, as it may not provide strong post-quantum security'
74+
INFO_EXTENSION_NEGOTIATION = 'pseudo-algorithm that denotes the peer supports RFC8308 extensions'
75+
INFO_STRICT_KEX = 'pseudo-algorithm that denotes the peer supports a stricter key exchange method as a counter-measure to the Terrapin attack (CVE-2023-48795)'
7476

7577
# Maintains a dictionary per calling thread that yields its own copy of MASTER_DB. This prevents results from one thread polluting the results of another thread.
7678
DB_PER_THREAD: Dict[int, Dict[str, Dict[str, List[List[Optional[str]]]]]] = {}
@@ -154,8 +156,10 @@ class SSH2_KexDB: # pylint: disable=too-few-public-methods
154156
'ecdh-sha2-wiRIU8TKjMZ418sMqlqtvQ==': [[], [FAIL_UNPROVEN]], # sect283k1
155157
'ecdh-sha2-zD/b3hu/71952ArpUG4OjQ==': [[], [FAIL_UNPROVEN, FAIL_SMALL_ECC_MODULUS]], # sect233k1
156158
'ecmqv-sha2': [[], [FAIL_UNPROVEN]],
157-
'ext-info-c': [[]], # Extension negotiation (RFC 8308)
158-
'ext-info-s': [[]], # Extension negotiation (RFC 8308)
159+
'ext-info-c': [[], [], [], [INFO_EXTENSION_NEGOTIATION]], # Extension negotiation (RFC 8308)
160+
'ext-info-s': [[], [], [], [INFO_EXTENSION_NEGOTIATION]], # Extension negotiation (RFC 8308)
161+
'kex-strict-c-v00@openssh.com': [[], [], [], [INFO_STRICT_KEX]], # Strict KEX marker (countermeasure for CVE-2023-48795).
162+
'kex-strict-s-v00@openssh.com': [[], [], [], [INFO_STRICT_KEX]], # Strict KEX marker (countermeasure for CVE-2023-48795).
159163

160164
# The GSS kex algorithms get special wildcard handling, since they include variable base64 data after their standard prefixes.
161165
'gss-13.3.132.0.10-sha256-*': [[], [FAIL_UNKNOWN]],

src/ssh_audit/ssh_audit.py

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -447,7 +447,7 @@ def output_info(out: OutputBuffer, software: Optional['Software'], client_audit:
447447
out.sep()
448448

449449

450-
def post_process_findings(banner: Optional[Banner], algs: Algorithms) -> List[str]:
450+
def post_process_findings(banner: Optional[Banner], algs: Algorithms, client_audit: bool) -> List[str]:
451451
'''Perform post-processing on scan results before reporting them to the user. Returns a list of algorithms that should not be recommended'''
452452

453453

@@ -466,6 +466,45 @@ def post_process_findings(banner: Optional[Banner], algs: Algorithms) -> List[st
466466
# Ensure that this algorithm doesn't appear in the recommendations section since the user cannot control this OpenSSH bug.
467467
algorithm_recommendation_suppress_list.append('diffie-hellman-group-exchange-sha256')
468468

469+
# Check for the Terrapin vulnerability (CVE-2023-48795), and mark the vulnerable algorithms.
470+
if algs.ssh2kex is not None and \
471+
((client_audit and 'kex-strict-c-v00@openssh.com' not in algs.ssh2kex.kex_algorithms) or (not client_audit and 'kex-strict-s-v00@openssh.com' not in algs.ssh2kex.kex_algorithms)): # Strict KEX marker is not present.
472+
473+
def add_terrapin_warning(db: Dict[str, Dict[str, List[List[Optional[str]]]]], category: str, algorithm_name: str) -> None:
474+
while len(db[category][algorithm_name]) < 3:
475+
db[category][algorithm_name].append([])
476+
477+
db[category][algorithm_name][2].append("vulnerable to the Terrapin attack (CVE-2023-48795), allowing message prefix truncation")
478+
479+
db = SSH2_KexDB.get_db()
480+
481+
# Without the strict KEX marker, these algorithms are always vulnerable.
482+
add_terrapin_warning(db, "enc", "chacha20-poly1305")
483+
add_terrapin_warning(db, "enc", "chacha20-poly1305@openssh.com")
484+
485+
cbc_ciphers = []
486+
etm_macs = []
487+
488+
# Find the list of CBC ciphers the peer supports.
489+
ciphers_supported = algs.ssh2kex.client.encryption if client_audit else algs.ssh2kex.server.encryption
490+
for cipher in ciphers_supported:
491+
if cipher.endswith("-cbc"):
492+
cbc_ciphers.append(cipher)
493+
494+
# Find the list of ETM MACs the peer supports.
495+
macs_supported = algs.ssh2kex.client.mac if client_audit else algs.ssh2kex.server.mac
496+
for mac in macs_supported:
497+
if mac.endswith("-etm@openssh.com"):
498+
etm_macs.append(mac)
499+
500+
# If at least one CBC cipher and at least one ETM MAC is supported, mark them all as vulnerable.
501+
if len(cbc_ciphers) > 0 and len(etm_macs) > 0:
502+
for cipher in cbc_ciphers:
503+
add_terrapin_warning(db, "enc", cipher)
504+
505+
for mac in etm_macs:
506+
add_terrapin_warning(db, "mac", mac)
507+
469508
return algorithm_recommendation_suppress_list
470509

471510

@@ -478,7 +517,7 @@ def output(out: OutputBuffer, aconf: AuditConf, banner: Optional[Banner], header
478517
algs = Algorithms(pkm, kex)
479518

480519
# Perform post-processing on the findings to make final adjustments before outputting the results.
481-
algorithm_recommendation_suppress_list = post_process_findings(banner, algs)
520+
algorithm_recommendation_suppress_list = post_process_findings(banner, algs, client_audit)
482521

483522
with out:
484523
if print_target:

test/test_ssh2.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ def test_ssh2_server_simple(self, output_spy, virtual_socket):
164164
self.audit(out, self._conf())
165165
out.write()
166166
lines = output_spy.flush()
167-
assert len(lines) == 70
167+
assert len(lines) == 83
168168

169169
def test_ssh2_server_invalid_first_packet(self, output_spy, virtual_socket):
170170
vsocket = virtual_socket

0 commit comments

Comments
 (0)