def server_scanner(p): try: logger = logging.getLogger(__name__) logger.info("Opening file") server_tester = ServerConnectivityTester(hostname='localhost', port=p) server_info = server_tester.perform() scanner = SynchronousScanner() results = dict() suite_names = [ 'SSLV2 Cipher Suites', 'SSLV3 Cipher Suites', 'TLSV1_0 Cipher Suites', 'TLSV1_1 Cipher Suites', 'TLSV1_2 Cipher Suites', 'TLSV1_3 Cipher Suites' ] suites = [ Sslv20ScanCommand, Sslv30ScanCommand, Tlsv10ScanCommand, Tlsv11ScanCommand, Tlsv12ScanCommand, Tlsv13ScanCommand ] logger.info("Scanning SSL/TLS suites, writing to ciphers.json") for suite_name, suite in zip(suite_names, suites): scan = scanner.run_scan_command(server_info, suite()) results[suite_name] = [ cipher.name for cipher in scan.accepted_cipher_list ] with open(filename, 'w') as outfile: json.dump(results, outfile) except ServerConnectivityError as e: raise RuntimeError( f'Could not connect to {e.server_info.hostname}: {e.error_message}' )
def test_ssl_service_for_ssl_vulnerability( self, org_uuid=None, network_service_uuid=None, network_service_scan_uuid=None, vulnerability_name=None, ): """ Test the given network service for the specified SSL vulnerability. :param org_uuid: The UUID of the organization to enumerate SSL vulnerabilities on behalf of. :param network_service_uuid: The UUID of the network service that is being scanned. :param network_service_scan_uuid: The UUID of the network service scan that this enumeration is a part of. :param vulnerability_name: A string representing the vulnerability to test for. :return: None """ logger.info( "Now testing network service %s for SSL vulnerability %s." % (network_service_uuid, vulnerability_name) ) command_map = get_ssl_vulnerabilities_command_map() ValidationHelper.validate_in(to_check=vulnerability_name, contained_by=command_map.keys()) command = command_map[vulnerability_name]["command"] ip_address, port, protocol = self.get_endpoint_information(network_service_uuid) scanner = SynchronousScanner() server_info = ServerConnectivityInfo(hostname=ip_address, ip_address=ip_address, port=port) try: server_info.test_connectivity_to_server() except ServerConnectivityError as e: logger.warning( "ServerConnectivityError thrown when attempting to test SSL at %s:%s for %s vulnerability: %s" % (ip_address, port, vulnerability_name, e.message) ) return try: result = scanner.run_scan_command(server_info, command()) vuln_model = SslVulnerabilityModel.from_database_model_uuid( uuid=network_service_scan_uuid, db_session=self.db_session, test_errored=False, vuln_test_name=vulnerability_name, ) vuln_model.test_results = [] for field in command_map[vulnerability_name]["fields"]: vuln_model.test_results.append({ "key": field, "value": getattr(result, field), }) vuln_model.save(org_uuid) except (socket.error, OpenSSLError): vuln_model = SslVulnerabilityModel.from_database_model_uuid( uuid=network_service_scan_uuid, db_session=self.db_session, test_errored=True, ) vuln_model.save(org_uuid) logger.info( "Network service %s successfully tested for SSL vulnerability %s." % (network_service_uuid, vulnerability_name) )
def enumerate_cipher_suites_for_ssl_service( self, org_uuid=None, network_service_uuid=None, network_service_scan_uuid=None, order_uuid=None, ): """ Enumerate all of the cipher suites that the given SSL/TLS service supports. :param org_uuid: The UUID of the organization to enumerate cipher suites on behalf of. :param network_service_uuid: The UUID of the network service that is being scanned. :param network_service_scan_uuid: The UUID of the network service scan that this enumeration is a part of. :return: None """ logger.info( "Now enumerating supported cipher suites for network service %s." % (network_service_uuid, )) ip_address = self.network_service.ip_address.address port = self.network_service.port server_info = ServerConnectivityInfo(hostname=ip_address, ip_address=ip_address, port=port) try: server_info.test_connectivity_to_server() except ServerConnectivityError as e: logger.warning( "ServerConnectivityError thrown when attempting to inspect SSL at %s:%s: %s" % (ip_address, port, e.message)) return scanner = SynchronousScanner() bulk_query = BulkElasticsearchQuery() network_service_scan = self.network_service_scan for ssl_protocol, command in get_ssl_cipher_suite_commands(): result = scanner.run_scan_command(server_info, command()) ssl_support_record = SslSupportModel.from_database_model( network_service_scan, ssl_version=ssl_protocol, supported=len(result.accepted_cipher_list) > 0, ) ssl_support_record.accepted_ciphers = [ cipher.name for cipher in result.accepted_cipher_list ] ssl_support_record.rejected_ciphers = [ cipher.name for cipher in result.rejected_cipher_list ] ssl_support_record.errored_ciphers = [ cipher.name for cipher in result.errored_cipher_list ] ssl_support_record.preferred_cipher = result.preferred_cipher.name if result.preferred_cipher else None bulk_query.add_model_for_indexing(model=ssl_support_record, index=org_uuid) logger.info( "All cipher suite information converted to Elasticsearch data. Now updating via bulk query." ) bulk_query.save() logger.info( "Bulk query completed. SSL cipher suites enumerated for network service %s." % (network_service_uuid, ))
def test_synchronous_scanner(self): server_test = ServerConnectivityTester(hostname='www.google.com') server_info = server_test.perform() sync_scanner = SynchronousScanner() plugin_result = sync_scanner.run_scan_command(server_info, CompressionScanCommand()) assert plugin_result.as_text() assert plugin_result.as_xml()
def test_synchronous_scanner(self): server_info = ServerConnectivityInfo(hostname='www.google.com') server_info.test_connectivity_to_server() sync_scanner = SynchronousScanner() plugin_result = sync_scanner.run_scan_command(server_info, CompressionScanCommand()) self.assertTrue(plugin_result.as_text()) self.assertTrue(plugin_result.as_xml())
def test_synchronous_scanner(self): server_test = ServerConnectivityTester(hostname='www.google.com') server_info = server_test.perform() sync_scanner = SynchronousScanner() plugin_result = sync_scanner.run_scan_command(server_info, CompressionScanCommand()) self.assertTrue(plugin_result.as_text()) self.assertTrue(plugin_result.as_xml())
def scan_ssl(self, ssl_domain, scan_id, cipher_list): # Comparing ciphers -- #used_ciphers = {cipher for cipher in sslyze.get("Accepted Ciphers").split(', ')} #bad_ciphers = list(used_ciphers - accepted_ciphers) #signature_algorithm = sslyze.get("Signature Algorithm", "sha1") #acceptable_ciphers = not bad_ciphers ssl_dict = {} ssl_dict["domain"] = ssl_domain["domain"] domain = ssl_domain["domain"] self.update_state(state="SCANNING") print(f'Scanning {domain} for ssl info...') #_install_req = subprocess.check_output("") try: server_tester = ServerConnectivityTester( hostname=ssl_domain["domain"], port=443, tls_wrapped_protocol=TlsWrappedProtocolEnum.PLAIN_TLS) print( f'\nTesting connectivity with {server_tester.hostname}:{server_tester.port}...' ) server_info = server_tester.perform() except ServerConnectivityError as e: # Could not establish an SSL connection to the server raise RuntimeError( f'Could not connect to {e.server_info.hostname}: {e.error_message}' ) _cmd = Tlsv10ScanCommand() synchronous_scanner = SynchronousScanner() scan_result = synchronous_scanner.run_scan_command(server_info, _cmd) i = 0 used_ciphers = [] for cipher in scan_result.accepted_cipher_list: print(f' {cipher.name}') used_ciphers.append(cipher.name) i = i + 1 print(f'Finished scanning {domain} for ssl info') bad_ciphers = [] for cipher in used_ciphers: if cipher not in cipher_list: bad_ciphers.append(cipher) ssl_dict['accepted_ciphers'] = used_ciphers ssl_dict['bad_ciphers'] = bad_ciphers return ssl_dict, "ssl", scan_id
def ciphers_scanner(server_info: ServerConnectivityInfo) -> dict: scanner = SynchronousScanner() commands = COMMANDS ciphers_info: dict = {} for command in commands: scan_result = scanner.run_scan_command(server_info, command) ciphers: list = [] for cipher in scan_result.accepted_cipher_list: ciphers.append(cipher.name) ciphers_info[command.get_cli_argument()] = ciphers return ciphers_info
def __init__(self, priority_queue_in, queue_in, queue_out, network_retries, network_timeout): # type: (JoinableQueue, JoinableQueue, JoinableQueue, int, int) -> None Process.__init__(self) self.priority_queue_in = priority_queue_in self.queue_in = queue_in self.queue_out = queue_out # The object that will actually run the scan commands self._synchronous_scanner = SynchronousScanner(network_retries, network_timeout)
def get_cert(site_json): hostname = get_hostname(site_json['hostname']) try: server_info = ServerConnectivityInfo(hostname=hostname) server_info.test_connectivity_to_server() command = CertificateInfoScanCommand() synchronous_scanner = SynchronousScanner() scan_result = synchronous_scanner.run_scan_command(server_info, command) except ServerConnectivityError: return None return scan_result
def check_tcp_service_for_ssl_protocol_cipher_support( self, org_uuid=None, service_uuid=None, ssl_protocol=None, scan_uuid=None ): """ Check to see what ciphers this TCP service supports for the given SSL protocol. :param org_uuid: The UUID of the organization to collect information on behalf of. :param service_uuid: The UUID of the network service to check for SSL support. :param ssl_protocol: The SSL protocol to check :param scan_uuid: The UUID of the network service scan that this SSL version check is associated with. :return: None """ ip_address, port, protocol = self.get_endpoint_information(service_uuid) server_info = ServerConnectivityInfo(hostname=ip_address, ip_address=ip_address, port=port) synchronous_scanner = SynchronousScanner() command = None if ssl_protocol == 'PROTOCOL_TLSv1' or ssl_protocol == 'PROTOCOL_TLS': command = Tlsv10ScanCommand() elif ssl_protocol == 'PROTOCOL_TLSv1_1': command = Tlsv11ScanCommand() elif ssl_protocol == 'PROTOCOL_TLSv1_2': command = Tlsv12ScanCommand() elif ssl_protocol == 'PROTOCOL_SSLv23': command = Sslv20ScanCommand() elif ssl_protocol == 'PROTOCOL_SSLv3': command = Sslv30ScanCommand() else: raise ValueError( "Not sure how to run scan command for SSL protocol of %s." % (ssl_protocol,) ) cipher_scan_result = synchronous_scanner.run_scan_command(server_info, command) ssl_support_record = SslSupportModel.from_database_model_uuid( uuid=scan_uuid, db_session=self.db_session, ssl_version=ssl_protocol, supported=True, ) ssl_support_record.accepted_ciphers = [ cipher.name for cipher in cipher_scan_result.accepted_cipher_list ] ssl_support_record.rejected_ciphers = [ cipher.name for cipher in cipher_scan_result.rejected_cipher_list ] ssl_support_record.errored_ciphers = [ cipher.name for cipher in cipher_scan_result.errored_cipher_list ] if cipher_scan_result.preferred_cipher is not None: ssl_support_record.preferred_cipher = cipher_scan_result.preferred_cipher.name else: ssl_support_record.preferred_cipher = None ssl_support_record.save(org_uuid)
def init_sslyze(hostname, port, starttls_smtp, options, sync=False): global network_timeout network_timeout = int(options.get("network_timeout", network_timeout)) tls_wrapped_protocol = TlsWrappedProtocolEnum.PLAIN_TLS if starttls_smtp: tls_wrapped_protocol = TlsWrappedProtocolEnum.STARTTLS_SMTP try: # logging.debug("\tTesting connectivity with timeout of %is." % network_timeout) server_tester = ServerConnectivityTester( hostname=hostname, port=port, tls_wrapped_protocol=tls_wrapped_protocol) server_info = server_tester.perform(network_timeout=network_timeout) except ServerConnectivityError as err: logging.warn("\tServer connectivity not established during test.") return None, None except Exception as err: utils.notify(err) logging.warn( "\tUnknown exception when performing server connectivity info.") return None, None if sync: scanner = SynchronousScanner(network_timeout=network_timeout) else: scanner = ConcurrentScanner(network_timeout=network_timeout) return server_info, scanner
def run_sslyze_commands(self, server_info): full_scan_results = {} synchronous_scanner = SynchronousScanner() full_scan_results["Cipher suites"] = self.run_cipher_suite_commands( server_info, synchronous_scanner) full_scan_results["Certificates"] = self.run_certificate_command( server_info, synchronous_scanner) full_scan_results["Compression"] = self.run_compression_command( server_info, synchronous_scanner) full_scan_results["Fallback SCSV"] = self.run_fallback_scsv_command( server_info, synchronous_scanner) full_scan_results["Heartbleed"] = self.run_heartbleed_command( server_info, synchronous_scanner) full_scan_results["Early Data"] = self.run_early_data_command( server_info, synchronous_scanner) full_scan_results[ "CCS Injection"] = self.run_openssl_ccs_injection_command( server_info, synchronous_scanner) full_scan_results["Robot"] = self.run_robot_command( server_info, synchronous_scanner) full_scan_results[ "Session Renegotiation"] = self.run_session_renegotiation_command( server_info, synchronous_scanner) full_scan_results[ "Session Resumption"] = self.run_session_resumption_command( server_info, synchronous_scanner) return full_scan_results
def get_cert_alt_names(host, port=443): try: server_tester = ServerConnectivityTester(hostname=host, port=port, tls_wrapped_protocol=TlsWrappedProtocolEnum.HTTPS) server_info = server_tester.perform() except ServerConnectivityError: print("Impossible to connect") sys.exit(1) command = CertificateInfoScanCommand() synchronous_scanner = SynchronousScanner() scan_result = synchronous_scanner.run_scan_command(server_info, command) cert = scan_result.verified_certificate_chain[0] subj_alt_names = [] san_ext = cert.extensions.get_extension_for_oid(ExtensionOID.SUBJECT_ALTERNATIVE_NAME) subj_alt_names = san_ext.value.get_values_for_type(DNSName) return subj_alt_names
def scan(name, ip, view, suite): """ Two inputs: web site name and ip TODO: extend this to include port """ try: server_tester = ServerConnectivityTester( hostname=name, ip_address=ip, port=443, tls_wrapped_protocol=TlsWrappedProtocolEnum.HTTPS) # This line checks to see if the host is online server_info = server_tester.perform() ip = server_info.ip_address # Could not establish an SSL connection to the server except ConnectionToServerTimedOut: error = results.set_error(f'{name}', "Connection to TCP 443 timed-out") return error except ServerConnectivityError: error = results.set_error(f'{name}', "Unknown Error") return error # Create a new results dictionary scan_output = results.new() # I hash the combination of hostname and ip for tracking key = md5((f'{name}' + ip).encode("utf-8")).hexdigest() results.set_result(scan_output, "MD5", key) results.set_result(scan_output, "Hostname", f'{name}') results.set_result(scan_output, "IP", ip) results.set_result(scan_output, "View", view) for suite in ciphersuites.get(suite): synchronous_scanner = SynchronousScanner() scan_result = synchronous_scanner.run_scan_command(server_info, suite) for cipher in scan_result.accepted_cipher_list: results.set_ciphers(scan_output, { "Version": cipher.ssl_version.name, "Cipher": cipher.name }) if len(scan_output["Results"]) == 0: results.set_result(scan_output, "Results", "No Policy Violations") return scan_output
def __init__( self, domain: str, target_profile: str, ca_file: Optional[str] = None, cert_expire_warning: int = 15, ) -> None: """ :param domain: :param target_profile: One of [old|intermediate|modern] :param ca_file: Path to a trusted custom root certificates in PEM format. :param cert_expire_warning: A warning is issued if the certificate expires in less days than specified. """ self.ca_file = ca_file self.cert_expire_warning = cert_expire_warning if TLSProfiler.PROFILES is None: TLSProfiler.PROFILES = requests.get(self.PROFILES_URL).json() log.info( f"Loaded version {TLSProfiler.PROFILES['version']} of the Mozilla TLS configuration recommendations." ) self.target_profile = TLSProfiler.PROFILES["configurations"][ target_profile] self.target_profile["tls_curves"] = self._get_equivalent_curves( self.target_profile["tls_curves"]) self.target_profile[ "certificate_curves"] = self._get_equivalent_curves( self.target_profile["certificate_curves"]) self.scanner = SynchronousScanner() try: server_tester = ServerConnectivityTester(hostname=domain, ) log.info( f"Testing connectivity with {server_tester.hostname}:{server_tester.port}..." ) self.server_info = server_tester.perform() self.server_error = None except ServerConnectivityError as e: # Could not establish an SSL connection to the server log.warning( f"Could not connect to {e.server_info.hostname}: {e.error_message}" ) self.server_error = e.error_message self.server_info = None
def scan(name, ip, port, view, suite): """ Five inputs: web site name, ip, port split-dns view, and cipher suite """ try: server_tester = ServerConnectivityTester( hostname=name, ip_address=ip, port=port, tls_wrapped_protocol=TlsWrappedProtocolEnum.HTTPS) # This line checks to see if the host is online server_info = server_tester.perform() ip = server_info.ip_address # Could not establish an SSL connection to the server except ConnectionToServerTimedOut: raise ConnectionError('Connection Timeout', ERROR_MSG_CONNECTION_TIMEOUT(name, port)) except ServerConnectivityError: raise ConnectionError('Unknow Connection Error', ERROR_MSG_UNKNOWN_CONNECTION(name, port)) # Create a new results dictionary scan_output = results.new() # I hash the combination of hostname and ip for tracking key = md5((f'{name}' + ip).encode("utf-8")).hexdigest() results.set_result(scan_output, "MD5", key) results.set_result(scan_output, "Hostname", f'{name}') results.set_result(scan_output, "IP", ip) results.set_result(scan_output, "View", view) for suite in ciphersuites.get(suite): synchronous_scanner = SynchronousScanner() scan_result = synchronous_scanner.run_scan_command(server_info, suite) for cipher in scan_result.accepted_cipher_list: results.set_ciphers(scan_output, { "Version": cipher.ssl_version.name, "Cipher": cipher.name }) if len(scan_output["Results"]) == 0: results.set_result(scan_output, "Results", "No Policy Violations") return scan_output
def search_subject_alt_name(self, target): print("Searching for Subject Alt Names") try: server_info = ServerConnectivityInfo(hostname=target) server_info.test_connectivity_to_server() synchronous_scanner = SynchronousScanner() # Certificate information command = CertificateInfoScanCommand() scan_result = synchronous_scanner.run_scan_command(server_info, command) # Direct object reference is pretty bad, but then again so is the crypto.x509 object implementation, so... extensions = scan_result.certificate_chain[0].extensions[6] for entry in extensions.value: if entry.value.strip() not in self.domains: self.domains.append(entry.value.strip()) except Exception as e: self.handle_exception(e)
def __init__(self, priority_queue_in, queue_in, queue_out, network_retries, network_timeout): # type: (JoinableQueue, JoinableQueue, JoinableQueue, int, int) -> None Process.__init__(self) self.priority_queue_in = priority_queue_in self.queue_in = queue_in self.queue_out = queue_out # The object that will actually run the scan commands self._synchronous_scanner = SynchronousScanner(network_retries, network_timeout)
class WorkerProcess(Process): """The main process class responsible for instantiating and running the plugins. """ def __init__( self, priority_queue_in: JoinableQueue, queue_in: JoinableQueue, queue_out: JoinableQueue, network_retries: int, network_timeout: int, ) -> None: Process.__init__(self) self.priority_queue_in = priority_queue_in self.queue_in = queue_in self.queue_out = queue_out # The object that will actually run the scan commands self._synchronous_scanner = SynchronousScanner(network_retries, network_timeout) def run(self) -> None: """The process will first complete tasks it gets from self.queue_in. Once it gets notified that all the tasks have been completed, it terminates. """ from sslyze.concurrent_scanner import PluginRaisedExceptionScanResult # Start processing task in the priority queue first current_queue_in = self.priority_queue_in while True: task = current_queue_in.get() # Grab a task from queue_in if task is None: # All tasks have been completed current_queue_in.task_done() if current_queue_in == self.priority_queue_in: # All high priority tasks have been completed; switch to low priority tasks current_queue_in = self.queue_in continue else: # All the tasks have been completed; pass on the sentinel to result_queue and exit self.queue_out.put(None) break server_info, scan_command = task try: result = self._synchronous_scanner.run_scan_command(server_info, scan_command) except Exception as e: # raise result = PluginRaisedExceptionScanResult(server_info, scan_command, e) # Send the result to queue_out self.queue_out.put(result) current_queue_in.task_done()
def demo_synchronous_scanner(): # Run one scan command to list the server's TLS 1.0 cipher suites try: server_tester = ServerConnectivityTester( hostname='smtp.gmail.com', port=587, tls_wrapped_protocol=TlsWrappedProtocolEnum.STARTTLS_SMTP ) print(f'\nTesting connectivity with {server_tester.hostname}:{server_tester.port}...') server_info = server_tester.perform() except ServerConnectivityError as e: # Could not establish an SSL connection to the server raise RuntimeError(f'Could not connect to {e.server_info.hostname}: {e.error_message}') command = Tlsv10ScanCommand() synchronous_scanner = SynchronousScanner() scan_result = synchronous_scanner.run_scan_command(server_info, command) for cipher in scan_result.accepted_cipher_list: print(f' {cipher.name}')
def executePerDomainAction(self, domain): """ This plugin's per-domain action is to run a barrage of sslyze certificate tests Params: domain (str) """ from sslyze.plugins.certificate_info_plugin import CertificateInfoScanCommand from sslyze.plugins.compression_plugin import CompressionScanCommand from sslyze.plugins.session_renegotiation_plugin import SessionRenegotiationScanCommand from sslyze.server_connectivity_tester import ServerConnectivityTester from sslyze.server_connectivity_tester import ServerConnectivityError from sslyze.synchronous_scanner import SynchronousScanner try: sslyze_conn_test = ServerConnectivityTester(hostname=domain) sslyze_server_info = sslyze_conn_test.perform() sslyze_scanner = SynchronousScanner() sslyze_results = sslyze_scanner.run_scan_command( sslyze_server_info, CertificateInfoScanCommand()) sslyze_result_lines = sslyze_results.as_text() for line in sslyze_result_lines: self.logger.info(line) sslyze_results = sslyze_scanner.run_scan_command( sslyze_server_info, SessionRenegotiationScanCommand()) sslyze_result_lines = sslyze_results.as_text() for line in sslyze_result_lines: self.logger.info(line) sslyze_results = sslyze_scanner.run_scan_command( sslyze_server_info, CompressionScanCommand()) sslyze_result_lines = sslyze_results.as_text() for line in sslyze_result_lines: self.logger.info(line) except ServerConnectivityError as e: # Could not establish a TLS/SSL connection to the server self.logger.error( f'sslyze ended early, could not connect to {e.server_info.hostname}: {e.error_message}' ) print( f'sslyze ended early, could not connect to {e.server_info.hostname}: {e.error_message}' )
def test_ssl_server_headers(self, hostname, port=443): ''' Uses the ServerConnectivityTester to identify host headers specific to TLS/SSL implementations to identify apparent security flaws with SSL/TLS implementations at the web server level. Currently, we can enumerate HSTS and Expect-CT Headers. HPKP is available, but is not being included because its being deprecated by Chrome. | test ssl server headers | hostname | port (optional | ''' try: tester = ServerConnectivityTester(hostname=hostname, port=port) server_info = tester.perform() scanner = SynchronousScanner() result = scanner.run_scan_command(server_info, HttpHeadersScanCommand()) logger.info("Test for HSTS Header") if result.hsts_header: preload = result.hsts_header.preload include_subdomains = result.hsts_header.include_subdomains max_age = result.hsts_header.max_age logger.info( "\tHSTS Header with Preload: {}, Include Subdomains: {} and max_age: {}" .format(preload, include_subdomains, max_age)) else: logger.warn("\tNo HSTS Header found") logger.info("Test for Expect-CT Header") if result.expect_ct_header: logger.info("\tExpect-CT Header found: {}".format( result.expect_ct_header)) else: logger.warn("\tNo Expect-CT Header found.") except ServerConnectivityError as e: logger.error('Error when trying to connect to {}: {}'.format( e.server_info.hostname, e.error_message))
class WorkerProcess(Process): """The main process class responsible for instantiating and running the plugins. """ def __init__( self, priority_queue_in: JoinableQueue, queue_in: JoinableQueue, queue_out: JoinableQueue, network_retries: int, network_timeout: int ) -> None: Process.__init__(self) self.priority_queue_in = priority_queue_in self.queue_in = queue_in self.queue_out = queue_out # The object that will actually run the scan commands self._synchronous_scanner = SynchronousScanner(network_retries, network_timeout) def run(self) -> None: """The process will first complete tasks it gets from self.queue_in. Once it gets notified that all the tasks have been completed, it terminates. """ from sslyze.concurrent_scanner import PluginRaisedExceptionScanResult # Start processing task in the priority queue first current_queue_in = self.priority_queue_in while True: task = current_queue_in.get() # Grab a task from queue_in if task is None: # All tasks have been completed current_queue_in.task_done() if current_queue_in == self.priority_queue_in: # All high priority tasks have been completed; switch to low priority tasks current_queue_in = self.queue_in continue else: # All the tasks have been completed; pass on the sentinel to result_queue and exit self.queue_out.put(None) break server_info, scan_command = task try: result = self._synchronous_scanner.run_scan_command(server_info, scan_command) except Exception as e: # raise result = PluginRaisedExceptionScanResult(server_info, scan_command, e) # Send the result to queue_out self.queue_out.put(result) current_queue_in.task_done()
def concurrent_scan(site_info): # Setup the server to scan and ensure it is online/reachable server_info = server_connectivity_tester(site_info.name) if server_info: synchronous_scanner = SynchronousScanner() cert_info_plugin = CertificateInfoPlugin() plugin_result = cert_info_plugin.process_task( server_info, CertificateInfoScanCommand()) #not plugin_result.verified_certificate_chain or #not plugin_result.leaf_certificate_subject_matches_hostname some sites' certs CN is with "www." so the result here is false if plugin_result.verified_certificate_chain and site_info.name not in str( plugin_result.verified_certificate_chain[0].subject): site_info.cert_trusted = "False" print("not trusted: " + site_info.name) print(plugin_result.__dict__) # elif not plugin_result.verified_certificate_chain: # site_info.cert_trusted = "False" # print("not trusted: " + site_info.name) # print(plugin_result.__dict__) else: site_info.cert_trusted = "True" scan_result1 = synchronous_scanner.run_scan_command( server_info, Sslv20ScanCommand()) if len(scan_result1.accepted_cipher_list) > 0: site_info.sslv2 = "True" scan_result2 = synchronous_scanner.run_scan_command( server_info, Sslv30ScanCommand()) if len(scan_result2.accepted_cipher_list) > 0: site_info.sslv3 = "True" scan_result3 = synchronous_scanner.run_scan_command( server_info, Tlsv10ScanCommand()) if len(scan_result3.accepted_cipher_list) > 0: site_info.tlsv1 = "True" scan_result4 = synchronous_scanner.run_scan_command( server_info, Tlsv11ScanCommand()) if len(scan_result4.accepted_cipher_list) > 0: site_info.tlsv11 = "True" scan_result5 = synchronous_scanner.run_scan_command( server_info, Tlsv12ScanCommand()) if len(scan_result5.accepted_cipher_list) > 0: site_info.tlsv12 = "True" scan_result6 = synchronous_scanner.run_scan_command( server_info, Tlsv13ScanCommand()) if len(scan_result6.accepted_cipher_list) > 0: site_info.tlsv13 = "True" recheck_cert(site_info)
def get_cert(site_json): hostname = get_hostname(site_json['hostname']) try: server_tester = ServerConnectivityTester(hostname=hostname) server_info = server_tester.perform() command = CertificateInfoScanCommand() synchronous_scanner = SynchronousScanner() scan_result = synchronous_scanner.run_scan_command( server_info, command) except sslyze.server_connectivity_tester.ServerNotReachableError: return None except sslyze.server_connectivity_tester.ServerConnectivityError: # plugin has very little documentation, keeping this here for now return None except OSError: return None except RuntimeError: return None except ValueError: return None return scan_result
def retrieve_ssl_vulnerabilities_for_tcp_service( self, org_uuid=None, service_uuid=None, scan_uuid=None, ): """ This performs various SSL vulnerability scans on the tcp service :param org_uuid: The UUID of the organization to collect information on behalf of. :param service_uuid: The UUID of the network service to retrieve the SSL certificate for. :param scan_uuid: The UUID of the network service scan that this SSL certificate retrieval is associated with. :return: None """ ip_address, port, protocol = self.get_endpoint_information(service_uuid) ssl_vulnerabilities_record = SslVulnerabilitiesModel.from_database_model_uuid( uuid=scan_uuid, db_session=self.db_session ) server_info = ServerConnectivityInfo(hostname=ip_address, ip_address=ip_address, port=port) try: server_info.test_connectivity_to_server() except ServerConnectivityError as e: # Could not establish an SSL connection to the server logger.error( "Error making an SSL connection to the server while looking for vulnerabilities, something went really wrong." ) synchronous_scanner = SynchronousScanner() fallback_scsv_command = FallbackScsvScanCommand() fallback_scsv_result = synchronous_scanner.run_scan_command(server_info, fallback_scsv_command) ssl_vulnerabilities_record.supports_fallback_scsv = fallback_scsv_result.supports_fallback_scsv heartbleed_command = HeartbleedScanCommand() heartbleed_result = synchronous_scanner.run_scan_command(server_info, heartbleed_command) ssl_vulnerabilities_record.is_vulnerable_to_heartbleed = heartbleed_result.is_vulnerable_to_heartbleed openssl_css_injection_command = OpenSslCcsInjectionScanCommand() openssl_css_injection_result = synchronous_scanner.run_scan_command(server_info, openssl_css_injection_command) ssl_vulnerabilities_record.is_vulnerable_to_ccs_injection = openssl_css_injection_result.is_vulnerable_to_ccs_injection session_renegotion_command = SessionRenegotiationScanCommand() session_renegotion_result = synchronous_scanner.run_scan_command(server_info, session_renegotion_command) ssl_vulnerabilities_record.accepts_client_renegotiation = session_renegotion_result.accepts_client_renegotiation ssl_vulnerabilities_record.supports_secure_renegotiation = session_renegotion_result.supports_secure_renegotiation session_resumption_support_command = SessionResumptionSupportScanCommand() session_resumption_support_result = synchronous_scanner.run_scan_command(server_info, session_resumption_support_command) ssl_vulnerabilities_record.is_ticket_resumption_supported = session_resumption_support_result.is_ticket_resumption_supported ssl_vulnerabilities_record.save(org_uuid)
def ssl_scan(self): print("Running SSL Scan") try: server_info = ServerConnectivityInfo( hostname=self.options["TARGET"]) server_info.test_connectivity_to_server() synchronous_scanner = SynchronousScanner() # TLS 1.0 command = Tlsv10ScanCommand() scan_result = synchronous_scanner.run_scan_command( server_info, command) print("Available TLSv1.0 Ciphers:") for cipher in scan_result.accepted_cipher_list: print(' {}'.format(cipher.name)) # TLSv1.2 command = Tlsv12ScanCommand() scan_result = synchronous_scanner.run_scan_command( server_info, command) print("Available TLSv1.2 Ciphers:") for cipher in scan_result.accepted_cipher_list: print(' {}'.format(cipher.name)) # Certificate information command = CertificateInfoScanCommand() scan_result = synchronous_scanner.run_scan_command( server_info, command) for entry in scan_result.as_text(): print(entry) # Heartbleed vulnerability info command = HeartbleedScanCommand() scan_result = synchronous_scanner.run_scan_command( server_info, command) for entry in scan_result.as_text(): print(entry) # HTTP Headers info command = HttpHeadersScanCommand() scan_result = synchronous_scanner.run_scan_command( server_info, command) for entry in scan_result.as_text(): print(entry) except Exception as e: self.handle_exception(e, "Error running SSL scan") pass
def init_sslyze(hostname, options, sync=False): global network_timeout network_timeout = int(options.get("network_timeout", network_timeout)) try: server_info = sslyze.server_connectivity.ServerConnectivityInfo( hostname=hostname, port=443) except sslyze.server_connectivity.ServerConnectivityError as error: logging.warn( "\tServer connectivity not established during initialization.") return None, None except Exception as err: utils.notify(err) logging.warn( "\tUnknown exception when initializing server connectivity info.") return None, None try: # logging.debug("\tTesting connectivity with timeout of %is." % network_timeout) server_info.test_connectivity_to_server( network_timeout=network_timeout) except sslyze.server_connectivity.ServerConnectivityError as err: logging.warn("\tServer connectivity not established during test.") return None, None except Exception as err: utils.notify(err) logging.warn( "\tUnknown exception when performing server connectivity info.") return None, None if sync: scanner = SynchronousScanner(network_timeout=network_timeout) else: scanner = ConcurrentScanner(network_timeout=network_timeout) return server_info, scanner
def attack_host(results, host_name): print("Running forward_secrecy_attack.py host name: {}".format(host_name)) expected_tls1_2_suites = ['TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384', 'TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256'] try: server_tester = ServerConnectivityTester( hostname=host_name, port=443, tls_wrapped_protocol=TlsWrappedProtocolEnum.HTTPS) server_info = server_tester.perform() except ServerConnectivityError as e: results.append(AttackResult('10.13', host_name, False, e)) return synchronous_scanner = SynchronousScanner() tls1_3_scan_result = synchronous_scanner.run_scan_command(server_info, Tlsv13ScanCommand()) tls1_3_accepted_ciphers = tls1_3_scan_result.accepted_cipher_list tls1_2_scan_result = synchronous_scanner.run_scan_command(server_info, Tlsv12ScanCommand()) tls1_2_accepted_ciphers = tls1_2_scan_result.accepted_cipher_list tls1_2_accepted_cipher_names = cipher_list_to_string_list(tls1_2_accepted_ciphers) tls1_1_scan_result = synchronous_scanner.run_scan_command(server_info, Tlsv11ScanCommand()) tls1_1_accepted_ciphers = tls1_1_scan_result.accepted_cipher_list tls1_0_scan_result = synchronous_scanner.run_scan_command(server_info, Tlsv10ScanCommand()) tls1_0_accepted_ciphers = tls1_0_scan_result.accepted_cipher_list ssl3_0_scan_result = synchronous_scanner.run_scan_command(server_info, Sslv30ScanCommand()) ssl3_0_accepted_ciphers = ssl3_0_scan_result.accepted_cipher_list ssl2_0_scan_result = synchronous_scanner.run_scan_command(server_info, Sslv20ScanCommand()) ssl2_0_accepted_ciphers = ssl2_0_scan_result.accepted_cipher_list # Determine result result = list_equal(tls1_2_accepted_cipher_names, expected_tls1_2_suites) and \ len(tls1_3_accepted_ciphers) == 0 and \ len(tls1_1_accepted_ciphers) == 0 and \ len(tls1_0_accepted_ciphers) == 0 and \ len(ssl3_0_accepted_ciphers) == 0 and \ len(ssl3_0_accepted_ciphers) == 0 # Build details details = '' if len(tls1_3_accepted_ciphers) != 0: details += 'TLS 1.3 should not be supported ' if not list_equal(tls1_2_accepted_cipher_names, expected_tls1_2_suites): details += ' TLS 1.2 supporting ' + str(tls1_2_accepted_cipher_names) \ + ', should only be ' + str(expected_tls1_2_suites) + ' ' if len(tls1_1_accepted_ciphers) != 0: details += 'TLS 1.1 should not be supported ' if len(tls1_0_accepted_ciphers) != 0: details += 'TLS 1.0 should not be supported ' if len(ssl3_0_accepted_ciphers) != 0: details += 'SSL 3.0 should not be supported ' if len(ssl2_0_accepted_ciphers) != 0: details += 'SSL 2.0 should not be supported ' if details == '': details = 'Cipher suites are correct' results.append(AttackResult('forward_secrecy', host_name, result, details)) # attack_host([], 'google.co.uk')
def run_tests(self, tests): """ Run all enabled tests against the target url with the http or https port specified in the connect function. The Test objects within the tests array describes each test. The array should be changed according to the outcome, and if both ports have been specified and are supported the results must be merged before returned. :param tests: Array of Test objects :type tests: Array[Test...] :param targetURL: The target including address and port :type targetURL: str :return: Array of test objects :rtype: Array[Test...] """ # Perform tests synchronous_scanner = SynchronousScanner() # Run all plugins and do individual checks to see if the tests passed for i, plugin in enumerate(PluginsRepository._PLUGIN_CLASSES): if tests[i].enabled is True: plugin_passed = True # Individual check for cipher suites if plugin is OpenSslCipherSuitesPlugin: for command in plugin.get_available_commands(): scan_result = synchronous_scanner.run_scan_command( self.server_info, command()) if not self.is_open_ssl_cihper_suites_secure( command, scan_result): # If one command fails the plugin fails as a whole plugin_passed = False break # Individual check for certificates elif plugin is CertificateInfoPlugin: for command in plugin.get_available_commands(): scan_result = synchronous_scanner.run_scan_command( self.server_info, command()) if not self.is_certificate_info_secure(scan_result): plugin_passed = False break # Individual check for compression elif plugin is CompressionPlugin: for command in plugin.get_available_commands(): scan_result = synchronous_scanner.run_scan_command( self.server_info, command()) if not self.is_compression_secure(scan_result): plugin_passed = False break # Individual check for fallback scsv elif plugin is FallbackScsvPlugin: for command in plugin.get_available_commands(): scan_result = synchronous_scanner.run_scan_command( self.server_info, command()) if not self.is_fallback_scsv_secure(scan_result): plugin_passed = False break # Individual check for heartbleed elif plugin is HeartbleedPlugin: for command in plugin.get_available_commands(): scan_result = synchronous_scanner.run_scan_command( self.server_info, command()) if not self.is_heartbleed_secure(scan_result): plugin_passed = False break # Individual check for secure http headers elif plugin is HttpHeadersPlugin: for command in plugin.get_available_commands(): scan_result = synchronous_scanner.run_scan_command( self.server_info, command()) if not self.is_http_headers_secure(scan_result): plugin_passed = False break # Individual check for openssl css injection elif plugin is OpenSslCcsInjectionPlugin: for command in plugin.get_available_commands(): scan_result = synchronous_scanner.run_scan_command( self.server_info, command()) if not self.is_openssl_css_injection_secure( scan_result): plugin_passed = False break # Individual check for session renegotiation elif plugin is SessionRenegotiationPlugin: for command in plugin.get_available_commands(): scan_result = synchronous_scanner.run_scan_command( self.server_info, command()) if not self.is_session_renegotiation_secure( scan_result): plugin_passed = False break # Individual check for session resumption elif plugin is SessionResumptionPlugin: for command in plugin.get_available_commands(): scan_result = synchronous_scanner.run_scan_command( self.server_info, command()) if not self.is_session_resumption_secure(scan_result): plugin_passed = False break # Individual check for the robot attack elif plugin is RobotPlugin: for command in plugin.get_available_commands(): scan_result = synchronous_scanner.run_scan_command( self.server_info, command()) if not self.is_robot_secure(scan_result): plugin_passed = False break # Individual check for early data support elif plugin is EarlyDataPlugin: for command in plugin.get_available_commands(): scan_result = synchronous_scanner.run_scan_command( self.server_info, command()) if not self.is_early_data_secure(scan_result): plugin_passed = False break else: plugin_passed = None tests[i].passed = plugin_passed return tests
def ssltlsscan(web): target = web.split('//')[1] print(R + '\n ===============================') print(R + ' S S L E N U M E R A T I O N') print(R + ' ===============================\n') print(GR + ' [*] Testing server SSL status...') try: req = requests.get('https://' + target) print(G + ' [+] SSL Working Properly...') time.sleep(0.6) print(O + " [!] Running SSL Enumeration...\n") try: server_tester = ServerConnectivityTester(hostname=target) server_info = server_tester.perform() scanner = SynchronousScanner() command = Tlsv10ScanCommand() scan_result = scanner.run_scan_command(server_info, command) print(G + " [+] Available TLS v1.0 Ciphers:") for cipher in scan_result.accepted_cipher_list: print(C + ' {}'.format(cipher.name)) print('') command = Tlsv11ScanCommand() scan_result = scanner.run_scan_command(server_info, command) print(G + " [+] Available TLS v1.1 Ciphers:") for cipher in scan_result.accepted_cipher_list: print(C + ' {}'.format(cipher.name)) print('') command = Tlsv12ScanCommand() scan_result = scanner.run_scan_command(server_info, command) print(G + " [+] Available TLS v1.2 Ciphers:") for cipher in scan_result.accepted_cipher_list: print(C + ' {}'.format(cipher.name)) print('') command = CertificateInfoScanCommand() scan_result = scanner.run_scan_command(server_info, command) print(G + ' [+] Certificate Information:') for entry in scan_result.as_text(): if entry != '': if 'certificate information' in entry.lower(): pass elif ':' in entry: print(GR + ' [+] ' + entry.strip().split(':', 1)[0].strip() + ' : ' + C + entry.strip().split(':', 1)[1].strip()) else: print(O + '\n [+] ' + entry.strip()) print('') command = HttpHeadersScanCommand() scan_result = scanner.run_scan_command(server_info, command) print(G + ' [+] HTTP Results:') for entry in scan_result.as_text(): if 'http security' not in entry.strip().lower( ) and entry != '': if '-' in entry: print(GR + ' [+] ' + entry.split('-', 1)[0].strip() + ' - ' + C + entry.split('-', 1)[1].strip()) elif ':' in entry: print(GR + ' [+] ' + entry.strip().split(':', 1)[0].strip() + ' : ' + C + entry.strip().split(':', 1)[1].strip()) else: print(O + '\n [+] ' + entry.strip()) print('') except Exception as e: print(R + ' [-] Unhandled SSL Runtime Exception : ' + str(e)) pass except requests.exceptions.SSLError as e: print(R + ' [-] Distant Server SSL not working : ' + str(e)) print(G + ' [+] SSlScan Module Completed!')
# Setup the server to scan and ensure it is online/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)) # Example 1: Run one scan command synchronously to list the server's TLS 1.0 cipher suites print('\nRunning one scan command synchronously...') synchronous_scanner = SynchronousScanner() command = Tlsv10ScanCommand() scan_result = synchronous_scanner.run_scan_command(server_info, command) for cipher in scan_result.accepted_cipher_list: print(' {}'.format(cipher.name)) # Example 2: Run multiple scan commands concurrently. It is of course much faster than the SynchronousScanner concurrent_scanner = ConcurrentScanner() # Queue some scan commands print('\nQueuing some commands...') concurrent_scanner.queue_scan_command(server_info, Tlsv12ScanCommand()) concurrent_scanner.queue_scan_command(server_info, SessionRenegotiationScanCommand()) concurrent_scanner.queue_scan_command(server_info, CertificateInfoScanCommand())
if __name__ == '__main__': # Setup the server to scan and ensure it is online/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)) # Example 1: Run one scan command synchronously to list the server's TLS 1.0 cipher suites print('\nRunning one scan command synchronously...') synchronous_scanner = SynchronousScanner() command = Tlsv10ScanCommand() scan_result = synchronous_scanner.run_scan_command(server_info, command) for cipher in scan_result.accepted_cipher_list: print(' {}'.format(cipher.name)) # Example 2: Run multiple scan commands concurrently. It is of course much faster than the SynchronousScanner concurrent_scanner = ConcurrentScanner() # Queue some scan commands print('\nQueuing some commands...') concurrent_scanner.queue_scan_command(server_info, Tlsv12ScanCommand()) concurrent_scanner.queue_scan_command(server_info, SessionRenegotiationScanCommand()) concurrent_scanner.queue_scan_command(server_info, CertificateInfoScanCommand())