mirror of
				https://github.com/jtesta/ssh-audit.git
				synced 2025-11-03 18:52:15 +01:00 
			
		
		
		
	Now issues a warning when 2048-bit moduli are encountered.
This commit is contained in:
		@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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:
 | 
			
		||||
 
 | 
			
		||||
@@ -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]],
 | 
			
		||||
 
 | 
			
		||||
@@ -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))
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user