mirror of
				https://github.com/jtesta/ssh-audit.git
				synced 2025-10-30 21:15:27 +01:00 
			
		
		
		
	Recognize libssh (software, history, compatibility, security, etc). Closes #8.
This commit is contained in:
		
							
								
								
									
										102
									
								
								ssh-audit.py
									
									
									
									
									
								
							
							
						
						
									
										102
									
								
								ssh-audit.py
									
									
									
									
									
								
							| @@ -472,6 +472,7 @@ class SSH(object): | |||||||
| 	class Product(object): | 	class Product(object): | ||||||
| 		OpenSSH = 'OpenSSH' | 		OpenSSH = 'OpenSSH' | ||||||
| 		DropbearSSH = 'Dropbear SSH' | 		DropbearSSH = 'Dropbear SSH' | ||||||
|  | 		LibSSH = 'libssh' | ||||||
| 	 | 	 | ||||||
| 	class Software(object): | 	class Software(object): | ||||||
| 		def __init__(self, vendor, product, version, patch, os): | 		def __init__(self, vendor, product, version, patch, os): | ||||||
| @@ -632,6 +633,12 @@ class SSH(object): | |||||||
| 				v = None | 				v = None | ||||||
| 				os = cls._extract_os(banner.comments) | 				os = cls._extract_os(banner.comments) | ||||||
| 				return cls(v, p, mx.group(1), patch, os) | 				return cls(v, p, mx.group(1), patch, os) | ||||||
|  | 			mx = re.match(r'^libssh-([\d\.]+\d+)(.*)', software) | ||||||
|  | 			if mx: | ||||||
|  | 				patch = cls._fix_patch(mx.group(2)) | ||||||
|  | 				v, p = None, SSH.Product.LibSSH | ||||||
|  | 				os = cls._extract_os(banner.comments) | ||||||
|  | 				return cls(v, p, mx.group(1), patch, os) | ||||||
| 			mx = re.match(r'^RomSShell_([\d\.]+\d+)(.*)', software) | 			mx = re.match(r'^RomSShell_([\d\.]+\d+)(.*)', software) | ||||||
| 			if mx: | 			if mx: | ||||||
| 				patch = cls._fix_patch(mx.group(2)) | 				patch = cls._fix_patch(mx.group(2)) | ||||||
| @@ -718,21 +725,34 @@ class SSH(object): | |||||||
| 	class Security(object): | 	class Security(object): | ||||||
| 		CVE = { | 		CVE = { | ||||||
| 			'Dropbear SSH': [ | 			'Dropbear SSH': [ | ||||||
| 				['0.44', '2015.71', 1, 'CVE-2016-3116', 5.5, 'bypass command restrictions via xauth command injection.'], | 				['0.44', '2015.71', 1, 'CVE-2016-3116', 5.5, 'bypass command restrictions via xauth command injection'], | ||||||
| 				['0.28', '2013.58', 1, 'CVE-2013-4434', 5.0, 'discover valid usernames through different time delays.'], | 				['0.28', '2013.58', 1, 'CVE-2013-4434', 5.0, 'discover valid usernames through different time delays'], | ||||||
| 				['0.28', '2013.58', 1, 'CVE-2013-4421', 5.0, 'cause DoS (memory consumption) via a compressed packet.'], | 				['0.28', '2013.58', 1, 'CVE-2013-4421', 5.0, 'cause DoS (memory consumption) via a compressed packet'], | ||||||
| 				['0.52', '2011.54', 1, 'CVE-2012-0920', 7.1, 'execute arbitrary code or bypass command restrictions.'], | 				['0.52', '2011.54', 1, 'CVE-2012-0920', 7.1, 'execute arbitrary code or bypass command restrictions'], | ||||||
| 				['0.40', '0.48.1',  1, 'CVE-2007-1099', 7.5, 'conduct a MitM attack (no warning for hostkey mismatch).'], | 				['0.40', '0.48.1',  1, 'CVE-2007-1099', 7.5, 'conduct a MitM attack (no warning for hostkey mismatch)'], | ||||||
| 				['0.28', '0.47',    1, 'CVE-2006-1206', 7.5, 'cause DoS (slot exhaustion) via large number of connections.'], | 				['0.28', '0.47',    1, 'CVE-2006-1206', 7.5, 'cause DoS (slot exhaustion) via large number of connections'], | ||||||
| 				['0.39', '0.47',    1, 'CVE-2006-0225', 4.6, 'execute arbitrary commands via scp with crafted filenames.'], | 				['0.39', '0.47',    1, 'CVE-2006-0225', 4.6, 'execute arbitrary commands via scp with crafted filenames'], | ||||||
| 				['0.28', '0.46',    1, 'CVE-2005-4178', 6.5, 'execute arbitrary code via buffer overflow vulnerability.'], | 				['0.28', '0.46',    1, 'CVE-2005-4178', 6.5, 'execute arbitrary code via buffer overflow vulnerability'], | ||||||
| 				['0.28', '0.42',    1, 'CVE-2004-2486', 7.5, 'execute arbitrary code via DSS verification code.'], | 				['0.28', '0.42',    1, 'CVE-2004-2486', 7.5, 'execute arbitrary code via DSS verification code']], | ||||||
| 			] | 			'libssh': [ | ||||||
|  | 				['0.1',   '0.7.2',  1, 'CVE-2016-0739', 4.3, 'conduct a MitM attack (weakness in DH key generation)'], | ||||||
|  | 				['0.5.1', '0.6.4',  1, 'CVE-2015-3146', 5.0, 'cause DoS via kex packets (null pointer dereference)'], | ||||||
|  | 				['0.5.1', '0.6.3',  1, 'CVE-2014-8132', 5.0, 'cause DoS via kex init packet (dangling pointer)'], | ||||||
|  | 				['0.4.7', '0.6.2',  1, 'CVE-2014-0017', 1.9, 'leak data via PRNG state reuse on forking servers'], | ||||||
|  | 				['0.4.7', '0.5.3',  1, 'CVE-2013-0176', 4.3, 'cause DoS via kex packet (null pointer dereference)'], | ||||||
|  | 				['0.4.7', '0.5.2',  1, 'CVE-2012-6063', 7.5, 'cause DoS or execute arbitrary code via sftp (double free)'], | ||||||
|  | 				['0.4.7', '0.5.2',  1, 'CVE-2012-4562', 7.5, 'cause DoS or execute arbitrary code (overflow check)'], | ||||||
|  | 				['0.4.7', '0.5.2',  1, 'CVE-2012-4561', 5.0, 'cause DoS via unspecified vectors (invalid pointer)'], | ||||||
|  | 				['0.4.7', '0.5.2',  1, 'CVE-2012-4560', 7.5, 'cause DoS or execute arbitrary code (buffer overflow)'], | ||||||
|  | 				['0.4.7', '0.5.2',  1, 'CVE-2012-4559', 6.8, 'cause DoS or execute arbitrary code (double free)']] | ||||||
| 		} | 		} | ||||||
| 		TXT = { | 		TXT = { | ||||||
| 			'Dropbear SSH': [ | 			'Dropbear SSH': [ | ||||||
| 				['0.28', '0.34', 1, 'remote root exploit', 'remote format string buffer overflow exploit (exploit-db#387).'], | 				['0.28', '0.34', 1, 'remote root exploit', 'remote format string buffer overflow exploit (exploit-db#387)']], | ||||||
| 			] | 			'libssh': [ | ||||||
|  | 				['0.3.3', '0.3.3', 1, 'null pointer check', 'missing null pointer check in "crypt_set_algorithms_server"'], | ||||||
|  | 				['0.3.3', '0.3.3', 1, 'integer overflow',   'integer overflow in "buffer_get_data"'], | ||||||
|  | 				['0.3.3', '0.3.3', 3, 'heap overflow',      'heap overflow in "packet_decrypt"']] | ||||||
| 		} | 		} | ||||||
| 	 | 	 | ||||||
| 	class Socket(ReadBuf, WriteBuf): | 	class Socket(ReadBuf, WriteBuf): | ||||||
| @@ -964,29 +984,29 @@ class KexDB(object): | |||||||
|  |  | ||||||
| 	ALGORITHMS = { | 	ALGORITHMS = { | ||||||
| 		'kex': { | 		'kex': { | ||||||
| 			'diffie-hellman-group1-sha1': [['2.3.0,d0.28', '6.6', '6.9'], [FAIL_OPENSSH67_UNSAFE, FAIL_OPENSSH70_LOGJAM], [WARN_MODULUS_SIZE, WARN_HASH_WEAK]], | 			'diffie-hellman-group1-sha1': [['2.3.0,d0.28,l10.2', '6.6', '6.9'], [FAIL_OPENSSH67_UNSAFE, FAIL_OPENSSH70_LOGJAM], [WARN_MODULUS_SIZE, WARN_HASH_WEAK]], | ||||||
| 			'diffie-hellman-group14-sha1': [['3.9,d0.53'], [], [WARN_HASH_WEAK]], | 			'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': [['7.3,d2016.73']], | ||||||
| 			'diffie-hellman-group16-sha512': [['7.3,d2016.73']], | 			'diffie-hellman-group16-sha512': [['7.3,d2016.73']], | ||||||
| 			'diffie-hellman-group18-sha512': [['7.3']], | 			'diffie-hellman-group18-sha512': [['7.3']], | ||||||
| 			'diffie-hellman-group-exchange-sha1': [['2.3.0', '6.6', None], [FAIL_OPENSSH67_UNSAFE], [WARN_HASH_WEAK]], | 			'diffie-hellman-group-exchange-sha1': [['2.3.0', '6.6', None], [FAIL_OPENSSH67_UNSAFE], [WARN_HASH_WEAK]], | ||||||
| 			'diffie-hellman-group-exchange-sha256': [['4.4'], [], [WARN_MODULUS_CUSTOM]], | 			'diffie-hellman-group-exchange-sha256': [['4.4'], [], [WARN_MODULUS_CUSTOM]], | ||||||
| 			'ecdh-sha2-nistp256': [['5.7,d2013.62'], [WARN_CURVES_WEAK]], | 			'ecdh-sha2-nistp256': [['5.7,d2013.62,l10.6.0'], [WARN_CURVES_WEAK]], | ||||||
| 			'ecdh-sha2-nistp384': [['5.7,d2013.62'], [WARN_CURVES_WEAK]], | 			'ecdh-sha2-nistp384': [['5.7,d2013.62'], [WARN_CURVES_WEAK]], | ||||||
| 			'ecdh-sha2-nistp521': [['5.7,d2013.62'], [WARN_CURVES_WEAK]], | 			'ecdh-sha2-nistp521': [['5.7,d2013.62'], [WARN_CURVES_WEAK]], | ||||||
| 			'curve25519-sha256@libssh.org': [['6.5,d2013.62']], | 			'curve25519-sha256@libssh.org': [['6.5,d2013.62,l10.6.0']], | ||||||
| 			'kexguess2@matt.ucc.asn.au': [['d2013.57']], | 			'kexguess2@matt.ucc.asn.au': [['d2013.57']], | ||||||
| 		}, | 		}, | ||||||
| 		'key': { | 		'key': { | ||||||
| 			'rsa-sha2-256': [['7.2']], | 			'rsa-sha2-256': [['7.2']], | ||||||
| 			'rsa-sha2-512': [['7.2']], | 			'rsa-sha2-512': [['7.2']], | ||||||
| 			'ssh-ed25519': [['6.5']], | 			'ssh-ed25519': [['6.5,l10.7.0']], | ||||||
| 			'ssh-ed25519-cert-v01@openssh.com': [['6.5']], | 			'ssh-ed25519-cert-v01@openssh.com': [['6.5']], | ||||||
| 			'ssh-rsa': [['2.5.0,d0.28']], | 			'ssh-rsa': [['2.5.0,d0.28,l10.2']], | ||||||
| 			'ssh-dss': [['2.1.0,d0.28', '6.9'], [FAIL_OPENSSH70_WEAK], [WARN_MODULUS_SIZE, WARN_RNDSIG_KEY]], | 			'ssh-dss': [['2.1.0,d0.28,l10.2', '6.9'], [FAIL_OPENSSH70_WEAK], [WARN_MODULUS_SIZE, WARN_RNDSIG_KEY]], | ||||||
| 			'ecdsa-sha2-nistp256': [['5.7,d2013.62'], [WARN_CURVES_WEAK], [WARN_RNDSIG_KEY]], | 			'ecdsa-sha2-nistp256': [['5.7,d2013.62,l10.6.4'], [WARN_CURVES_WEAK], [WARN_RNDSIG_KEY]], | ||||||
| 			'ecdsa-sha2-nistp384': [['5.7,d2013.62'], [WARN_CURVES_WEAK], [WARN_RNDSIG_KEY]], | 			'ecdsa-sha2-nistp384': [['5.7,d2013.62,l10.6.4'], [WARN_CURVES_WEAK], [WARN_RNDSIG_KEY]], | ||||||
| 			'ecdsa-sha2-nistp521': [['5.7,d2013.62'], [WARN_CURVES_WEAK], [WARN_RNDSIG_KEY]], | 			'ecdsa-sha2-nistp521': [['5.7,d2013.62,l10.6.4'], [WARN_CURVES_WEAK], [WARN_RNDSIG_KEY]], | ||||||
| 			'ssh-rsa-cert-v00@openssh.com': [['5.4', '6.9'], [FAIL_OPENSSH70_LEGACY], []], | 			'ssh-rsa-cert-v00@openssh.com': [['5.4', '6.9'], [FAIL_OPENSSH70_LEGACY], []], | ||||||
| 			'ssh-dss-cert-v00@openssh.com': [['5.4', '6.9'], [FAIL_OPENSSH70_LEGACY], [WARN_MODULUS_SIZE, WARN_RNDSIG_KEY]], | 			'ssh-dss-cert-v00@openssh.com': [['5.4', '6.9'], [FAIL_OPENSSH70_LEGACY], [WARN_MODULUS_SIZE, WARN_RNDSIG_KEY]], | ||||||
| 			'ssh-rsa-cert-v01@openssh.com': [['5.6']], | 			'ssh-rsa-cert-v01@openssh.com': [['5.6']], | ||||||
| @@ -996,10 +1016,10 @@ class KexDB(object): | |||||||
| 			'ecdsa-sha2-nistp521-cert-v01@openssh.com': [['5.7'], [WARN_CURVES_WEAK], [WARN_RNDSIG_KEY]], | 			'ecdsa-sha2-nistp521-cert-v01@openssh.com': [['5.7'], [WARN_CURVES_WEAK], [WARN_RNDSIG_KEY]], | ||||||
| 		}, | 		}, | ||||||
| 		'enc': { | 		'enc': { | ||||||
| 			'none': [['1.2.2,d2013.56'], [FAIL_PLAINTEXT]], | 			'none': [['1.2.2,d2013.56,l10.2'], [FAIL_PLAINTEXT]], | ||||||
| 			'3des-cbc': [['1.2.2,d0.28', '6.6', None], [FAIL_OPENSSH67_UNSAFE], [WARN_CIPHER_WEAK, WARN_CIPHER_MODE, WARN_BLOCK_SIZE]], | 			'3des-cbc': [['1.2.2,d0.28,l10.2', '6.6', None], [FAIL_OPENSSH67_UNSAFE], [WARN_CIPHER_WEAK, WARN_CIPHER_MODE, WARN_BLOCK_SIZE]], | ||||||
| 			'3des-ctr': [['d0.52']], | 			'3des-ctr': [['d0.52']], | ||||||
| 			'blowfish-cbc': [['1.2.2,d0.28', '6.6,d0.52', '7.1,d0.52'], [FAIL_OPENSSH67_UNSAFE, FAIL_DBEAR53_DISABLED], [WARN_OPENSSH72_LEGACY, WARN_CIPHER_MODE, WARN_BLOCK_SIZE]], | 			'blowfish-cbc': [['1.2.2,d0.28,l10.2', '6.6,d0.52', '7.1,d0.52'], [FAIL_OPENSSH67_UNSAFE, FAIL_DBEAR53_DISABLED], [WARN_OPENSSH72_LEGACY, WARN_CIPHER_MODE, WARN_BLOCK_SIZE]], | ||||||
| 			'twofish-cbc': [['d0.28', 'd2014.66'], [FAIL_DBEAR67_DISABLED], [WARN_CIPHER_MODE]], | 			'twofish-cbc': [['d0.28', 'd2014.66'], [FAIL_DBEAR67_DISABLED], [WARN_CIPHER_MODE]], | ||||||
| 			'twofish128-cbc': [['d0.47', 'd2014.66'], [FAIL_DBEAR67_DISABLED], [WARN_CIPHER_MODE]], | 			'twofish128-cbc': [['d0.47', 'd2014.66'], [FAIL_DBEAR67_DISABLED], [WARN_CIPHER_MODE]], | ||||||
| 			'twofish256-cbc': [['d0.47', 'd2014.66'], [FAIL_DBEAR67_DISABLED], [WARN_CIPHER_MODE]], | 			'twofish256-cbc': [['d0.47', 'd2014.66'], [FAIL_DBEAR67_DISABLED], [WARN_CIPHER_MODE]], | ||||||
| @@ -1009,27 +1029,27 @@ class KexDB(object): | |||||||
| 			'arcfour': [['2.1.0', '6.6', '7.1'], [FAIL_OPENSSH67_UNSAFE], [WARN_OPENSSH72_LEGACY, WARN_CIPHER_WEAK]], | 			'arcfour': [['2.1.0', '6.6', '7.1'], [FAIL_OPENSSH67_UNSAFE], [WARN_OPENSSH72_LEGACY, WARN_CIPHER_WEAK]], | ||||||
| 			'arcfour128': [['4.2', '6.6', '7.1'], [FAIL_OPENSSH67_UNSAFE], [WARN_OPENSSH72_LEGACY, WARN_CIPHER_WEAK]], | 			'arcfour128': [['4.2', '6.6', '7.1'], [FAIL_OPENSSH67_UNSAFE], [WARN_OPENSSH72_LEGACY, WARN_CIPHER_WEAK]], | ||||||
| 			'arcfour256': [['4.2', '6.6', '7.1'], [FAIL_OPENSSH67_UNSAFE], [WARN_OPENSSH72_LEGACY, WARN_CIPHER_WEAK]], | 			'arcfour256': [['4.2', '6.6', '7.1'], [FAIL_OPENSSH67_UNSAFE], [WARN_OPENSSH72_LEGACY, WARN_CIPHER_WEAK]], | ||||||
| 			'aes128-cbc': [['2.3.0,d0.28', '6.6', None], [FAIL_OPENSSH67_UNSAFE], [WARN_CIPHER_MODE]], | 			'aes128-cbc': [['2.3.0,d0.28,l10.2', '6.6', None], [FAIL_OPENSSH67_UNSAFE], [WARN_CIPHER_MODE]], | ||||||
| 			'aes192-cbc': [['2.3.0', '6.6', None], [FAIL_OPENSSH67_UNSAFE], [WARN_CIPHER_MODE]], | 			'aes192-cbc': [['2.3.0,l10.2', '6.6', None], [FAIL_OPENSSH67_UNSAFE], [WARN_CIPHER_MODE]], | ||||||
| 			'aes256-cbc': [['2.3.0,d0.47', '6.6', None], [FAIL_OPENSSH67_UNSAFE], [WARN_CIPHER_MODE]], | 			'aes256-cbc': [['2.3.0,d0.47,l10.2', '6.6', None], [FAIL_OPENSSH67_UNSAFE], [WARN_CIPHER_MODE]], | ||||||
| 			'rijndael128-cbc': [['2.3.0', '3.0.2'], [FAIL_OPENSSH31_REMOVE], [WARN_CIPHER_MODE]], | 			'rijndael128-cbc': [['2.3.0', '3.0.2'], [FAIL_OPENSSH31_REMOVE], [WARN_CIPHER_MODE]], | ||||||
| 			'rijndael192-cbc': [['2.3.0', '3.0.2'], [FAIL_OPENSSH31_REMOVE], [WARN_CIPHER_MODE]], | 			'rijndael192-cbc': [['2.3.0', '3.0.2'], [FAIL_OPENSSH31_REMOVE], [WARN_CIPHER_MODE]], | ||||||
| 			'rijndael256-cbc': [['2.3.0', '3.0.2'], [FAIL_OPENSSH31_REMOVE], [WARN_CIPHER_MODE]], | 			'rijndael256-cbc': [['2.3.0', '3.0.2'], [FAIL_OPENSSH31_REMOVE], [WARN_CIPHER_MODE]], | ||||||
| 			'rijndael-cbc@lysator.liu.se': [['2.3.0', '6.6', '7.1'], [FAIL_OPENSSH67_UNSAFE], [WARN_OPENSSH72_LEGACY, WARN_CIPHER_MODE]], | 			'rijndael-cbc@lysator.liu.se': [['2.3.0', '6.6', '7.1'], [FAIL_OPENSSH67_UNSAFE], [WARN_OPENSSH72_LEGACY, WARN_CIPHER_MODE]], | ||||||
| 			'aes128-ctr': [['3.7,d0.52']], | 			'aes128-ctr': [['3.7,d0.52,l10.4.1']], | ||||||
| 			'aes192-ctr': [['3.7']], | 			'aes192-ctr': [['3.7,l10.4.1']], | ||||||
| 			'aes256-ctr': [['3.7,d0.52']], | 			'aes256-ctr': [['3.7,d0.52,l10.4.1']], | ||||||
| 			'aes128-gcm@openssh.com': [['6.2']], | 			'aes128-gcm@openssh.com': [['6.2']], | ||||||
| 			'aes256-gcm@openssh.com': [['6.2']], | 			'aes256-gcm@openssh.com': [['6.2']], | ||||||
| 			'chacha20-poly1305@openssh.com': [['6.5'], [], [], [INFO_OPENSSH69_CHACHA]], | 			'chacha20-poly1305@openssh.com': [['6.5'], [], [], [INFO_OPENSSH69_CHACHA]], | ||||||
| 		}, | 		}, | ||||||
| 		'mac': { | 		'mac': { | ||||||
| 			'none': [['d2013.56'], [FAIL_PLAINTEXT]], | 			'none': [['d2013.56'], [FAIL_PLAINTEXT]], | ||||||
| 			'hmac-sha1': [['2.1.0,d0.28'], [], [WARN_ENCRYPT_AND_MAC, WARN_HASH_WEAK]], | 			'hmac-sha1': [['2.1.0,d0.28,l10.2'], [], [WARN_ENCRYPT_AND_MAC, WARN_HASH_WEAK]], | ||||||
| 			'hmac-sha1-96': [['2.5.0,d0.47', '6.6', '7.1'], [FAIL_OPENSSH67_UNSAFE], [WARN_OPENSSH72_LEGACY, WARN_ENCRYPT_AND_MAC, WARN_HASH_WEAK]], | 			'hmac-sha1-96': [['2.5.0,d0.47', '6.6', '7.1'], [FAIL_OPENSSH67_UNSAFE], [WARN_OPENSSH72_LEGACY, WARN_ENCRYPT_AND_MAC, WARN_HASH_WEAK]], | ||||||
| 			'hmac-sha2-256': [['5.9,d2013.56'], [], [WARN_ENCRYPT_AND_MAC]], | 			'hmac-sha2-256': [['5.9,d2013.56,l10.7.0'], [], [WARN_ENCRYPT_AND_MAC]], | ||||||
| 			'hmac-sha2-256-96': [['5.9', '6.0'], [FAIL_OPENSSH61_REMOVE], [WARN_ENCRYPT_AND_MAC]], | 			'hmac-sha2-256-96': [['5.9', '6.0'], [FAIL_OPENSSH61_REMOVE], [WARN_ENCRYPT_AND_MAC]], | ||||||
| 			'hmac-sha2-512': [['5.9,d2013.56'], [], [WARN_ENCRYPT_AND_MAC]], | 			'hmac-sha2-512': [['5.9,d2013.56,l10.7.0'], [], [WARN_ENCRYPT_AND_MAC]], | ||||||
| 			'hmac-sha2-512-96': [['5.9', '6.0'], [FAIL_OPENSSH61_REMOVE], [WARN_ENCRYPT_AND_MAC]], | 			'hmac-sha2-512-96': [['5.9', '6.0'], [FAIL_OPENSSH61_REMOVE], [WARN_ENCRYPT_AND_MAC]], | ||||||
| 			'hmac-md5': [['2.1.0,d0.28', '6.6', '7.1'], [FAIL_OPENSSH67_UNSAFE], [WARN_OPENSSH72_LEGACY, WARN_ENCRYPT_AND_MAC, WARN_HASH_WEAK]], | 			'hmac-md5': [['2.1.0,d0.28', '6.6', '7.1'], [FAIL_OPENSSH67_UNSAFE], [WARN_OPENSSH72_LEGACY, WARN_ENCRYPT_AND_MAC, WARN_HASH_WEAK]], | ||||||
| 			'hmac-md5-96': [['2.5.0', '6.6', '7.1'], [FAIL_OPENSSH67_UNSAFE], [WARN_OPENSSH72_LEGACY, WARN_ENCRYPT_AND_MAC, WARN_HASH_WEAK]], | 			'hmac-md5-96': [['2.5.0', '6.6', '7.1'], [FAIL_OPENSSH67_UNSAFE], [WARN_OPENSSH72_LEGACY, WARN_ENCRYPT_AND_MAC, WARN_HASH_WEAK]], | ||||||
| @@ -1053,6 +1073,8 @@ class KexDB(object): | |||||||
| def get_ssh_version(version_desc): | def get_ssh_version(version_desc): | ||||||
| 	if version_desc.startswith('d'): | 	if version_desc.startswith('d'): | ||||||
| 		return (SSH.Product.DropbearSSH, version_desc[1:]) | 		return (SSH.Product.DropbearSSH, version_desc[1:]) | ||||||
|  | 	elif version_desc.startswith('l1'): | ||||||
|  | 		return (SSH.Product.LibSSH, version_desc[2:]) | ||||||
| 	else: | 	else: | ||||||
| 		return (SSH.Product.OpenSSH, version_desc) | 		return (SSH.Product.OpenSSH, version_desc) | ||||||
|  |  | ||||||
| @@ -1116,6 +1138,8 @@ def get_alg_since_text(alg_desc): | |||||||
| 		ssh_prefix, ssh_version = get_ssh_version(v) | 		ssh_prefix, ssh_version = get_ssh_version(v) | ||||||
| 		if not ssh_version: | 		if not ssh_version: | ||||||
| 			continue | 			continue | ||||||
|  | 		if ssh_prefix in [SSH.Product.LibSSH]: | ||||||
|  | 			continue | ||||||
| 		if ssh_version.endswith('C'): | 		if ssh_version.endswith('C'): | ||||||
| 			ssh_version = '{0} (client only)'.format(ssh_version[:-1]) | 			ssh_version = '{0} (client only)'.format(ssh_version[:-1]) | ||||||
| 		tv.append('{0} {1}'.format(ssh_prefix, ssh_version)) | 		tv.append('{0} {1}'.format(ssh_prefix, ssh_version)) | ||||||
| @@ -1142,12 +1166,15 @@ def get_alg_pairs(kex, pkm): | |||||||
|  |  | ||||||
| def get_alg_recommendations(software, kex, pkm, for_server=True): | def get_alg_recommendations(software, kex, pkm, for_server=True): | ||||||
| 	alg_pairs = get_alg_pairs(kex, pkm) | 	alg_pairs = get_alg_pairs(kex, pkm) | ||||||
|  | 	vproducts = [SSH.Product.OpenSSH, | ||||||
|  | 	             SSH.Product.DropbearSSH, | ||||||
|  | 	             SSH.Product.LibSSH] | ||||||
| 	if software is not None: | 	if software is not None: | ||||||
| 		if software.product not in [SSH.Product.OpenSSH, SSH.Product.DropbearSSH]: | 		if software.product not in vproducts: | ||||||
| 			software = None | 			software = None | ||||||
| 	if software is None: | 	if software is None: | ||||||
| 		ssh_timeframe = get_ssh_timeframe(alg_pairs, for_server) | 		ssh_timeframe = get_ssh_timeframe(alg_pairs, for_server) | ||||||
| 		for product in [SSH.Product.OpenSSH, SSH.Product.DropbearSSH]: | 		for product in vproducts: | ||||||
| 			if product not in ssh_timeframe: | 			if product not in ssh_timeframe: | ||||||
| 				continue | 				continue | ||||||
| 			version = ssh_timeframe[product][0] | 			version = ssh_timeframe[product][0] | ||||||
| @@ -1302,7 +1329,8 @@ def output_security_sub(sub, software, padlen): | |||||||
| 			continue | 			continue | ||||||
| 		target, name = line[2:4] | 		target, name = line[2:4] | ||||||
| 		is_server, is_client = target & 1 == 1, target & 2 == 2 | 		is_server, is_client = target & 1 == 1, target & 2 == 2 | ||||||
| 		if is_client: | 		is_local = target & 4 == 4 | ||||||
|  | 		if not is_server: | ||||||
| 			continue | 			continue | ||||||
| 		p = '' if out.batch else ' ' * (padlen - len(name)) | 		p = '' if out.batch else ' ' * (padlen - len(name)) | ||||||
| 		if sub == 'cve': | 		if sub == 'cve': | ||||||
|   | |||||||
| @@ -2,6 +2,7 @@ | |||||||
| # -*- coding: utf-8 -*- | # -*- coding: utf-8 -*- | ||||||
| import pytest | import pytest | ||||||
|  |  | ||||||
|  |  | ||||||
| class TestVersionCompare(object): | class TestVersionCompare(object): | ||||||
| 	@pytest.fixture(autouse=True) | 	@pytest.fixture(autouse=True) | ||||||
| 	def init(self, ssh_audit): | 	def init(self, ssh_audit): | ||||||
| @@ -15,26 +16,30 @@ class TestVersionCompare(object): | |||||||
| 		b = self.ssh.Banner.parse('SSH-2.0-OpenSSH_{0}'.format(v)) | 		b = self.ssh.Banner.parse('SSH-2.0-OpenSSH_{0}'.format(v)) | ||||||
| 		return self.ssh.Software.parse(b) | 		return self.ssh.Software.parse(b) | ||||||
| 	 | 	 | ||||||
|  | 	def get_libssh_software(self, v): | ||||||
|  | 		b = self.ssh.Banner.parse('SSH-2.0-libssh-{0}'.format(v)) | ||||||
|  | 		return self.ssh.Software.parse(b) | ||||||
|  | 	 | ||||||
| 	def test_dropbear_compare_version_pre_years(self): | 	def test_dropbear_compare_version_pre_years(self): | ||||||
| 		s = self.get_dropbear_software('0.44') | 		s = self.get_dropbear_software('0.44') | ||||||
| 		assert s.compare_version('0.43') > 0 | 		assert s.compare_version('0.43') > 0 | ||||||
| 		assert s.compare_version('0.44') == 0 | 		assert s.compare_version('0.44') == 0 | ||||||
| 		assert s.compare_version('0.45') < 0 | 		assert s.compare_version('0.45') < 0 | ||||||
| 		assert s.between_versions('0.43', '0.45') == True | 		assert s.between_versions('0.43', '0.45') | ||||||
| 	 | 	 | ||||||
| 	def test_dropbear_compare_version_with_years(self): | 	def test_dropbear_compare_version_with_years(self): | ||||||
| 		s = self.get_dropbear_software('2015.71') | 		s = self.get_dropbear_software('2015.71') | ||||||
| 		assert s.compare_version('2014.67') > 0 | 		assert s.compare_version('2014.67') > 0 | ||||||
| 		assert s.compare_version('2015.71') == 0 | 		assert s.compare_version('2015.71') == 0 | ||||||
| 		assert s.compare_version('2016.74') < 0 | 		assert s.compare_version('2016.74') < 0 | ||||||
| 		assert s.between_versions('2014.67', '2016.74') == True | 		assert s.between_versions('2014.67', '2016.74') | ||||||
| 	 | 	 | ||||||
| 	def test_dropbear_compare_version_mixed(self): | 	def test_dropbear_compare_version_mixed(self): | ||||||
| 		s = self.get_dropbear_software('0.53.1') | 		s = self.get_dropbear_software('0.53.1') | ||||||
| 		assert s.compare_version('0.53') > 0 | 		assert s.compare_version('0.53') > 0 | ||||||
| 		assert s.compare_version('0.53.1') == 0 | 		assert s.compare_version('0.53.1') == 0 | ||||||
| 		assert s.compare_version('2011.54') < 0 | 		assert s.compare_version('2011.54') < 0 | ||||||
| 		assert s.between_versions('0.53', '2011.54') == True | 		assert s.between_versions('0.53', '2011.54') | ||||||
| 	 | 	 | ||||||
| 	def test_dropbear_compare_version_patchlevel(self): | 	def test_dropbear_compare_version_patchlevel(self): | ||||||
| 		s1 = self.get_dropbear_software('0.44') | 		s1 = self.get_dropbear_software('0.44') | ||||||
| @@ -85,8 +90,7 @@ class TestVersionCompare(object): | |||||||
| 		assert s.compare_version('3.7') > 0 | 		assert s.compare_version('3.7') > 0 | ||||||
| 		assert s.compare_version('3.7.1') == 0 | 		assert s.compare_version('3.7.1') == 0 | ||||||
| 		assert s.compare_version('3.8') < 0 | 		assert s.compare_version('3.8') < 0 | ||||||
| 		assert s.between_versions('3.7', '3.8') == True | 		assert s.between_versions('3.7', '3.8') | ||||||
| 		 |  | ||||||
| 	 | 	 | ||||||
| 	def test_openssh_compare_version_patchlevel(self): | 	def test_openssh_compare_version_patchlevel(self): | ||||||
| 		s1 = self.get_openssh_software('2.1.1') | 		s1 = self.get_openssh_software('2.1.1') | ||||||
| @@ -130,3 +134,36 @@ class TestVersionCompare(object): | |||||||
| 			if i + 1 < l: | 			if i + 1 < l: | ||||||
| 				vnext = versions[i + 1] | 				vnext = versions[i + 1] | ||||||
| 				assert s.compare_version(vnext) < 0 | 				assert s.compare_version(vnext) < 0 | ||||||
|  | 	 | ||||||
|  | 	def test_libssh_compare_version_simple(self): | ||||||
|  | 		s = self.get_libssh_software('0.3') | ||||||
|  | 		assert s.compare_version('0.2') > 0 | ||||||
|  | 		assert s.compare_version('0.3') == 0 | ||||||
|  | 		assert s.compare_version('0.3.1') < 0 | ||||||
|  | 		assert s.between_versions('0.2', '0.3.1') | ||||||
|  | 	 | ||||||
|  | 	def test_libssh_compare_version_sequential(self): | ||||||
|  | 		versions = [] | ||||||
|  | 		for v in ['0.2', '0.3']: | ||||||
|  | 			versions.append(v) | ||||||
|  | 		for i in range(1, 5): | ||||||
|  | 			versions.append('0.3.{0}'.format(i)) | ||||||
|  | 		for i in range(0, 9): | ||||||
|  | 			versions.append('0.4.{0}'.format(i)) | ||||||
|  | 		for i in range(0, 6): | ||||||
|  | 			versions.append('0.5.{0}'.format(i)) | ||||||
|  | 		for i in range(0, 6): | ||||||
|  | 			versions.append('0.6.{0}'.format(i)) | ||||||
|  | 		for i in range(0, 4): | ||||||
|  | 			versions.append('0.7.{0}'.format(i)) | ||||||
|  | 		l = len(versions) | ||||||
|  | 		for i in range(l): | ||||||
|  | 			v = versions[i] | ||||||
|  | 			s = self.get_libssh_software(v) | ||||||
|  | 			assert s.compare_version(v) == 0 | ||||||
|  | 			if i - 1 >= 0: | ||||||
|  | 				vbefore = versions[i - 1] | ||||||
|  | 				assert s.compare_version(vbefore) > 0 | ||||||
|  | 			if i + 1 < l: | ||||||
|  | 				vnext = versions[i + 1] | ||||||
|  | 				assert s.compare_version(vnext) < 0 | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Andris Raugulis
					Andris Raugulis