mirror of
				https://github.com/jtesta/ssh-audit.git
				synced 2025-10-30 21:15:27 +01:00 
			
		
		
		
	Algorithm lookup (#53)
* Adding ssh-audit.py to algorithm_lookup_branch * Removed the use of an error handler from algorithm_lookup and implemented suggestions made by jugmac00 and jtesta
This commit is contained in:
		| @@ -36,6 +36,7 @@ usage: ssh-audit.py [options] <host> | |||||||
|    -j,  --json             JSON output |    -j,  --json             JSON output | ||||||
|    -l,  --level=<level>    minimum output level (info|warn|fail) |    -l,  --level=<level>    minimum output level (info|warn|fail) | ||||||
|    -L,  --list-policies    list all the official, built-in policies |    -L,  --list-policies    list all the official, built-in policies | ||||||
|  |         --lookup=<alg>     performs an algorithm lookup (accepts a comma separated list) | ||||||
|    -M,  --make-policy=<policy.txt>  creates a policy based on the target server |    -M,  --make-policy=<policy.txt>  creates a policy based on the target server | ||||||
|                                     (i.e.: the target server has the ideal |                                     (i.e.: the target server has the ideal | ||||||
|                                     configuration that other servers should |                                     configuration that other servers should | ||||||
|   | |||||||
							
								
								
									
										70
									
								
								ssh-audit.py
									
									
									
									
									
								
							
							
						
						
									
										70
									
								
								ssh-audit.py
									
									
									
									
									
								
							| @@ -79,6 +79,7 @@ def usage(err: Optional[str] = None) -> None: | |||||||
|     uout.info('   -j,  --json             JSON output') |     uout.info('   -j,  --json             JSON output') | ||||||
|     uout.info('   -l,  --level=<level>    minimum output level (info|warn|fail)') |     uout.info('   -l,  --level=<level>    minimum output level (info|warn|fail)') | ||||||
|     uout.info('   -L,  --list-policies    list all the official, built-in policies') |     uout.info('   -L,  --list-policies    list all the official, built-in policies') | ||||||
|  |     uout.info('        --lookup=<alg>     performs an algorithm lookup (accepts a comma separated list)') | ||||||
|     uout.info('   -M,  --make-policy=<policy.txt>  creates a policy based on the target server\n                                    (i.e.: the target server has the ideal\n                                    configuration that other servers should\n                                    adhere to)') |     uout.info('   -M,  --make-policy=<policy.txt>  creates a policy based on the target server\n                                    (i.e.: the target server has the ideal\n                                    configuration that other servers should\n                                    adhere to)') | ||||||
|     uout.info('   -n,  --no-colors        disable colors') |     uout.info('   -n,  --no-colors        disable colors') | ||||||
|     uout.info('   -p,  --port=<port>      port to connect') |     uout.info('   -p,  --port=<port>      port to connect') | ||||||
| @@ -477,6 +478,7 @@ class AuditConf: | |||||||
|         self.target_file = None  # type: Optional[str] |         self.target_file = None  # type: Optional[str] | ||||||
|         self.target_list = []  # type: List[str] |         self.target_list = []  # type: List[str] | ||||||
|         self.list_policies = False |         self.list_policies = False | ||||||
|  |         self.lookup = '' | ||||||
|  |  | ||||||
|     def __setattr__(self, name: str, value: Union[str, int, float, bool, Sequence[int]]) -> None: |     def __setattr__(self, name: str, value: Union[str, int, float, bool, Sequence[int]]) -> None: | ||||||
|         valid = False |         valid = False | ||||||
| @@ -518,7 +520,7 @@ class AuditConf: | |||||||
|             if value == -1.0: |             if value == -1.0: | ||||||
|                 raise ValueError('invalid timeout: {}'.format(value)) |                 raise ValueError('invalid timeout: {}'.format(value)) | ||||||
|             valid = True |             valid = True | ||||||
|         elif name in ['policy_file', 'policy', 'target_file', 'target_list']: |         elif name in ['policy_file', 'policy', 'target_file', 'target_list', 'lookup']: | ||||||
|             valid = True |             valid = True | ||||||
|  |  | ||||||
|         if valid: |         if valid: | ||||||
| @@ -530,7 +532,7 @@ class AuditConf: | |||||||
|         aconf = cls() |         aconf = cls() | ||||||
|         try: |         try: | ||||||
|             sopts = 'h1246M:p:P:jbcnvl:t:T:L' |             sopts = 'h1246M:p:P:jbcnvl:t:T:L' | ||||||
|             lopts = ['help', 'ssh1', 'ssh2', 'ipv4', 'ipv6', 'make-policy=', 'port=', 'policy=', 'json', 'batch', 'client-audit', 'no-colors', 'verbose', 'level=', 'timeout=', 'targets=', 'list-policies'] |             lopts = ['help', 'ssh1', 'ssh2', 'ipv4', 'ipv6', 'make-policy=', 'port=', 'policy=', 'json', 'batch', 'client-audit', 'no-colors', 'verbose', 'level=', 'timeout=', 'targets=', 'list-policies', 'lookup='] | ||||||
|             opts, args = getopt.gnu_getopt(args, sopts, lopts) |             opts, args = getopt.gnu_getopt(args, sopts, lopts) | ||||||
|         except getopt.GetoptError as err: |         except getopt.GetoptError as err: | ||||||
|             usage_cb(str(err)) |             usage_cb(str(err)) | ||||||
| @@ -578,10 +580,15 @@ class AuditConf: | |||||||
|                 aconf.target_file = a |                 aconf.target_file = a | ||||||
|             elif o in ('-L', '--list-policies'): |             elif o in ('-L', '--list-policies'): | ||||||
|                 aconf.list_policies = True |                 aconf.list_policies = True | ||||||
|  |             elif o in ('--lookup'): | ||||||
|  |                 aconf.lookup = a | ||||||
|  |  | ||||||
|         if len(args) == 0 and aconf.client_audit is False and aconf.target_file is None and aconf.list_policies is False: |         if len(args) == 0 and aconf.client_audit is False and aconf.target_file is None and aconf.list_policies is False and aconf.lookup == '': | ||||||
|             usage_cb() |             usage_cb() | ||||||
|  |  | ||||||
|  |         if aconf.lookup != '': | ||||||
|  |             return aconf | ||||||
|  |  | ||||||
|         if aconf.list_policies: |         if aconf.list_policies: | ||||||
|             list_policies() |             list_policies() | ||||||
|             sys.exit(PROGRAM_RETVAL_GOOD) |             sys.exit(PROGRAM_RETVAL_GOOD) | ||||||
| @@ -3714,6 +3721,59 @@ def audit(aconf: AuditConf, sshv: Optional[int] = None, print_target: bool = Fal | |||||||
|     return program_retval |     return program_retval | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def algorithm_lookup(alg_names: str) -> int: | ||||||
|  |     alg_types = { | ||||||
|  |         'kex': 'key exchange algorithms', | ||||||
|  |         'key': 'host-key algorithms', | ||||||
|  |         'mac': 'message authentication code algorithms', | ||||||
|  |         'enc': 'encryption algorithms (ciphers)' | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     algorithm_names = alg_names.split(",") | ||||||
|  |     adb = SSH2.KexDB.ALGORITHMS | ||||||
|  |  | ||||||
|  |     # Use nested dictionary comprehension to iterate an outer dictionary where | ||||||
|  |     # each key is an alg type that consists of a value (which is itself a | ||||||
|  |     # dictionary) of alg names. Filter the alg names against the user supplied | ||||||
|  |     # list of names. | ||||||
|  |     algorithms_dict = { | ||||||
|  |         outer_k: { | ||||||
|  |             inner_k | ||||||
|  |             for (inner_k, inner_v) in outer_v.items() | ||||||
|  |             if inner_k in algorithm_names | ||||||
|  |         } | ||||||
|  |         for (outer_k, outer_v) in adb.items() | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     unknown_algorithms = []  # type: List[str] | ||||||
|  |     padding = len(max(algorithm_names, key=len)) | ||||||
|  |  | ||||||
|  |     for alg_type in alg_types: | ||||||
|  |         if len(algorithms_dict[alg_type]) > 0: | ||||||
|  |             title = str(alg_types.get(alg_type)) | ||||||
|  |             retval = output_algorithms(title, adb, alg_type, algorithms_dict[alg_type], unknown_algorithms, False, PROGRAM_RETVAL_GOOD, padding) | ||||||
|  |  | ||||||
|  |     algorithms_dict_flattened = [ | ||||||
|  |         alg_name | ||||||
|  |         for val in algorithms_dict.values() | ||||||
|  |         for alg_name in val | ||||||
|  |     ] | ||||||
|  |  | ||||||
|  |     algorithms_not_found = [ | ||||||
|  |         alg_name | ||||||
|  |         for alg_name in algorithm_names | ||||||
|  |         if alg_name not in algorithms_dict_flattened | ||||||
|  |     ] | ||||||
|  |  | ||||||
|  |     if len(algorithms_not_found) > 0: | ||||||
|  |         retval = PROGRAM_RETVAL_FAILURE | ||||||
|  |         out.head('# unknown algorithms') | ||||||
|  |         for algorithm_not_found in algorithms_not_found: | ||||||
|  |             out.fail(algorithm_not_found) | ||||||
|  |  | ||||||
|  |     return retval | ||||||
|  |  | ||||||
|  |  | ||||||
| utils = Utils() | utils = Utils() | ||||||
| out = Output() | out = Output() | ||||||
|  |  | ||||||
| @@ -3721,6 +3781,10 @@ out = Output() | |||||||
| def main() -> int: | def main() -> int: | ||||||
|     aconf = AuditConf.from_cmdline(sys.argv[1:], usage) |     aconf = AuditConf.from_cmdline(sys.argv[1:], usage) | ||||||
|  |  | ||||||
|  |     if aconf.lookup != '': | ||||||
|  |         retval = algorithm_lookup(aconf.lookup) | ||||||
|  |         sys.exit(retval) | ||||||
|  |  | ||||||
|     # If multiple targets were specified... |     # If multiple targets were specified... | ||||||
|     if len(aconf.target_list) > 0: |     if len(aconf.target_list) > 0: | ||||||
|         ret = PROGRAM_RETVAL_GOOD |         ret = PROGRAM_RETVAL_GOOD | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 thecliguy
					thecliguy