Now issues a warning when 2048-bit moduli are encountered.

This commit is contained in:
Joe Testa
2023-02-06 16:27:30 -05:00
parent f9e00b6f2d
commit c9dc9a9c10
17 changed files with 93 additions and 42 deletions

View File

@ -1,7 +1,7 @@
"""
The MIT License (MIT)
Copyright (C) 2017-2021 Joe Testa (jtesta@positronsecurity.com)
Copyright (C) 2017-2023 Joe Testa (jtesta@positronsecurity.com)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@ -220,5 +220,18 @@ class GEXTest:
del lst[1]
lst.insert(1, [text])
# Moduli smaller than 3072 get flagged as a warning.
elif smallest_modulus < 3072:
lst = SSH2_KexDB.ALGORITHMS['kex'][gex_alg]
# Ensure that a warning list exists for us to append to, below.
while len(lst) < 3:
lst.append([])
# Ensure this is only added once.
text = '2048-bit modulus only provides 112-bits of symmetric strength'
if text not in lst[2]:
lst[2].append(text)
if reconnect_failed:
break

View File

@ -1,7 +1,7 @@
"""
The MIT License (MIT)
Copyright (C) 2017-2021 Joe Testa (jtesta@positronsecurity.com)
Copyright (C) 2017-2023 Joe Testa (jtesta@positronsecurity.com)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@ -54,6 +54,9 @@ class HostKeyTest:
'ssh-ed25519-cert-v01@openssh.com': {'cert': True, 'variable_key_len': False},
}
TWO2K_MODULUS_WARNING = '2048-bit modulus only provides 112-bits of symmetric strength'
@staticmethod
def run(out: 'OutputBuffer', s: 'SSH_Socket', server_kex: 'SSH2_Kex') -> None:
KEX_TO_DHGROUP = {
@ -161,24 +164,34 @@ class HostKeyTest:
elif cert is True:
server_kex.set_rsa_key_size(host_key_type, hostkey_modulus_size, ca_modulus_size)
# Keys smaller than 2048 result in a failure. Update the database accordingly.
if (cert is False) and (hostkey_modulus_size < 2048):
# Keys smaller than 2048 result in a failure. Keys smaller 3072 result in a warning. Update the database accordingly.
if (cert is False) and (hostkey_modulus_size < 3072):
for rsa_type in HostKeyTest.RSA_FAMILY:
alg_list = SSH2_KexDB.ALGORITHMS['key'][rsa_type]
# If no failure list exists, add an empty failure list.
if len(alg_list) < 2:
# Ensure that failure & warning lists exist.
while len(alg_list) < 3:
alg_list.append([])
alg_list[1].append('using small %d-bit modulus' % hostkey_modulus_size)
elif (cert is True) and ((hostkey_modulus_size < 2048) or (ca_modulus_size > 0 and ca_modulus_size < 2048)): # pylint: disable=chained-comparison
# If the key is under 2048, add to the failure list.
if hostkey_modulus_size < 2048:
alg_list[1].append('using small %d-bit modulus' % hostkey_modulus_size)
elif HostKeyTest.TWO2K_MODULUS_WARNING not in alg_list[2]: # Issue a warning about 2048-bit moduli.
alg_list[2].append(HostKeyTest.TWO2K_MODULUS_WARNING)
elif (cert is True) and ((hostkey_modulus_size < 3072) or (ca_modulus_size > 0 and ca_modulus_size < 3072)): # pylint: disable=chained-comparison
alg_list = SSH2_KexDB.ALGORITHMS['key'][host_key_type]
min_modulus = min(hostkey_modulus_size, ca_modulus_size)
min_modulus = min_modulus if min_modulus > 0 else max(hostkey_modulus_size, ca_modulus_size)
# If no failure list exists, add an empty failure list.
if len(alg_list) < 2:
# Ensure that failure & warning lists exist.
while len(alg_list) < 3:
alg_list.append([])
alg_list[1].append('using small %d-bit modulus' % min_modulus)
if (hostkey_modulus_size < 2048) or (ca_modulus_size > 0 and ca_modulus_size < 2048): # pylint: disable=chained-comparison
alg_list[1].append('using small %d-bit modulus' % min_modulus)
elif HostKeyTest.TWO2K_MODULUS_WARNING not in alg_list[2]:
alg_list[2].append(HostKeyTest.TWO2K_MODULUS_WARNING)
# 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:

View File

@ -61,6 +61,7 @@ class SSH2_KexDB: # pylint: disable=too-few-public-methods
WARN_UNTRUSTED = 'using untrusted algorithm'
WARN_OPENSSH74_UNSAFE = 'disabled (in client) since OpenSSH 7.4, unsafe algorithm'
WARN_OPENSSH72_LEGACY = 'disabled (in client) since OpenSSH 7.2, legacy algorithm'
WARN_2048BIT_MODULUS = '2048-bit modulus only provides 112-bits of symmetric strength'
INFO_OPENSSH82_FUTURE_DEPRECATION = 'a future deprecation notice has been issued in OpenSSH 8.2: https://www.openssh.com/txt/release-8.2'
INFO_OPENSSH69_CHACHA = 'default cipher since OpenSSH 6.9.'
@ -68,7 +69,7 @@ class SSH2_KexDB: # pylint: disable=too-few-public-methods
ALGORITHMS: Dict[str, Dict[str, List[List[Optional[str]]]]] = {
# Format: 'algorithm_name': [['version_first_appeared_in'], [reason_for_failure1, reason_for_failure2, ...], [warning1, warning2, ...]]
# Format: 'algorithm_name': [['version_first_appeared_in'], [reason_for_failure1, reason_for_failure2, ...], [warning1, warning2, ...], [info1, info2, ...]]
'kex': {
'diffie-hellman-group1-sha1': [['2.3.0,d0.28,l10.2', '6.6', '6.9'], [FAIL_1024BIT_MODULUS, FAIL_OPENSSH67_UNSAFE, FAIL_OPENSSH70_LOGJAM], [WARN_HASH_WEAK]],
'gss-group1-sha1-toWM5Slw5Ew8Mqkay+al2g==': [[], [FAIL_1024BIT_MODULUS, FAIL_OPENSSH67_UNSAFE, FAIL_OPENSSH70_LOGJAM], [WARN_HASH_WEAK]],
@ -77,11 +78,11 @@ class SSH2_KexDB: # pylint: disable=too-few-public-methods
'gss-gex-sha1-': [[], [], [WARN_HASH_WEAK]],
'gss-group1-sha1-eipGX3TCiQSrx573bT1o1Q==': [[], [FAIL_1024BIT_MODULUS], [WARN_HASH_WEAK]],
'gss-group1-sha1-': [[], [FAIL_1024BIT_MODULUS], [WARN_HASH_WEAK]],
'gss-group14-sha1-': [[], [], [WARN_HASH_WEAK]],
'gss-group14-sha1-eipGX3TCiQSrx573bT1o1Q==': [[], [], [WARN_HASH_WEAK]],
'gss-group14-sha1-toWM5Slw5Ew8Mqkay+al2g==': [[], [], [WARN_HASH_WEAK]],
'gss-group14-sha256-': [[]],
'gss-group14-sha256-toWM5Slw5Ew8Mqkay+al2g==': [[]],
'gss-group14-sha1-': [[], [], [WARN_HASH_WEAK, WARN_2048BIT_MODULUS]],
'gss-group14-sha1-eipGX3TCiQSrx573bT1o1Q==': [[], [], [WARN_HASH_WEAK, WARN_2048BIT_MODULUS]],
'gss-group14-sha1-toWM5Slw5Ew8Mqkay+al2g==': [[], [], [WARN_HASH_WEAK, WARN_2048BIT_MODULUS]],
'gss-group14-sha256-': [[], [], [WARN_2048BIT_MODULUS]],
'gss-group14-sha256-toWM5Slw5Ew8Mqkay+al2g==': [[], [], [WARN_2048BIT_MODULUS]],
'gss-group15-sha512-': [[]],
'gss-group15-sha512-toWM5Slw5Ew8Mqkay+al2g==': [[]],
'gss-group16-sha512-': [[]],
@ -92,9 +93,9 @@ class SSH2_KexDB: # pylint: disable=too-few-public-methods
'gss-curve448-sha512-*': [[]],
'gss-gex-sha1-*': [[], [], [WARN_HASH_WEAK]],
'gss-gex-sha256-*': [[]],
'gss-group1-sha1-*': [[], [], [WARN_HASH_WEAK]],
'gss-group14-sha1-*': [[], [], [WARN_HASH_WEAK]],
'gss-group14-sha256-*': [[]],
'gss-group1-sha1-*': [[], [FAIL_1024BIT_MODULUS], [WARN_HASH_WEAK]],
'gss-group14-sha1-*': [[], [], [WARN_HASH_WEAK, WARN_2048BIT_MODULUS]],
'gss-group14-sha256-*': [[], [], [WARN_2048BIT_MODULUS]],
'gss-group15-sha512-*': [[]],
'gss-group16-sha512-*': [[]],
'gss-group17-sha512-*': [[]],
@ -103,9 +104,9 @@ class SSH2_KexDB: # pylint: disable=too-few-public-methods
'gss-nistp384-sha256-*': [[], [FAIL_CURVES_WEAK]],
'gss-nistp521-sha512-*': [[], [FAIL_CURVES_WEAK]],
'diffie-hellman-group1-sha256': [[], [FAIL_1024BIT_MODULUS]],
'diffie-hellman-group14-sha1': [['3.9,d0.53,l10.6.0'], [], [WARN_HASH_WEAK]],
'diffie-hellman-group14-sha256': [['7.3,d2016.73']],
'diffie-hellman-group14-sha256@ssh.com': [[]],
'diffie-hellman-group14-sha1': [['3.9,d0.53,l10.6.0'], [], [WARN_HASH_WEAK, WARN_2048BIT_MODULUS]],
'diffie-hellman-group14-sha256': [['7.3,d2016.73'], [], [WARN_2048BIT_MODULUS]],
'diffie-hellman-group14-sha256@ssh.com': [[], [], [WARN_2048BIT_MODULUS]],
'diffie-hellman-group15-sha256': [[]],
'diffie-hellman-group15-sha256@ssh.com': [[]],
'diffie-hellman-group15-sha384@ssh.com': [[]],
@ -171,7 +172,7 @@ class SSH2_KexDB: # pylint: disable=too-few-public-methods
'curve448-sha512': [[]],
'kexguess2@matt.ucc.asn.au': [['d2013.57']],
'rsa1024-sha1': [[], [FAIL_1024BIT_MODULUS], [WARN_HASH_WEAK]],
'rsa2048-sha256': [[]],
'rsa2048-sha256': [[], [], [WARN_2048BIT_MODULUS]],
'sntrup4591761x25519-sha512@tinyssh.org': [['8.0', '8.4'], [], [WARN_EXPERIMENTAL]],
'sntrup761x25519-sha512@openssh.com': [['8.5'], [], []],
'kexAlgoCurve25519SHA256': [[]],
@ -225,8 +226,8 @@ class SSH2_KexDB: # pylint: disable=too-few-public-methods
'webauthn-sk-ecdsa-sha2-nistp256@openssh.com': [['8.3'], [FAIL_CURVES_WEAK]],
'ssh-xmss@openssh.com': [['7.7'], [WARN_EXPERIMENTAL]],
'ssh-xmss-cert-v01@openssh.com': [['7.7'], [WARN_EXPERIMENTAL]],
'dsa2048-sha224@libassh.org': [[], [FAIL_UNPROVEN]],
'dsa2048-sha256@libassh.org': [[], [FAIL_UNPROVEN]],
'dsa2048-sha224@libassh.org': [[], [FAIL_UNPROVEN], [WARN_2048BIT_MODULUS]],
'dsa2048-sha256@libassh.org': [[], [FAIL_UNPROVEN], [WARN_2048BIT_MODULUS]],
'dsa3072-sha256@libassh.org': [[], [FAIL_UNPROVEN]],
'ecdsa-sha2-1.3.132.0.10-cert-v01@openssh.com': [[], [FAIL_UNKNOWN]],
'eddsa-e382-shake256@libassh.org': [[], [FAIL_UNPROVEN]],

View File

@ -2,7 +2,7 @@
"""
The MIT License (MIT)
Copyright (C) 2017-2021 Joe Testa (jtesta@positronsecurity.com)
Copyright (C) 2017-2023 Joe Testa (jtesta@positronsecurity.com)
Copyright (C) 2017 Andris Raugulis (moo@arthepsy.eu)
Permission is hereby granted, free of charge, to any person obtaining a copy
@ -365,7 +365,7 @@ def output_recommendations(out: OutputBuffer, algs: Algorithms, software: Option
elif action == 'chg':
an, sg, fn = 'change', '!', out.fail
ret = False
chg_additional_info = ' (increase modulus size to 2048 bits or larger)'
chg_additional_info = ' (increase modulus size to 3072 bits or larger)'
b = '(SSH{})'.format(sshv) if sshv == 1 else ''
fm = '(rec) {0}{1}{2}-- {3} algorithm to {4}{5} {6}'
fn(fm.format(sg, name, p, alg_type, an, chg_additional_info, b))