def test_plugin_process_pool(self): server_info = ServerConnectivityInfo(hostname=u'www.google.com') server_info.test_connectivity_to_server() # Get the list of available plugins sslyze_plugins = PluginsFinder.get() # Create a process pool to run scanning commands concurrently plugins_process_pool = PluginsProcessPool(sslyze_plugins) # Queue some scan commands that are quick plugins_process_pool.queue_plugin_task(server_info, 'certinfo_basic') plugins_process_pool.queue_plugin_task(server_info, 'reneg') plugins_process_pool.queue_plugin_task(server_info, 'compression') # Process the results nb_results = 0 for plugin_result in plugins_process_pool.get_results(): self.assertTrue(plugin_result.as_text()) self.assertTrue(plugin_result.as_xml()) nb_results += 1 self.assertEquals(nb_results, 3)
def test_plugin_process_pool(self): server_info = ServerConnectivityInfo(hostname=u'www.google.com') server_info.test_connectivity_to_server() # Get the list of available plugins sslyze_plugins = PluginsFinder.get() # Create a process pool to run scanning commands concurrently plugins_process_pool = PluginsProcessPool(sslyze_plugins) # Queue some scan commands that are quick plugins_process_pool.queue_plugin_task(server_info, 'certinfo_basic') plugins_process_pool.queue_plugin_task(server_info, 'reneg') plugins_process_pool.queue_plugin_task(server_info, 'compression') # Process the results nb_results = 0 for plugin_result in plugins_process_pool.get_results(): self.assertTrue(plugin_result.as_text()) self.assertTrue(plugin_result.as_xml()) nb_results +=1 self.assertEquals(nb_results, 3)
def main(): # For py2exe builds freeze_support() # Handle SIGINT to terminate processes signal.signal(signal.SIGINT, sigint_handler) start_time = time() #--PLUGINS INITIALIZATION-- sslyze_plugins = PluginsFinder() available_plugins = sslyze_plugins.get_plugins() available_commands = sslyze_plugins.get_commands() # Create the command line parser and the list of available options sslyze_parser = CommandLineParser(available_plugins, __version__) online_servers_list = [] invalid_servers_list = [] # Parse the command line try: good_server_list, bad_server_list, args_command_list = sslyze_parser.parse_command_line() invalid_servers_list.extend(bad_server_list) except CommandLineParsingError as e: print e.get_error_msg() return should_print_text_results = not args_command_list.quiet and args_command_list.xml_file != '-' \ and args_command_list.json_file != '-' if should_print_text_results: print '\n\n\n' + _format_title('Available plugins') for plugin in available_plugins: print ' ' + plugin.__name__ print '\n\n' #--PROCESSES INITIALIZATION-- if args_command_list.https_tunnel: # Maximum one process to not kill the proxy plugins_process_pool = PluginsProcessPool(sslyze_plugins, args_command_list.nb_retries, args_command_list.timeout, max_processes_nb=1) else: plugins_process_pool = PluginsProcessPool(sslyze_plugins, args_command_list.nb_retries, args_command_list.timeout) #--TESTING SECTION-- # Figure out which hosts are up and fill the task queue with work to do if should_print_text_results: print _format_title('Checking host(s) availability') connectivity_tester = ServersConnectivityTester(good_server_list) connectivity_tester.start_connectivity_testing() SERVER_OK_FORMAT = ' {host}:{port:<25} => {ip_address} {client_auth_msg}' SERVER_INVALID_FORMAT = ' {server_string:<35} => WARNING: {error_msg}; discarding corresponding tasks.' # Store and print servers we were able to connect to for server_connectivity_info in connectivity_tester.get_reachable_servers(): online_servers_list.append(server_connectivity_info) if should_print_text_results: client_auth_msg = '' client_auth_requirement = server_connectivity_info.client_auth_requirement if client_auth_requirement == ClientAuthenticationServerConfigurationEnum.REQUIRED: client_auth_msg = ' WARNING: Server REQUIRED client authentication, specific plugins will fail.' elif client_auth_requirement == ClientAuthenticationServerConfigurationEnum.OPTIONAL: client_auth_msg = ' WARNING: Server requested optional client authentication' print SERVER_OK_FORMAT.format(host=server_connectivity_info.hostname, port=server_connectivity_info.port, ip_address=server_connectivity_info.ip_address, client_auth_msg=client_auth_msg) # Send tasks to worker processes for plugin_command in available_commands: if getattr(args_command_list, plugin_command): # Get this plugin's options if there's any plugin_options_dict = {} for option in available_commands[plugin_command].get_interface().get_options(): # Was this option set ? if getattr(args_command_list,option.dest): plugin_options_dict[option.dest] = getattr(args_command_list, option.dest) plugins_process_pool.queue_plugin_task(server_connectivity_info, plugin_command, plugin_options_dict) for tentative_server_info, exception in connectivity_tester.get_invalid_servers(): invalid_servers_list.append(('{}:{}'.format(tentative_server_info.hostname, tentative_server_info.port), exception)) # Print servers we were NOT able to connect to if should_print_text_results: for server_string, exception in invalid_servers_list: if isinstance(exception, ServerConnectivityError): print SERVER_INVALID_FORMAT.format(server_string=server_string, error_msg=exception.error_msg) else: # Unexpected bug in SSLyze raise exception print '\n\n' # Keep track of how many tasks have to be performed for each target task_num = 0 for command in available_commands: if getattr(args_command_list, command): task_num += 1 # --REPORTING SECTION-- # XML output xml_output_list = [] # Each host has a list of results result_dict = {} # We cannot use the server_info object directly as its address will change due to multiprocessing RESULT_KEY_FORMAT = '{ip_address}:{port}'.format for server_info in online_servers_list: result_dict[RESULT_KEY_FORMAT(ip_address=server_info.ip_address, port=server_info.port)] = [] # Process the results as they come for plugin_result in plugins_process_pool.get_results(): server_info = plugin_result.server_info result_dict[RESULT_KEY_FORMAT(ip_address=server_info.ip_address, port=server_info.port)].append(plugin_result) result_list = result_dict[RESULT_KEY_FORMAT(ip_address=server_info.ip_address, port=server_info.port)] if len(result_list) == task_num: # Done with this server; print the results and update the xml doc if args_command_list.xml_file: xml_output_list.append(_format_xml_target_result(server_info, result_list)) if should_print_text_results: print _format_txt_target_result(server_info, result_list) # --TERMINATE-- exec_time = time()-start_time # Output JSON to a file if needed if args_command_list.json_file: json_output = {'total_scan_time': str(exec_time), 'network_timeout': str(args_command_list.timeout), 'network_max_retries': str(args_command_list.nb_retries), 'invalid_targets': {}} # Add the list of invalid targets for server_string, exception in invalid_servers_list: if isinstance(exception, ServerConnectivityError): json_output['invalidTargets'][server_string] = exception.error_msg else: # Unexpected bug in SSLyze raise exception # Add the output of the plugins for each server for host_str, plugin_result_list in result_dict.iteritems(): server_info = plugin_result_list[0].server_info json_output[host_str] = _format_json_result(server_info, plugin_result_list) final_json_output = json.dumps(json_output, default=lambda o: o.__dict__, sort_keys=True, indent=4) if args_command_list.json_file == '-': # Print XML output to the console if needed print final_json_output else: # Otherwise save the XML output to the console with open(args_command_list.json_file, 'w') as json_file: json_file.write(final_json_output) # Output XML doc to a file if needed if args_command_list.xml_file: result_xml_attr = {'totalScanTime': str(exec_time), 'networkTimeout': str(args_command_list.timeout), 'networkMaxRetries': str(args_command_list.nb_retries)} result_xml = Element('results', attrib = result_xml_attr) # Sort results in alphabetical order to make the XML files (somewhat) diff-able xml_output_list.sort(key=lambda xml_elem: xml_elem.attrib['host']) for xml_element in xml_output_list: result_xml.append(xml_element) xml_final_doc = Element('document', title="SSLyze Scan Results", SSLyzeVersion=__version__, SSLyzeWeb=PROJECT_URL) # Add the list of invalid targets invalid_targets_xml = Element('invalidTargets') for server_string, exception in invalid_servers_list: if isinstance(exception, ServerConnectivityError): error_xml = Element('invalidTarget', error=exception.error_msg) error_xml.text = server_string invalid_targets_xml.append(error_xml) else: # Unexpected bug in SSLyze raise exception xml_final_doc.append(invalid_targets_xml) # Add the output of the plugins xml_final_doc.append(result_xml) # Remove characters that are illegal for XML # https://lsimons.wordpress.com/2011/03/17/stripping-illegal-characters-out-of-xml-in-python/ xml_final_string = tostring(xml_final_doc, encoding='UTF-8') illegal_xml_chars_RE = re.compile(u'[\x00-\x08\x0b\x0c\x0e-\x1F\uD800-\uDFFF\uFFFE\uFFFF]') xml_sanitized_final_string = illegal_xml_chars_RE.sub('', xml_final_string) # Hack: Prettify the XML file so it's (somewhat) diff-able xml_final_pretty = minidom.parseString(xml_sanitized_final_string).toprettyxml(indent=" ", encoding="utf-8" ) if args_command_list.xml_file == '-': # Print XML output to the console if needed print xml_final_pretty else: # Otherwise save the XML output to the console with open(args_command_list.xml_file, 'w') as xml_file: xml_file.write(xml_final_pretty) if should_print_text_results: print _format_title('Scan Completed in {0:.2f} s'.format(exec_time))
def main(): # For py2exe builds freeze_support() # Handle SIGINT to terminate processes signal.signal(signal.SIGINT, sigint_handler) start_time = time() #--PLUGINS INITIALIZATION-- sslyze_plugins = PluginsFinder() available_plugins = sslyze_plugins.get_plugins() available_commands = sslyze_plugins.get_commands() # Create the command line parser and the list of available options sslyze_parser = CommandLineParser(available_plugins, __version__) online_servers_list = [] invalid_servers_list = [] # Parse the command line try: good_server_list, bad_server_list, args_command_list = sslyze_parser.parse_command_line( ) invalid_servers_list.extend(bad_server_list) except CommandLineParsingError as e: print e.get_error_msg() return should_print_text_results = not args_command_list.quiet and args_command_list.xml_file != '-' \ and args_command_list.json_file != '-' if should_print_text_results: print '\n\n\n' + _format_title('Available plugins') for plugin in available_plugins: print ' ' + plugin.__name__ print '\n\n' #--PROCESSES INITIALIZATION-- if args_command_list.https_tunnel: # Maximum one process to not kill the proxy plugins_process_pool = PluginsProcessPool(sslyze_plugins, args_command_list.nb_retries, args_command_list.timeout, max_processes_nb=1) else: plugins_process_pool = PluginsProcessPool(sslyze_plugins, args_command_list.nb_retries, args_command_list.timeout) #--TESTING SECTION-- # Figure out which hosts are up and fill the task queue with work to do if should_print_text_results: print _format_title('Checking host(s) availability') connectivity_tester = ServersConnectivityTester(good_server_list) connectivity_tester.start_connectivity_testing( network_timeout=args_command_list.timeout) SERVER_OK_FORMAT = u' {host}:{port:<25} => {ip_address} {client_auth_msg}' SERVER_INVALID_FORMAT = u' {server_string:<35} => WARNING: {error_msg}; discarding corresponding tasks.' # Store and print servers we were able to connect to for server_connectivity_info in connectivity_tester.get_reachable_servers( ): online_servers_list.append(server_connectivity_info) if should_print_text_results: client_auth_msg = '' client_auth_requirement = server_connectivity_info.client_auth_requirement if client_auth_requirement == ClientAuthenticationServerConfigurationEnum.REQUIRED: client_auth_msg = ' WARNING: Server REQUIRED client authentication, specific plugins will fail.' elif client_auth_requirement == ClientAuthenticationServerConfigurationEnum.OPTIONAL: client_auth_msg = ' WARNING: Server requested optional client authentication' print SERVER_OK_FORMAT.format( host=server_connectivity_info.hostname, port=server_connectivity_info.port, ip_address=server_connectivity_info.ip_address, client_auth_msg=client_auth_msg) # Send tasks to worker processes for plugin_command in available_commands: if getattr(args_command_list, plugin_command): # Get this plugin's options if there's any plugin_options_dict = {} for option in available_commands[plugin_command].get_interface( ).get_options(): # Was this option set ? if getattr(args_command_list, option.dest): plugin_options_dict[option.dest] = getattr( args_command_list, option.dest) plugins_process_pool.queue_plugin_task( server_connectivity_info, plugin_command, plugin_options_dict) for tentative_server_info, exception in connectivity_tester.get_invalid_servers( ): invalid_servers_list.append( (tentative_server_info.server_string, exception)) # Print servers we were NOT able to connect to if should_print_text_results: for server_string, exception in invalid_servers_list: if isinstance(exception, ServerConnectivityError): print SERVER_INVALID_FORMAT.format( server_string=server_string, error_msg=exception.error_msg) else: # Unexpected bug in SSLyze raise exception print '\n\n' # Keep track of how many tasks have to be performed for each target task_num = 0 for command in available_commands: if getattr(args_command_list, command): task_num += 1 # --REPORTING SECTION-- # XML output xml_output_list = [] # Each host has a list of results result_dict = {} # We cannot use the server_info object directly as its address will change due to multiprocessing RESULT_KEY_FORMAT = u'{hostname}:{ip_address}:{port}'.format for server_info in online_servers_list: result_dict[RESULT_KEY_FORMAT(hostname=server_info.hostname, ip_address=server_info.ip_address, port=server_info.port)] = [] # Process the results as they come for plugin_result in plugins_process_pool.get_results(): server_info = plugin_result.server_info result_dict[RESULT_KEY_FORMAT( hostname=server_info.hostname, ip_address=server_info.ip_address, port=server_info.port)].append(plugin_result) result_list = result_dict[RESULT_KEY_FORMAT( hostname=server_info.hostname, ip_address=server_info.ip_address, port=server_info.port)] if len(result_list) == task_num: # Done with this server; print the results and update the xml doc if args_command_list.xml_file: xml_output_list.append( _format_xml_target_result(server_info, result_list)) if should_print_text_results: print _format_txt_target_result(server_info, result_list) # --TERMINATE-- exec_time = time() - start_time # Output JSON to a file if needed if args_command_list.json_file: json_output = { 'total_scan_time': str(exec_time), 'network_timeout': str(args_command_list.timeout), 'network_max_retries': str(args_command_list.nb_retries), 'invalid_targets': [], 'accepted_targets': [] } # Add the list of invalid targets for server_string, exception in invalid_servers_list: if isinstance(exception, ServerConnectivityError): json_output['invalid_targets'].append( {server_string: exception.error_msg}) else: # Unexpected bug in SSLyze raise exception # Add the output of the plugins for each server for host_str, plugin_result_list in result_dict.iteritems(): server_info = plugin_result_list[0].server_info json_output['accepted_targets'].append( _format_json_result(server_info, plugin_result_list)) final_json_output = json.dumps(json_output, default=lambda o: o.__dict__, sort_keys=True, indent=4) if args_command_list.json_file == '-': # Print XML output to the console if needed print final_json_output else: # Otherwise save the XML output to the console with open(args_command_list.json_file, 'w') as json_file: json_file.write(final_json_output) # Output XML doc to a file if needed if args_command_list.xml_file: result_xml_attr = { 'totalScanTime': str(exec_time), 'networkTimeout': str(args_command_list.timeout), 'networkMaxRetries': str(args_command_list.nb_retries) } result_xml = Element('results', attrib=result_xml_attr) # Sort results in alphabetical order to make the XML files (somewhat) diff-able xml_output_list.sort(key=lambda xml_elem: xml_elem.attrib['host']) for xml_element in xml_output_list: result_xml.append(xml_element) xml_final_doc = Element('document', title="SSLyze Scan Results", SSLyzeVersion=__version__, SSLyzeWeb=PROJECT_URL) # Add the list of invalid targets invalid_targets_xml = Element('invalidTargets') for server_string, exception in invalid_servers_list: if isinstance(exception, ServerConnectivityError): error_xml = Element('invalidTarget', error=exception.error_msg) error_xml.text = server_string invalid_targets_xml.append(error_xml) else: # Unexpected bug in SSLyze raise exception xml_final_doc.append(invalid_targets_xml) # Add the output of the plugins xml_final_doc.append(result_xml) # Remove characters that are illegal for XML # https://lsimons.wordpress.com/2011/03/17/stripping-illegal-characters-out-of-xml-in-python/ xml_final_string = tostring(xml_final_doc, encoding='UTF-8') illegal_xml_chars_RE = re.compile( u'[\x00-\x08\x0b\x0c\x0e-\x1F\uD800-\uDFFF\uFFFE\uFFFF]') xml_sanitized_final_string = illegal_xml_chars_RE.sub( '', xml_final_string) # Hack: Prettify the XML file so it's (somewhat) diff-able xml_final_pretty = minidom.parseString( xml_sanitized_final_string).toprettyxml(indent=" ", encoding="utf-8") if args_command_list.xml_file == '-': # Print XML output to the console if needed print xml_final_pretty else: # Otherwise save the XML output to the console with open(args_command_list.xml_file, 'w') as xml_file: xml_file.write(xml_final_pretty) if should_print_text_results: print _format_title('Scan Completed in {0:.2f} s'.format(exec_time))
try: server_info = ServerConnectivityInfo( hostname=hostname, port=587, tls_wrapped_protocol=TlsWrappedProtocolEnum.STARTTLS_SMTP) server_info.test_connectivity_to_server() except ServerConnectivityError as e: # Could not establish an SSL connection to the server raise RuntimeError('Error when connecting to {}: {}'.format( hostname, e.error_msg)) # Get the list of available plugins sslyze_plugins = PluginsFinder.get() # Create a process pool to run scanning commands concurrently plugins_process_pool = PluginsProcessPool(sslyze_plugins) # Queue some scan commands; the commands are same as what is described in the SSLyze CLI --help text. print '\nQueuing some commands...' plugins_process_pool.queue_plugin_task(server_info, 'sslv3') plugins_process_pool.queue_plugin_task(server_info, 'reneg') plugins_process_pool.queue_plugin_task(server_info, 'certinfo_basic') # Process the results reneg_result = None print '\nProcessing results...' for plugin_result in plugins_process_pool.get_results(): # Sometimes a plugin command can unexpectedly fail (as a bug); it is returned as a PluginRaisedExceptionResult if isinstance(plugin_result, sslyze.plugins.plugin_base.PluginRaisedExceptionResult): plugins_process_pool.emergency_shutdown()
def main(): # For py2exe builds freeze_support() # Handle SIGINT to terminate processes signal.signal(signal.SIGINT, sigint_handler) start_time = time() # Retrieve available plugins sslyze_plugins = PluginsFinder() available_plugins = sslyze_plugins.get_plugins() available_commands = sslyze_plugins.get_commands() # Create the command line parser and the list of available options sslyze_parser = CommandLineParser(available_plugins, __version__) try: good_server_list, bad_server_list, args_command_list = sslyze_parser.parse_command_line() except CommandLineParsingError as e: print e.get_error_msg() return output_hub = OutputHub() output_hub.command_line_parsed(available_plugins, args_command_list) # Initialize the pool of processes that will run each plugin if args_command_list.https_tunnel: # Maximum one process to not kill the proxy plugins_process_pool = PluginsProcessPool(sslyze_plugins, args_command_list.nb_retries, args_command_list.timeout, max_processes_nb=1) else: plugins_process_pool = PluginsProcessPool(sslyze_plugins, args_command_list.nb_retries, args_command_list.timeout) # Figure out which hosts are up and fill the task queue with work to do connectivity_tester = ServersConnectivityTester(good_server_list) connectivity_tester.start_connectivity_testing(network_timeout=args_command_list.timeout) # Store and print server whose command line string was bad for failed_scan in bad_server_list: output_hub.server_connectivity_test_failed(failed_scan) # Store and print servers we were able to connect to online_servers_list = [] for server_connectivity_info in connectivity_tester.get_reachable_servers(): online_servers_list.append(server_connectivity_info) output_hub.server_connectivity_test_succeeded(server_connectivity_info) # Send tasks to worker processes for plugin_command in available_commands: if getattr(args_command_list, plugin_command): # Get this plugin's options if there's any plugin_options_dict = {} for option in available_commands[plugin_command].get_interface().get_options(): # Was this option set ? if getattr(args_command_list,option.dest): plugin_options_dict[option.dest] = getattr(args_command_list, option.dest) plugins_process_pool.queue_plugin_task(server_connectivity_info, plugin_command, plugin_options_dict) # Store and print servers we were NOT able to connect to for tentative_server_info, exception in connectivity_tester.get_invalid_servers(): failed_scan = FailedServerScan(tentative_server_info.server_string, exception) output_hub.server_connectivity_test_failed(failed_scan) # Keep track of how many tasks have to be performed for each target task_num = 0 output_hub.scans_started() for command in available_commands: if getattr(args_command_list, command): task_num += 1 # Each host has a list of results result_dict = {} # We cannot use the server_info object directly as its address will change due to multiprocessing RESULT_KEY_FORMAT = u'{hostname}:{ip_address}:{port}'.format for server_info in online_servers_list: result_dict[RESULT_KEY_FORMAT(hostname=server_info.hostname, ip_address=server_info.ip_address, port=server_info.port)] = [] # Process the results as they come for plugin_result in plugins_process_pool.get_results(): server_info = plugin_result.server_info result_dict[RESULT_KEY_FORMAT(hostname=server_info.hostname, ip_address=server_info.ip_address, port=server_info.port)].append(plugin_result) plugin_result_list = result_dict[RESULT_KEY_FORMAT(hostname=server_info.hostname, ip_address=server_info.ip_address, port=server_info.port)] if len(plugin_result_list) == task_num: # Done with this server; send the result to the output hub output_hub.server_scan_completed(CompletedServerScan(server_info, plugin_result_list)) # All done exec_time = time()-start_time output_hub.scans_completed(exec_time)
def get_sslyze(host, host_type): result = { 'ssl_ok': 1 } try: if host_type == '1': server_connection = ServerConnectivityInfo(hostname = host, port = 443, tls_server_name_indication = host) elif host_type == '2': server_connection = ServerConnectivityInfo(hostname = host, port = 25, tls_server_name_indication = host, tls_wrapped_protocol = TlsWrappedProtocolEnum.STARTTLS_SMTP) server_connection.test_connectivity_to_server() except ServerConnectivityError: return {'ssl_ok': 0} sslyze_plugins = PluginsFinder() plugins_process_pool = PluginsProcessPool(sslyze_plugins) plugins_process_pool.queue_plugin_task(server_connection, 'sslv2') plugins_process_pool.queue_plugin_task(server_connection, 'sslv3') plugins_process_pool.queue_plugin_task(server_connection, 'tlsv1') plugins_process_pool.queue_plugin_task(server_connection, 'tlsv1_1') plugins_process_pool.queue_plugin_task(server_connection, 'tlsv1_2') plugins_process_pool.queue_plugin_task(server_connection, 'reneg') plugins_process_pool.queue_plugin_task(server_connection, 'certinfo_basic') plugins_process_pool.queue_plugin_task(server_connection, 'compression') plugins_process_pool.queue_plugin_task(server_connection, 'heartbleed') plugins_process_pool.queue_plugin_task(server_connection, 'openssl_ccs') plugins_process_pool.queue_plugin_task(server_connection, 'fallback') if host_type == '1': plugins_process_pool.queue_plugin_task(server_connection, 'hsts') ciphers = [] result['protocol_num'] = 0 for plugin_result in plugins_process_pool.get_results(): if isinstance(plugin_result, sslyze.plugins.plugin_base.PluginRaisedExceptionResult): #plugins_process_pool.emergency_shutdown() if len(plugin_result.as_text()) == 2: if 'errors' not in result: result['errors'] = [] result['errors'].append("%s: %s" % (plugin_result.as_text()[0], plugin_result.as_text()[1])) else: print 'Scan command failed: {}'.format(plugin_result.as_text()) elif plugin_result.plugin_command in ['sslv2', 'sslv3', 'tlsv1', 'tlsv1_1' ,'tlsv1_2']: result, ciphers = ssl_protocols(result, plugin_result, plugin_result.plugin_command, ciphers) elif plugin_result.plugin_command == 'reneg': result['session_renegotiation_client'] = plugin_result.accepts_client_renegotiation result['session_renegotiation_secure'] = plugin_result.supports_secure_renegotiation elif plugin_result.plugin_command == 'certinfo_basic': result['cert_matches'] = plugin_result.hostname_validation_result cns_in_certificate_chain = [] has_sha1_signed_certificate = False for cert in plugin_result.certificate_chain: cert_identity = plugin_result._extract_subject_cn_or_oun(cert) cns_in_certificate_chain.append(cert_identity) if not plugin_result._is_root_certificate(cert) and "sha1" in cert.as_dict['signatureAlgorithm']: has_sha1_signed_certificate = True result['sha1_cert'] = has_sha1_signed_certificate # TODO: ocsp_stapling elif plugin_result.plugin_command == 'compression': result['compression'] = 1 if plugin_result.compression_name else 0 elif plugin_result.plugin_command == 'heartbleed': result['heartbleed'] = plugin_result.is_vulnerable_to_heartbleed elif plugin_result.plugin_command == 'openssl_ccs': result['ccs_injection'] = plugin_result.is_vulnerable_to_ccs_injection elif plugin_result.plugin_command == 'fallback': result['fallback_scsv_available'] = plugin_result.supports_fallback_scsv elif plugin_result.plugin_command == 'hsts': result['hsts_available'] = 1 if plugin_result.hsts_header else 0 if not result['ssl_ok']: return result cipher_string = ' '.join(ciphers) if result['tlsv1_2_available']: result['protocol_best'] = 'tlsv1_2' elif result['tlsv1_1_available']: result['protocol_best'] = 'tlsv1_1' elif result['tlsv1_available']: result['protocol_best'] = 'tlsv1' elif result['sslv3_available']: result['protocol_best'] = 'sslv3' elif result['sslv2_available']: result['protocol_best'] = 'sslv2' if result['protocol_num'] == 1: result['fallback_scsv_available'] = 0 result['rc4_available'] = 'RC4' in cipher_string result['md5_available'] = 'MD5' in cipher_string result['pfs_available'] = 'ECDHE_' in cipher_string or 'DHE_' in cipher_string result['anon_suite_available'] = 'anon_' in cipher_string return result
def scan(hostname, port): # Setup the servers to scan and ensure they are reachable try: server_info = ServerConnectivityInfo(hostname=hostname, port=port) server_info.test_connectivity_to_server() except ServerConnectivityError as e: # Could not establish an SSL connection to the server raise RuntimeError('Error when connecting to {}: {}'.format(hostname, e.error_msg)) # Get the list of available plugins sslyze_plugins = PluginsFinder() # Create a process pool to run scanning commands concurrently plugins_process_pool = PluginsProcessPool(sslyze_plugins) # Queue some scan commands; the commands are same as what is described in the SSLyze CLI --help text. # print '\nQueuing some commands...' plugins_process_pool.queue_plugin_task(server_info, 'sslv3') plugins_process_pool.queue_plugin_task(server_info, 'certinfo_basic') plugins_process_pool.queue_plugin_task(server_info, 'tlsv1') plugins_process_pool.queue_plugin_task(server_info, 'tlsv1_1') plugins_process_pool.queue_plugin_task(server_info, 'tlsv1_2') plugins_process_pool.queue_plugin_task(server_info, 'sslv2') result = {} result['server_info'] = server_info.__dict__ for res in plugins_process_pool.get_results(): if res.plugin_command in ['sslv2','sslv3','tlsv1','tlsv1_1','tlsv1_2']: supported = False if len(res.accepted_cipher_list) > 0: supported = True acc_ciphers = [] rej_ciphers = [] for cipher in res.accepted_cipher_list: acc_ciphers.append(cipher.name) result[res.plugin_command] = {'supported': supported, 'accepted_ciphers': acc_ciphers} elif res.plugin_command == 'certinfo_basic': result['certinfo'] = parse_certinfo(res.__dict__) return result
def get_scan(host): try: server_info = ServerConnectivityInfo(hostname=host, port=443) server_info.test_connectivity_to_server() found = 'True' except: found = 'False' if found == 'True': sslyze_plugins = PluginsFinder() plugins_process_pool = PluginsProcessPool(sslyze_plugins) cmds = ['sslv2', 'sslv3', 'tlsv1', 'tlsv1_1', 'tlsv1_2', 'certinfo_full'] for x in cmds: plugins_process_pool.queue_plugin_task(server_info, x) commonn = host_match = cert_sha1 = cert_start = extendedval = trusted = cert_end = ouline = isline = puline = cert_alt = cert_unix_start = cert_unix_end = crts = '' for x in plugins_process_pool.get_results(): if x.plugin_command == 'certinfo_full': try: y = x.certificate_chain[0].as_dict cert_sha1 = str(x.certificate_chain[0].sha1_fingerprint) host_match = str(x.hostname_validation_result) extendedval = str(x.is_leaf_certificate_ev) for z in x.path_validation_result_list: if z.trust_store.name == 'Microsoft': # check against the MS certificate store using "Microsoft", but you can also use "Mozilla NSS", "Apple" or "Java 6" trusted = str(z.is_certificate_trusted) except: y = '' if y != '': cert_start = y['validity']['notBefore'] cert_end = y['validity']['notAfter'] commonn = y['subject']['commonName'].lower() cert_unix_start = str(time.mktime(time.strptime(str(cert_start), "%b %d %H:%M:%S %Y %Z"))).split('.')[0] cert_unix_end = str(time.mktime(time.strptime(str(cert_end), "%b %d %H:%M:%S %Y %Z"))).split('.')[0] for z in ['organizationName', 'organizationalUnitName', 'localityName', 'stateOrProvinceName', 'countryName']: try: a = y['subject'][z] ouline += str(a)+', ' except: pass for z in ['organizationalUnitName', 'organizationName', 'commonName', 'countryName']: try: a = y['issuer'][z] isline += str(a)+', ' except: pass for z in ['publicKeyAlgorithm', 'publicKeySize']: try: a = y['subjectPublicKeyInfo'][z] puline += str(a)+', ' except: pass try: c = y['extensions']['X509v3 Subject Alternative Name']['DNS'] cert_alt = ', '.join(c) except: cert_alt = '' elif x.plugin_command != 'certinfo_full': if len(x.accepted_cipher_list) != 0: crts += str(x.plugin_command)+', ' crts = crts[:-2] puline = puline[:-2] isline = isline[:-2] ouline = ouline[:-2] a = '' b = [host, commonn, cert_sha1, host_match, extendedval, trusted, cert_start, cert_unix_start, cert_end, cert_unix_end, cert_alt, ouline, isline, puline, crts, timest, unixtime] for c in b: a += '"'+c+'",' resu.append(str(a[:-1])) print a[:-1]
hostname = "smtp.gmail.com" try: server_info = ServerConnectivityInfo( hostname=hostname, port=587, tls_wrapped_protocol=TlsWrappedProtocolEnum.STARTTLS_SMTP ) server_info.test_connectivity_to_server() except ServerConnectivityError as e: # Could not establish an SSL connection to the server raise RuntimeError("Error when connecting to {}: {}".format(hostname, e.error_msg)) # Get the list of available plugins sslyze_plugins = PluginsFinder() # Create a process pool to run scanning commands concurrently plugins_process_pool = PluginsProcessPool(sslyze_plugins) # Queue some scan commands; the commands are same as what is described in the SSLyze CLI --help text. print "\nQueuing some commands..." plugins_process_pool.queue_plugin_task(server_info, "sslv3") plugins_process_pool.queue_plugin_task(server_info, "reneg") plugins_process_pool.queue_plugin_task(server_info, "certinfo_basic") # Process the results reneg_result = None print "\nProcessing results..." for server_info, plugin_command, plugin_result in plugins_process_pool.get_results(): # Each plugin result has attributes with the information you're looking for, specific to each plugin # All these attributes are documented within each plugin's module if plugin_result.plugin_command == "sslv3": # Do something with the result
# Setup the servers to scan and ensure they are reachable hostname = u'smtp.gmail.com' try: server_info = ServerConnectivityInfo(hostname=hostname, port=587, tls_wrapped_protocol=TlsWrappedProtocolEnum.STARTTLS_SMTP) server_info.test_connectivity_to_server() except ServerConnectivityError as e: # Could not establish an SSL connection to the server raise RuntimeError('Error when connecting to {}: {}'.format(hostname, e.error_msg)) # Get the list of available plugins sslyze_plugins = PluginsFinder.get() # Create a process pool to run scanning commands concurrently plugins_process_pool = PluginsProcessPool(sslyze_plugins) # Queue some scan commands; the commands are same as what is described in the SSLyze CLI --help text. print '\nQueuing some commands...' plugins_process_pool.queue_plugin_task(server_info, 'sslv3') plugins_process_pool.queue_plugin_task(server_info, 'reneg') plugins_process_pool.queue_plugin_task(server_info, 'certinfo_basic') # Process the results reneg_result = None print '\nProcessing results...' for plugin_result in plugins_process_pool.get_results(): # Sometimes a plugin command can unexpectedly fail (as a bug); it is returned as a PluginRaisedExceptionResult if isinstance(plugin_result, sslyze.plugins.plugin_base.PluginRaisedExceptionResult): plugins_process_pool.emergency_shutdown() raise RuntimeError('Scan command failed: {}'.format(plugin_result.as_text()))
def get_scan(host): try: server_info = ServerConnectivityInfo(hostname=host, port=443) server_info.test_connectivity_to_server() found = 'True' except: found = 'False' if found == 'True': sslyze_plugins = PluginsFinder() plugins_process_pool = PluginsProcessPool(sslyze_plugins) cmds = [ 'sslv2', 'sslv3', 'tlsv1', 'tlsv1_1', 'tlsv1_2', 'certinfo_full' ] for x in cmds: plugins_process_pool.queue_plugin_task(server_info, x) commonn = host_match = cert_sha1 = cert_start = extendedval = trusted = cert_end = ouline = isline = puline = cert_alt = cert_unix_start = cert_unix_end = crts = '' for x in plugins_process_pool.get_results(): if x.plugin_command == 'certinfo_full': try: y = x.certificate_chain[0].as_dict cert_sha1 = str(x.certificate_chain[0].sha1_fingerprint) host_match = str(x.hostname_validation_result) extendedval = str(x.is_leaf_certificate_ev) for z in x.path_validation_result_list: if z.trust_store.name == 'Microsoft': # check against the MS certificate store using "Microsoft", but you can also use "Mozilla NSS", "Apple" or "Java 6" trusted = str(z.is_certificate_trusted) except: y = '' if y != '': cert_start = y['validity']['notBefore'] cert_end = y['validity']['notAfter'] commonn = y['subject']['commonName'].lower() cert_unix_start = str( time.mktime( time.strptime( str(cert_start), "%b %d %H:%M:%S %Y %Z"))).split('.')[0] cert_unix_end = str( time.mktime( time.strptime( str(cert_end), "%b %d %H:%M:%S %Y %Z"))).split('.')[0] for z in [ 'organizationName', 'organizationalUnitName', 'localityName', 'stateOrProvinceName', 'countryName' ]: try: a = y['subject'][z] ouline += str(a) + ', ' except: pass for z in [ 'organizationalUnitName', 'organizationName', 'commonName', 'countryName' ]: try: a = y['issuer'][z] isline += str(a) + ', ' except: pass for z in ['publicKeyAlgorithm', 'publicKeySize']: try: a = y['subjectPublicKeyInfo'][z] puline += str(a) + ', ' except: pass try: c = y['extensions']['X509v3 Subject Alternative Name'][ 'DNS'] cert_alt = ', '.join(c) except: cert_alt = '' elif x.plugin_command != 'certinfo_full': if len(x.accepted_cipher_list) != 0: crts += str(x.plugin_command) + ', ' crts = crts[:-2] puline = puline[:-2] isline = isline[:-2] ouline = ouline[:-2] a = '' b = [ host, commonn, cert_sha1, host_match, extendedval, trusted, cert_start, cert_unix_start, cert_end, cert_unix_end, cert_alt, ouline, isline, puline, crts, timest, unixtime ] for c in b: a += '"' + c + '",' resu.append(str(a[:-1])) print a[:-1]
# Setup the servers to scan and ensure they are reachable hostname = 'smtp.gmail.com' try: server_info = ServerConnectivityInfo(hostname=hostname, port=587, tls_wrapped_protocol=TlsWrappedProtocolEnum.STARTTLS_SMTP) server_info.test_connectivity_to_server() except ServerConnectivityError as e: # Could not establish an SSL connection to the server raise RuntimeError('Error when connecting to {}: {}'.format(hostname, e.error_msg)) # Get the list of available plugins sslyze_plugins = PluginsFinder() # Create a process pool to run scanning commands concurrently plugins_process_pool = PluginsProcessPool(sslyze_plugins) # Queue some scan commands; the commands are same as what is described in the SSLyze CLI --help text. print '\nQueuing some commands...' plugins_process_pool.queue_plugin_task(server_info, 'sslv3') plugins_process_pool.queue_plugin_task(server_info, 'reneg') plugins_process_pool.queue_plugin_task(server_info, 'certinfo_basic') # Process the results reneg_result = None print '\nProcessing results...' for server_info, plugin_command, plugin_result in plugins_process_pool.get_results(): # Each plugin result has attributes with the information you're looking for, specific to each plugin # All these attributes are documented within each plugin's module if plugin_result.plugin_command == 'sslv3': # Do something with the result
def main(): # For py2exe builds freeze_support() # Handle SIGINT to terminate processes signal.signal(signal.SIGINT, sigint_handler) start_time = time() # Retrieve available plugins sslyze_plugins = PluginsFinder.get() available_plugins = sslyze_plugins.get_plugins() available_commands = sslyze_plugins.get_commands() # Create the command line parser and the list of available options sslyze_parser = CommandLineParser(available_plugins, __version__) try: good_server_list, bad_server_list, args_command_list = sslyze_parser.parse_command_line() except CommandLineParsingError as e: print(e.get_error_msg()) return output_hub = OutputHub() output_hub.command_line_parsed(available_plugins, args_command_list) # Initialize the pool of processes that will run each plugin if args_command_list.https_tunnel: # Maximum one process to not kill the proxy plugins_process_pool = PluginsProcessPool(sslyze_plugins, args_command_list.nb_retries, args_command_list.timeout, max_processes_nb=1) else: plugins_process_pool = PluginsProcessPool(sslyze_plugins, args_command_list.nb_retries, args_command_list.timeout) # Figure out which hosts are up and fill the task queue with work to do connectivity_tester = ServersConnectivityTester(good_server_list) connectivity_tester.start_connectivity_testing(network_timeout=args_command_list.timeout) # Store and print server whose command line string was bad for failed_scan in bad_server_list: output_hub.server_connectivity_test_failed(failed_scan) # Store and print servers we were able to connect to online_servers_list = [] for server_connectivity_info in connectivity_tester.get_reachable_servers(): online_servers_list.append(server_connectivity_info) output_hub.server_connectivity_test_succeeded(server_connectivity_info) # Send tasks to worker processes for plugin_command in available_commands: if getattr(args_command_list, plugin_command): # Get this plugin's options if there's any plugin_options_dict = {} for option in available_commands[plugin_command].get_interface().get_options(): # Was this option set ? if getattr(args_command_list,option.dest): plugin_options_dict[option.dest] = getattr(args_command_list, option.dest) plugins_process_pool.queue_plugin_task(server_connectivity_info, plugin_command, plugin_options_dict) # Store and print servers we were NOT able to connect to for tentative_server_info, exception in connectivity_tester.get_invalid_servers(): failed_scan = FailedServerScan(tentative_server_info.server_string, exception) output_hub.server_connectivity_test_failed(failed_scan) # Keep track of how many tasks have to be performed for each target task_num = 0 output_hub.scans_started() for command in available_commands: if getattr(args_command_list, command): task_num += 1 # Each host has a list of results result_dict = {} # We cannot use the server_info object directly as its address will change due to multiprocessing RESULT_KEY_FORMAT = u'{hostname}:{ip_address}:{port}'.format for server_info in online_servers_list: result_dict[RESULT_KEY_FORMAT(hostname=server_info.hostname, ip_address=server_info.ip_address, port=server_info.port)] = [] # Process the results as they come for plugin_result in plugins_process_pool.get_results(): server_info = plugin_result.server_info result_dict[RESULT_KEY_FORMAT(hostname=server_info.hostname, ip_address=server_info.ip_address, port=server_info.port)].append(plugin_result) plugin_result_list = result_dict[RESULT_KEY_FORMAT(hostname=server_info.hostname, ip_address=server_info.ip_address, port=server_info.port)] if len(plugin_result_list) == task_num: # Done with this server; send the result to the output hub output_hub.server_scan_completed(CompletedServerScan(server_info, plugin_result_list)) # All done exec_time = time()-start_time output_hub.scans_completed(exec_time)