def scan_serial(scanner, server_info, data, options): logging.debug("\tRunning scans in serial.") logging.debug("\t\tSSLv2 scan.") sslv2 = scanner.run_scan_command(server_info, Sslv20ScanCommand()) logging.debug("\t\tSSLv3 scan.") sslv3 = scanner.run_scan_command(server_info, Sslv30ScanCommand()) logging.debug("\t\tTLSv1.0 scan.") tlsv1 = scanner.run_scan_command(server_info, Tlsv10ScanCommand()) logging.debug("\t\tTLSv1.1 scan.") tlsv1_1 = scanner.run_scan_command(server_info, Tlsv11ScanCommand()) logging.debug("\t\tTLSv1.2 scan.") tlsv1_2 = scanner.run_scan_command(server_info, Tlsv12ScanCommand()) logging.debug("\t\tTLSv1.3 scan.") tlsv1_3 = scanner.run_scan_command(server_info, Tlsv13ScanCommand()) certs = None if options.get("sslyze_certs", True) is True: try: logging.debug("\t\tCertificate information scan.") certs = scanner.run_scan_command(server_info, CertificateInfoScanCommand()) # Let generic exceptions bubble up. except idna.core.InvalidCodepoint: logging.warn(utils.format_last_exception()) data['errors'].append("Invalid certificate/OCSP for this domain.") certs = None else: certs = None logging.debug("\tDone scanning.") return sslv2, sslv3, tlsv1, tlsv1_1, tlsv1_2, tlsv1_3, certs
def test_null_cipher_suites(self): server_info = ServerConnectivityInfo(hostname='null.badssl.com') server_info.test_connectivity_to_server() plugin = OpenSslCipherSuitesPlugin() plugin_result = plugin.process_task(server_info, Tlsv12ScanCommand()) accepted_cipher_name_list = [ cipher.name for cipher in plugin_result.accepted_cipher_list ] self.assertEqual( { 'TLS_ECDH_anon_WITH_AES_256_CBC_SHA', 'TLS_DH_anon_WITH_AES_256_CBC_SHA256', 'TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA', 'TLS_DH_anon_WITH_AES_256_GCM_SHA384', 'TLS_DH_anon_WITH_AES_256_CBC_SHA', 'TLS_ECDH_anon_WITH_AES_128_CBC_SHA', 'TLS_DH_anon_WITH_AES_128_CBC_SHA256', 'TLS_DH_anon_WITH_AES_128_CBC_SHA', 'TLS_DH_anon_WITH_AES_128_GCM_SHA256', 'TLS_DH_anon_WITH_SEED_CBC_SHA', 'TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA', 'TLS_ECDHE_RSA_WITH_NULL_SHA', 'TLS_ECDH_anon_WITH_NULL_SHA', 'TLS_RSA_WITH_NULL_SHA256', 'TLS_RSA_WITH_NULL_SHA' }, set(accepted_cipher_name_list)) self.assertTrue(plugin_result.as_text()) self.assertTrue(plugin_result.as_xml()) # Ensure the results are pickable so the ConcurrentScanner can receive them via a Queue self.assertTrue(pickle.dumps(plugin_result))
def test_null_cipher_suites(self): server_test = ServerConnectivityTester(hostname='null.badssl.com') server_info = server_test.perform() plugin = OpenSslCipherSuitesPlugin() plugin_result = plugin.process_task(server_info, Tlsv12ScanCommand()) expected_ciphers = { 'TLS_ECDH_anon_WITH_AES_256_CBC_SHA', 'TLS_DH_anon_WITH_AES_256_CBC_SHA256', 'TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA', 'TLS_DH_anon_WITH_AES_256_GCM_SHA384', 'TLS_DH_anon_WITH_AES_256_CBC_SHA', 'TLS_ECDH_anon_WITH_AES_128_CBC_SHA', 'TLS_DH_anon_WITH_AES_128_CBC_SHA256', 'TLS_DH_anon_WITH_AES_128_CBC_SHA', 'TLS_DH_anon_WITH_AES_128_GCM_SHA256', 'TLS_DH_anon_WITH_SEED_CBC_SHA', 'TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA', 'TLS_ECDHE_RSA_WITH_NULL_SHA', 'TLS_ECDH_anon_WITH_NULL_SHA', 'TLS_RSA_WITH_NULL_SHA256', 'TLS_RSA_WITH_NULL_SHA' } assert expected_ciphers == set( [cipher.name for cipher in plugin_result.accepted_cipher_list]) assert plugin_result.as_text() assert plugin_result.as_xml() # Ensure the results are pickable so the ConcurrentScanner can receive them via a Queue assert pickle.dumps(plugin_result)
def test_tlsv1_2_enabled(self): server_test = ServerConnectivityTester(hostname='www.google.com') server_info = server_test.perform() plugin = OpenSslCipherSuitesPlugin() # Also do full HTTP connections plugin_result = plugin.process_task(server_info, Tlsv12ScanCommand(http_get=True)) assert plugin_result.preferred_cipher assert plugin_result.accepted_cipher_list expected_ciphers = { 'TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384', 'TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA', 'TLS_RSA_WITH_AES_256_GCM_SHA384', 'TLS_RSA_WITH_AES_256_CBC_SHA', 'TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA', 'TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256', 'TLS_RSA_WITH_AES_128_GCM_SHA256', 'TLS_RSA_WITH_AES_128_CBC_SHA', 'TLS_RSA_WITH_3DES_EDE_CBC_SHA', 'TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256', 'TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256' } assert expected_ciphers == set( [cipher.name for cipher in plugin_result.accepted_cipher_list]) assert plugin_result.rejected_cipher_list assert not plugin_result.errored_cipher_list assert plugin_result.as_text() assert plugin_result.as_xml() # Ensure the results are pickable so the ConcurrentScanner can receive them via a Queue assert pickle.dumps(plugin_result)
def test_tlsv1_2_enabled(self): server_info = ServerConnectivityInfo(hostname=u'www.google.com') server_info.test_connectivity_to_server() plugin = OpenSslCipherSuitesPlugin() # Also do full HTTP connections plugin_result = plugin.process_task(server_info, Tlsv12ScanCommand(http_get=True)) self.assertTrue(plugin_result.preferred_cipher) self.assertTrue(plugin_result.accepted_cipher_list) accepted_cipher_name_list = [ cipher.name for cipher in plugin_result.accepted_cipher_list ] self.assertEquals( { 'TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384', 'TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA', 'TLS_RSA_WITH_AES_256_GCM_SHA384', 'TLS_RSA_WITH_AES_256_CBC_SHA', 'TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA', 'TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256', 'TLS_RSA_WITH_AES_128_GCM_SHA256', 'TLS_RSA_WITH_AES_128_CBC_SHA', 'TLS_RSA_WITH_3DES_EDE_CBC_SHA' }, set(accepted_cipher_name_list)) self.assertTrue(plugin_result.rejected_cipher_list) self.assertFalse(plugin_result.errored_cipher_list) self.assertTrue(plugin_result.as_text()) self.assertTrue(plugin_result.as_xml())
def __init__(self, host, port, proxy=None): """ :param proxy: (dict) Default: None; Set this one up if you wish to use a proxy to hit your target host. E.g.: { "server":"someproxy.com", "port":6000, "user":"******", "pass":"******" } """ self.host = host self.port = port self.policies = { "ssl2.0": { "allowed": False, "command": Sslv20ScanCommand() }, "ssl3.0": { "allowed": False, "command": Sslv30ScanCommand() }, "tls1.0": { "allowed": False, "command": Tlsv10ScanCommand() }, "tls1.1": { "allowed": False, "command": Tlsv11ScanCommand() }, "tls1.2": { "allowed": True, "command": Tlsv12ScanCommand() }, "tls1.3": { "allowed": True, "command": Tlsv13ScanCommand() }, } if not isinstance(host, str) or not isinstance(port, int): raise TypeError('EncryptionCheck class not properly initialized.') # Proxy setup if proxy is not None: if not ("server" in proxy and "port" in proxy): raise ValueError('Invalid proxy settings detected.') proxy_server = proxy['server'] proxy_port = proxy['port'] proxy_user = proxy.get('user', None) proxy_pass = proxy.get('pass', None) tunnel_settings = HttpConnectTunnelingSettings( proxy_server, proxy_port, basic_auth_user=proxy_user, basic_auth_password=proxy_pass) else: tunnel_settings = None self.tunnel = tunnel_settings self.proxy = proxy
def test_server_cipher_ordering(self): configured_ciphers = [ 'ECDHE-RSA-CHACHA20-POLY1305', 'ECDHE-RSA-AES128-GCM-SHA256', 'ECDHE-RSA-AES256-GCM-SHA384', 'ECDHE-RSA-AES128-SHA256', 'ECDHE-RSA-AES256-SHA384', 'ECDHE-RSA-AES128-SHA', 'ECDHE-RSA-AES256-SHA', 'AES128-GCM-SHA256', 'AES256-GCM-SHA384', 'AES128-SHA256', 'AES256-SHA256', 'AES128-SHA', 'AES256-SHA' ] random.shuffle(configured_ciphers) cipher_string = ":".join(configured_ciphers) with ModernOpenSslServer(cipher=cipher_string, prefer_server_order=True) as server: # And the client does NOT provide a client certificate server_test = ServerConnectivityTester( hostname=server.hostname, ip_address=server.ip_address, port=server.port) server_info = server_test.perform() # OpenSslCipherSuitesPlugin works even when a client cert was not supplied plugin = OpenSslCipherSuitesPlugin() plugin_result = plugin.process_task(server_info, Tlsv12ScanCommand()) detected_ciphers = [ c.openssl_name for c in plugin_result.accepted_cipher_list ] assert configured_ciphers == detected_ciphers
def test_tlsv1_2_enabled(self): server_info = ServerConnectivityInfo(hostname='www.google.com') server_info.test_connectivity_to_server() plugin = OpenSslCipherSuitesPlugin() # Also do full HTTP connections plugin_result = plugin.process_task(server_info, Tlsv12ScanCommand(http_get=True)) self.assertTrue(plugin_result.preferred_cipher) self.assertTrue(plugin_result.accepted_cipher_list) accepted_cipher_name_list = [cipher.name for cipher in plugin_result.accepted_cipher_list] self.assertEqual({'TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384', 'TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA', 'TLS_RSA_WITH_AES_256_GCM_SHA384', 'TLS_RSA_WITH_AES_256_CBC_SHA', 'TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA', 'TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256', 'TLS_RSA_WITH_AES_128_GCM_SHA256', 'TLS_RSA_WITH_AES_128_CBC_SHA', 'TLS_RSA_WITH_3DES_EDE_CBC_SHA', 'TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256', 'TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256'}, set(accepted_cipher_name_list)) self.assertTrue(plugin_result.rejected_cipher_list) self.assertFalse(plugin_result.errored_cipher_list) self.assertTrue(plugin_result.as_text()) self.assertTrue(plugin_result.as_xml()) # Ensure the results are pickable so the ConcurrentScanner can receive them via a Queue self.assertTrue(pickle.dumps(plugin_result))
def scan_serial(scanner, server_info, data, options): errors = 0 def run_scan(scan_type, command, errors): if (errors >= 2): return None, errors logging.debug("\t\t{} scan.".format(scan_type)) result = None try: result = scanner.run_scan_command(server_info, command) except Exception as err: logging.warning("{}: Error during {} scan.".format( server_info.hostname, scan_type)) logging.debug("{}: Exception during {} scan: {}".format( server_info.hostname, scan_type, err)) errors = errors + 1 return result, errors logging.debug("\tRunning scans in serial.") sslv2, errors = run_scan("SSLv2", Sslv20ScanCommand(), errors) sslv3, errors = run_scan("SSLv3", Sslv30ScanCommand(), errors) tlsv1, errors = run_scan("TLSv1.0", Tlsv10ScanCommand(), errors) tlsv1_1, errors = run_scan("TLSv1.1", Tlsv11ScanCommand(), errors) tlsv1_2, errors = run_scan("TLSv1.2", Tlsv12ScanCommand(), errors) tlsv1_3, errors = run_scan("TLSv1.3", Tlsv13ScanCommand(), errors) certs = None if errors < 2 and options.get("sslyze_certs", True) is True: try: logging.debug("\t\tCertificate information scan.") certs = scanner.run_scan_command( server_info, CertificateInfoScanCommand(ca_file=CA_FILE)) except idna.core.InvalidCodepoint: logging.warning(utils.format_last_exception()) data['errors'].append("Invalid certificate/OCSP for this domain.") certs = None except Exception as err: logging.warning( "{}: Error during certificate information scan.".format( server_info.hostname)) logging.debug( "{}: Exception during certificate information scan: {}".format( server_info.hostname, err)) else: certs = None reneg = None if options.get("sslyze_reneg", True) is True: reneg, errors = run_scan("Renegotiation", SessionRenegotiationScanCommand(), errors) else: reneg = None logging.debug("\tDone scanning.") return sslv2, sslv3, tlsv1, tlsv1_1, tlsv1_2, tlsv1_3, certs, reneg
def test_smtp_post_handshake_response(self): server_info = ServerConnectivityInfo(hostname='smtp.gmail.com', port=587, tls_wrapped_protocol=TlsWrappedProtocolEnum.STARTTLS_SMTP) server_info.test_connectivity_to_server() plugin = OpenSslCipherSuitesPlugin() plugin_result = plugin.process_task(server_info, Tlsv12ScanCommand()) self.assertTrue(plugin_result.as_text()) self.assertTrue(plugin_result.as_xml())
def test_follows_client_cipher_suite_preference(self): # Google.com does not follow client cipher suite preference server_info = ServerConnectivityInfo(hostname=u'www.google.com') server_info.test_connectivity_to_server() plugin = OpenSslCipherSuitesPlugin() plugin_result = plugin.process_task(server_info, Tlsv12ScanCommand()) self.assertTrue(plugin_result.preferred_cipher) self.assertTrue(plugin_result.accepted_cipher_list) # Sogou.com follows client cipher suite preference server_info = ServerConnectivityInfo(hostname=u'www.sogou.com') server_info.test_connectivity_to_server() plugin = OpenSslCipherSuitesPlugin() plugin_result = plugin.process_task(server_info, Tlsv12ScanCommand()) self.assertIsNone(plugin_result.preferred_cipher) self.assertTrue(plugin_result.accepted_cipher_list)
def test_dh_info(self): server_info = ServerConnectivityInfo(hostname=u'dh1024.badssl.com') server_info.test_connectivity_to_server() plugin = OpenSslCipherSuitesPlugin() plugin_result = plugin.process_task(server_info, Tlsv12ScanCommand()) self.assertTrue(plugin_result.preferred_cipher) self.assertEquals(plugin_result.preferred_cipher.dh_info['GroupSize'], u'1024') self.assertTrue(plugin_result.as_text()) self.assertTrue(plugin_result.as_xml())
def test_rc4_md5_cipher_suites(self): server_info = ServerConnectivityInfo(hostname=u'rc4-md5.badssl.com') server_info.test_connectivity_to_server() plugin = OpenSslCipherSuitesPlugin() plugin_result = plugin.process_task(server_info, Tlsv12ScanCommand()) accepted_cipher_name_list = [cipher.name for cipher in plugin_result.accepted_cipher_list] self.assertEquals({'TLS_RSA_WITH_RC4_128_MD5'}, set(accepted_cipher_name_list)) self.assertTrue(plugin_result.as_text()) self.assertTrue(plugin_result.as_xml())
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 test_follows_client_cipher_suite_preference(self): # Google.com does not follow client cipher suite preference server_info = ServerConnectivityInfo(hostname='www.google.com') server_info.test_connectivity_to_server() plugin = OpenSslCipherSuitesPlugin() plugin_result = plugin.process_task(server_info, Tlsv12ScanCommand()) self.assertTrue(plugin_result.preferred_cipher) self.assertTrue(plugin_result.accepted_cipher_list) # Sogou.com follows client cipher suite preference server_info = ServerConnectivityInfo(hostname='www.sogou.com') server_info.test_connectivity_to_server() plugin = OpenSslCipherSuitesPlugin() plugin_result = plugin.process_task(server_info, Tlsv12ScanCommand()) self.assertIsNone(plugin_result.preferred_cipher) self.assertTrue(plugin_result.accepted_cipher_list) # Ensure the results are pickable so the ConcurrentScanner can receive them via a Queue self.assertTrue(pickle.dumps(plugin_result))
def test_follows_client_cipher_suite_preference(self): # Google.com does not follow client cipher suite preference server_test = ServerConnectivityTester(hostname='www.google.com') server_info = server_test.perform() plugin = OpenSslCipherSuitesPlugin() plugin_result = plugin.process_task(server_info, Tlsv12ScanCommand()) assert plugin_result.preferred_cipher assert plugin_result.accepted_cipher_list # Sogou.com follows client cipher suite preference server_test = ServerConnectivityTester(hostname='www.sogou.com') server_info = server_test.perform() plugin = OpenSslCipherSuitesPlugin() plugin_result = plugin.process_task(server_info, Tlsv12ScanCommand()) assert plugin_result.preferred_cipher is None assert plugin_result.accepted_cipher_list # Ensure the results are pickable so the ConcurrentScanner can receive them via a Queue assert pickle.dumps(plugin_result)
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 test_dh_info(self): server_info = ServerConnectivityInfo(hostname='dh1024.badssl.com') server_info.test_connectivity_to_server() plugin = OpenSslCipherSuitesPlugin() plugin_result = plugin.process_task(server_info, Tlsv12ScanCommand()) self.assertTrue(plugin_result.preferred_cipher) self.assertEquals(plugin_result.preferred_cipher.dh_info['GroupSize'], '1024') self.assertTrue(plugin_result.as_text()) self.assertTrue(plugin_result.as_xml()) # Ensure the results are pickable so the ConcurrentScanner can receive them via a Queue self.assertTrue(pickle.dumps(plugin_result))
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 test_rc4_md5_cipher_suites(self): server_info = ServerConnectivityInfo(hostname='rc4-md5.badssl.com') server_info.test_connectivity_to_server() plugin = OpenSslCipherSuitesPlugin() plugin_result = plugin.process_task(server_info, Tlsv12ScanCommand()) accepted_cipher_name_list = [cipher.name for cipher in plugin_result.accepted_cipher_list] self.assertEqual({'TLS_RSA_WITH_RC4_128_MD5'}, set(accepted_cipher_name_list)) self.assertTrue(plugin_result.as_text()) self.assertTrue(plugin_result.as_xml()) # Ensure the results are pickable so the ConcurrentScanner can receive them via a Queue self.assertTrue(pickle.dumps(plugin_result))
def test_rc4_md5_cipher_suites(self): server_test = ServerConnectivityTester(hostname='rc4-md5.badssl.com') server_info = server_test.perform() plugin = OpenSslCipherSuitesPlugin() plugin_result = plugin.process_task(server_info, Tlsv12ScanCommand()) accepted_cipher_name_list = [ cipher.name for cipher in plugin_result.accepted_cipher_list ] assert {'TLS_RSA_WITH_RC4_128_MD5'} == set(accepted_cipher_name_list) assert plugin_result.as_text() assert plugin_result.as_xml() # Ensure the results are pickable so the ConcurrentScanner can receive them via a Queue assert pickle.dumps(plugin_result)
def test_succeeds_when_client_auth_failed_tls_1_2(self): # Given a TLS 1.2 server that requires client authentication with LegacyOpenSslServer( client_auth_config=ClientAuthConfigEnum.REQUIRED) as server: # And the client does NOT provide a client certificate server_test = ServerConnectivityTester( hostname=server.hostname, ip_address=server.ip_address, port=server.port) server_info = server_test.perform() # OpenSslCipherSuitesPlugin works even when a client cert was not supplied plugin = OpenSslCipherSuitesPlugin() plugin_result = plugin.process_task(server_info, Tlsv12ScanCommand()) assert plugin_result.accepted_cipher_list assert plugin_result.as_text() assert plugin_result.as_xml()
def demo_concurrent_scanner(): # Setup the server to scan and ensure it is online/reachable server_info = demo_server_connectivity_tester() # Run multiple scan commands concurrently. It is 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, CertificateInfoScanCommand()) # Process the results print('\nProcessing results...') for scan_result in concurrent_scanner.get_results(): # All scan results have the corresponding scan_command and server_info as an attribute print(f'\nReceived result for "{scan_result.scan_command.get_title()}" ' f'on {scan_result.server_info.hostname}') # A scan command can fail (as a bug); it is returned as a PluginRaisedExceptionResult if isinstance(scan_result, PluginRaisedExceptionScanResult): raise RuntimeError(f'Scan command failed: {scan_result.scan_command.get_title()}') # Each scan result has attributes with the information yo're looking for # All these attributes are documented within each scan command's module if isinstance(scan_result.scan_command, Tlsv12ScanCommand): for cipher in scan_result.accepted_cipher_list: print(f' {cipher.name}') elif isinstance(scan_result.scan_command, CertificateInfoScanCommand): # Print the Common Names within the verified certificate chain if not scan_result.verified_certificate_chain: print('Error: certificate chain is not trusted!') else: print('Certificate chain common names:') for cert in scan_result.verified_certificate_chain: cert_common_names = cert.subject.get_attributes_for_oid(NameOID.COMMON_NAME) print(f' {cert_common_names[0].value}')
def run_cipher_suite_commands(self, server_info, synchronous_scanner): cipher_scan_results = {} commands = [ Sslv20ScanCommand(), Sslv30ScanCommand(), Tlsv10ScanCommand(), Tlsv11ScanCommand(), Tlsv12ScanCommand(), Tlsv13ScanCommand() ] for command in commands: scan_result = synchronous_scanner.run_scan_command( server_info, command) ciphers = [] for cipher in scan_result.accepted_cipher_list: ciphers.append({ "name": cipher.name, "key_size": cipher.key_size, "is_anonymous": cipher.is_anonymous }) cipher_scan_results[scan_result.scan_command.get_title()] = ciphers #print('ciphers obtained for ',server_info) return cipher_scan_results
from .errors import ConnectionError # Policy prohibits the use of SSL 2.0/3.0 and TLS 1.0 ciphersuites = { "policy": [ Sslv20ScanCommand(), Sslv30ScanCommand(), Tlsv10ScanCommand(), Tlsv11ScanCommand() ], "full": [ Sslv20ScanCommand(), Sslv30ScanCommand(), Tlsv10ScanCommand(), Tlsv11ScanCommand(), Tlsv12ScanCommand(), Tlsv13ScanCommand() ] } # sslyze config SynchronousScanner.DEFAULT_NETWORK_RETRIES = 1 SynchronousScanner.DEFAULT_NETWORK_TIMEOUT = 3 ERROR_MSG_CONNECTION_TIMEOUT = 'TCP connection to {}:{} timed-out'.format ERROR_MSG_UNKNOWN_CONNECTION = \ 'TCP connection to {}:{} encountered unknown error'.format def scan(name, ip, port, view, suite): """ Five inputs: web site name, ip, port
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!')
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 get_supported_tls_cipher_suites(hostname): server_info = get_ssl_server_info(hostname) concurrent_scanner = ConcurrentScanner() concurrent_scanner.queue_scan_command(server_info, Sslv20ScanCommand()) concurrent_scanner.queue_scan_command(server_info, Sslv30ScanCommand()) concurrent_scanner.queue_scan_command(server_info, Tlsv10ScanCommand()) concurrent_scanner.queue_scan_command(server_info, Tlsv11ScanCommand()) concurrent_scanner.queue_scan_command(server_info, Tlsv12ScanCommand()) concurrent_scanner.queue_scan_command(server_info, Tlsv13ScanCommand()) concurrent_scanner.queue_scan_command(server_info, FallbackScsvScanCommand()) for scan_result in concurrent_scanner.get_results(): # A scan command can fail (as a bug); it is returned as a PluginRaisedExceptionResult if isinstance(scan_result, PluginRaisedExceptionScanResult): raise RuntimeError( f'Scan command failed: {scan_result.scan_command.get_title()}') if isinstance(scan_result.scan_command, Sslv20ScanCommand): accepted_ssl2 = [ cipher.name for cipher in scan_result.accepted_cipher_list ] denied_ssl2 = [ cipher.name for cipher in scan_result.rejected_cipher_list ] errored_ssl2 = [ cipher.name for cipher in scan_result.errored_cipher_list ] if isinstance(scan_result.scan_command, Sslv30ScanCommand): accepted_ssl3 = [ cipher.name for cipher in scan_result.accepted_cipher_list ] denied_ssl3 = [ cipher.name for cipher in scan_result.rejected_cipher_list ] errored_ssl3 = [ cipher.name for cipher in scan_result.errored_cipher_list ] if isinstance(scan_result.scan_command, Tlsv10ScanCommand): accepted_tls10 = [ cipher.name for cipher in scan_result.accepted_cipher_list ] denied_tls10 = [ cipher.name for cipher in scan_result.rejected_cipher_list ] errored_tls10 = [ cipher.name for cipher in scan_result.errored_cipher_list ] if isinstance(scan_result.scan_command, Tlsv11ScanCommand): accepted_tls11 = [ cipher.name for cipher in scan_result.accepted_cipher_list ] denied_tls11 = [ cipher.name for cipher in scan_result.rejected_cipher_list ] errored_tls11 = [ cipher.name for cipher in scan_result.errored_cipher_list ] if isinstance(scan_result.scan_command, Tlsv12ScanCommand): accepted_tls12 = [ cipher.name for cipher in scan_result.accepted_cipher_list ] denied_tls12 = [ cipher.name for cipher in scan_result.rejected_cipher_list ] errored_tls12 = [ cipher.name for cipher in scan_result.errored_cipher_list ] if isinstance(scan_result.scan_command, Tlsv13ScanCommand): accepted_tls13 = [ cipher.name for cipher in scan_result.accepted_cipher_list ] denied_tls13 = [ cipher.name for cipher in scan_result.rejected_cipher_list ] errored_tls13 = [ cipher.name for cipher in scan_result.errored_cipher_list ] if isinstance(scan_result.scan_command, FallbackScsvScanCommand): supports_fallback_scsv = scan_result.supports_fallback_scsv return { 'accepted_ssl2': accepted_ssl2, 'denied_ssl2': denied_ssl2, 'errored_ssl2': errored_ssl2, 'accepted_ssl3': accepted_ssl3, 'denied_ssl3': denied_ssl3, 'errored_ssl3': errored_ssl3, 'accepted_tls10': accepted_tls10, 'denied_tls10': denied_tls10, 'errored_tls10': errored_tls10, 'accepted_tls11': accepted_tls11, 'denied_tls11': denied_tls11, 'errored_tls11': errored_tls11, 'accepted_tls12': accepted_tls12, 'denied_tls12': denied_tls12, 'errored_tls12': errored_tls12, 'accepted_tls13': accepted_tls13, 'denied_tls13': denied_tls13, 'errored_tls13': errored_tls13, 'supports_fallback_scsv': supports_fallback_scsv }
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()) # Process the results reneg_result = None print('\nProcessing results...') for scan_result in concurrent_scanner.get_results(): # All scan results have the corresponding scan_command and server_info as an attribute print('\nReceived scan result for {} on host {}'.format( scan_result.scan_command.__class__.__name__, scan_result.server_info.hostname)) # Sometimes a scan command can unexpectedly fail (as a bug); it is returned as a PluginRaisedExceptionResult
def scan_parallel(scanner, server_info, data, options): logging.debug("\tRunning scans in parallel.") def queue(command): try: return scanner.queue_scan_command(server_info, command) except OSError as err: text = ("OSError - likely too many processes and open files.") data['errors'].append(text) logging.warn("%s\n%s" % (text, utils.format_last_exception())) return None, None, None, None, None, None, None except Exception as err: text = ("Unknown exception queueing sslyze command.\n%s" % utils.format_last_exception()) data['errors'].append(text) logging.warn(text) return None, None, None, None, None, None, None # Initialize commands and result containers sslv2, sslv3, tlsv1, tlsv1_1, tlsv1_2, tlsv1_3, certs = None, None, None, None, None, None # Queue them all up queue(Sslv20ScanCommand()) queue(Sslv30ScanCommand()) queue(Tlsv10ScanCommand()) queue(Tlsv11ScanCommand()) queue(Tlsv12ScanCommand()) queue(Tlsv13ScanCommand()) if options.get("sslyze-certs", True) is True: queue(CertificateInfoScanCommand()) # Reassign them back to predictable places after they're all done was_error = False for result in scanner.get_results(): try: if isinstance(result, PluginRaisedExceptionScanResult): error = ("Scan command failed: %s" % result.as_text()) logging.warn(error) data['errors'].append(error) return None, None, None, None, None, None, None if type(result.scan_command) == Sslv20ScanCommand: sslv2 = result elif type(result.scan_command) == Sslv30ScanCommand: sslv3 = result elif type(result.scan_command) == Tlsv10ScanCommand: tlsv1 = result elif type(result.scan_command) == Tlsv11ScanCommand: tlsv1_1 = result elif type(result.scan_command) == Tlsv12ScanCommand: tlsv1_2 = result elif type(result.scan_command) == Tlsv13ScanCommand: tlsv1_3 = result elif type(result.scan_command) == CertificateInfoScanCommand: certs = result else: error = "Couldn't match scan result with command! %s" % result logging.warn("\t%s" % error) data['errors'].append(error) was_error = True except Exception as err: was_error = True text = ("Exception inside async scanner result processing.\n%s" % utils.format_last_exception()) data['errors'].append(text) logging.warn("\t%s" % text) # There was an error during async processing. if was_error: return None, None, None, None, None, None, None logging.debug("\tDone scanning.") return sslv2, sslv3, tlsv1, tlsv1_1, tlsv1_2, tlsv1_3, certs