def test_works_when_client_auth_succeeded(self): # Given a server that requires client authentication with LegacyOpenSslServer(client_auth_config=ClientAuthConfigEnum.REQUIRED) as server: # And the client provides a client certificate client_creds = ClientAuthenticationCredentials( client_certificate_chain_path=server.get_client_certificate_path(), client_key_path=server.get_client_key_path(), ) server_test = ServerConnectivityTester( hostname=server.hostname, ip_address=server.ip_address, port=server.port, client_auth_credentials=client_creds, ) server_info = server_test.perform() # The plugin works fine plugin = FallbackScsvPlugin() plugin_result = plugin.process_task(server_info, FallbackScsvScanCommand()) self.assertFalse(plugin_result.supports_fallback_scsv) self.assertTrue(plugin_result.as_text()) self.assertTrue(plugin_result.as_xml())
def test_works_when_client_auth_succeeded(self): # Given a server that requires client authentication try: with VulnerableOpenSslServer( client_auth_config= ClientAuthenticationServerConfigurationEnum.REQUIRED ) as server: # And the client provides a client certificate client_creds = ClientAuthenticationCredentials( client_certificate_chain_path=server. get_client_certificate_path(), client_key_path=server.get_client_key_path(), ) server_test = ServerConnectivityTester( hostname=server.hostname, ip_address=server.ip_address, port=server.port, client_auth_credentials=client_creds, ) server_info = server_test.perform() # The plugin works fine plugin = FallbackScsvPlugin() plugin_result = plugin.process_task(server_info, FallbackScsvScanCommand()) except NotOnLinux64Error: logging.warning('WARNING: Not on Linux - skipping test') return self.assertFalse(plugin_result.supports_fallback_scsv) self.assertTrue(plugin_result.as_text()) self.assertTrue(plugin_result.as_xml())
def run_fallback_scsv_command(self, server_info, synchronous_scanner): command = FallbackScsvScanCommand() try: scan_result = synchronous_scanner.run_scan_command( server_info, command) #print('fallback_scsv obtained for ',server_info) return scan_result.supports_fallback_scsv except: #print('fallback_scsv obtained for ',server_info) return None
def test_fallback_good(self): server_info = ServerConnectivityInfo(hostname=u'www.google.com') server_info.test_connectivity_to_server() plugin = FallbackScsvPlugin() plugin_result = plugin.process_task(server_info, FallbackScsvScanCommand()) self.assertTrue(plugin_result.supports_fallback_scsv) self.assertTrue(plugin_result.as_text()) self.assertTrue(plugin_result.as_xml())
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 test_fallback_good(self): server_test = ServerConnectivityTester(hostname='www.google.com') server_info = server_test.perform() plugin = FallbackScsvPlugin() plugin_result = plugin.process_task(server_info, FallbackScsvScanCommand()) self.assertTrue(plugin_result.supports_fallback_scsv) 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_fails_when_client_auth_failed(self): # Given a 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() # The plugin fails when a client cert was not supplied plugin = FallbackScsvPlugin() with self.assertRaises(ClientCertificateRequested): plugin.process_task(server_info, FallbackScsvScanCommand())
def test_fallback_bad(self): with VulnerableOpenSslServer() as server: server_test = ServerConnectivityTester( hostname=server.hostname, ip_address=server.ip_address, port=server.port) server_info = server_test.perform() plugin = FallbackScsvPlugin() plugin_result = plugin.process_task(server_info, FallbackScsvScanCommand()) self.assertFalse(plugin_result.supports_fallback_scsv) 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_fallback_bad(self): try: server = VulnerableOpenSslServer(port=8010) except NotOnLinux64Error: # The test suite only has the vulnerable OpenSSL version compiled for Linux 64 bits logging.warning('WARNING: Not on Linux - skipping test_fallback_bad() test') return server.start() server_info = ServerConnectivityInfo(hostname=server.hostname, ip_address=server.ip_address, port=server.port) server_info.test_connectivity_to_server() plugin = FallbackScsvPlugin() plugin_result = plugin.process_task(server_info, FallbackScsvScanCommand()) server.terminate() self.assertFalse(plugin_result.supports_fallback_scsv) self.assertTrue(plugin_result.as_text()) self.assertTrue(plugin_result.as_xml())
def test_fails_when_client_auth_failed(self): # Given a server that requires client authentication try: with VulnerableOpenSslServer( client_auth_config= ClientAuthenticationServerConfigurationEnum.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() # The plugin fails when a client cert was not supplied plugin = FallbackScsvPlugin() with self.assertRaises(ClientCertificateRequested): plugin.process_task(server_info, FallbackScsvScanCommand()) except NotOnLinux64Error: logging.warning('WARNING: Not on Linux - skipping test') return
def test_fallback_bad(self): try: with VulnerableOpenSslServer() as server: server_test = ServerConnectivityTester( hostname=server.hostname, ip_address=server.ip_address, port=server.port) server_info = server_test.perform() plugin = FallbackScsvPlugin() plugin_result = plugin.process_task(server_info, FallbackScsvScanCommand()) except NotOnLinux64Error: # The test suite only has the vulnerable OpenSSL version compiled for Linux 64 bits logging.warning( 'WARNING: Not on Linux - skipping test_fallback_bad() test') return self.assertFalse(plugin_result.supports_fallback_scsv) 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 module_run(self, hostportsip): for host, port, ip_address in hostportsip: self.heading('{0}:{1} ({2})'.format(host, port, ip_address), level=0) port = int(port) try: tls_wrapped_protocol = self.STARTTLS_PROTOCOL_DICT[port] except KeyError: self.error("Protocol not found for port {}".format(port)) continue try: server_info = ServerConnectivityInfo(hostname=host, port=port, ip_address=ip_address, tls_wrapped_protocol=tls_wrapped_protocol) server_info.test_connectivity_to_server() except ServerConnectivityError as e: self.error("Could not connect to {0}:{1}: {2}".format(host, port, e)) continue concurrent_scanner = ConcurrentScanner() concurrent_scanner.queue_scan_command(server_info, SessionRenegotiationScanCommand()) concurrent_scanner.queue_scan_command(server_info, CompressionScanCommand()) concurrent_scanner.queue_scan_command(server_info, FallbackScsvScanCommand()) concurrent_scanner.queue_scan_command(server_info, HeartbleedScanCommand()) concurrent_scanner.queue_scan_command(server_info, RobotScanCommand()) concurrent_scanner.queue_scan_command(server_info, OpenSslCcsInjectionScanCommand()) concurrent_scanner.queue_scan_command(server_info, SessionResumptionSupportScanCommand()) for scan_result in concurrent_scanner.get_results(): data = None if isinstance(scan_result, HeartbleedScanResult): if scan_result.is_vulnerable_to_heartbleed: data = {'reference': 'VULNERABLE - HEARTBLEED - Server is vulnerable to Heartbleed', 'example': '\n'.join(scan_result.as_text())} elif isinstance(scan_result, RobotScanResult): if scan_result.robot_result_enum == RobotScanResultEnum.VULNERABLE_STRONG_ORACLE: data = {'reference': 'VULNERABLE - ROBOT - Strong oracle, a real attack is possible', 'example': '\n'.join(scan_result.as_text())} elif scan_result.robot_result_enum == RobotScanResultEnum.VULNERABLE_WEAK_ORACLE: data = {'reference': 'VULNERABLE - ROBOT - Weak oracle, the attack would take too long', 'example': '\n'.join(scan_result.as_text())} elif isinstance(scan_result, CompressionScanResult): if scan_result.compression_name: data = {'reference': "VULNERABLE - Server supports Deflate compression", 'example': '\n'.join(scan_result.as_text())} elif isinstance(scan_result, FallbackScsvScanResult): if scan_result.supports_fallback_scsv: data = {'reference': "VULNERABLE - Signaling cipher suite not supported", 'example': '\n'.join(scan_result.as_text())} data = None elif isinstance(scan_result, OpenSslCcsInjectionScanResult): if scan_result.is_vulnerable_to_ccs_injection: data = {'reference': 'VULNERABLE - Server is vulnerable to OpenSSL CCS injection', 'example': '\n'.join(scan_result.as_text())} elif isinstance(scan_result, SessionRenegotiationScanResult): if scan_result.accepts_client_renegotiation: data = {'reference': 'VULNERABLE - Server honors client-initiated renegotiations', 'example': '\n'.join(scan_result.as_text())} elif isinstance(scan_result, PluginRaisedExceptionScanResult): self.error('Scan command failed: {}'.format(scan_result.as_text())) continue if data: data['host'] = host data['category'] = 'TLS vulnerability' for key in sorted(data.keys()): self.output('%s: %s' % (key.title(), data[key])) self.add_vulnerabilities(**data) self.output(self.ruler*50)
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 }
def main(): if len(sys.argv) < 2: print("Error: please provide a domain") exit(-1) hostname = sys.argv[1] """ Testing connectivity to the server """ try: server_info = ServerConnectivityInfo(hostname) server_info.test_connectivity_to_server() print( "[*] Connection established. \n[.] Starting tests on {} \n".format( hostname)) except ServerConnectivityError as e: raise RuntimeError("Error when connecting to {}: {}".format( hostname, e.error_msg)) scanner = SynchronousScanner() """ Creating an output file """ output = open("/root/PycharmProjects/SSL-TLS-Tool/output/" + hostname, "w") output.write("##############################################\n") output.write("Output result for host: {}\n".format(hostname)) output.write("Start {}\n".format(datetime.datetime.now())) output.write("##############################################\n\n") """ Certificate: """ scan_result = scanner.run_scan_command(server_info, CertificateInfoScanCommand()) for e in scan_result.as_text(): output.write(e + "\n") """ Protocols and Ciphers Suits: """ run_command(scanner, server_info, Tlsv10ScanCommand(), output) run_command(scanner, server_info, Tlsv11ScanCommand(), output) run_command(scanner, server_info, Tlsv12ScanCommand(), output) run_command(scanner, server_info, Sslv20ScanCommand(), output) run_command(scanner, server_info, Sslv30ScanCommand(), output) """ Testing vulnerabilities: """ run_command(scanner, server_info, DrownScanCommand(), output) run_command(scanner, server_info, PoodleSslScanCommand(), output) run_command(scanner, server_info, HeartbleedScanCommand(), output) run_command(scanner, server_info, OpenSslCcsInjectionScanCommand(), output) run_command(scanner, server_info, CompressionScanCommand(), output) run_command(scanner, server_info, FallbackScsvScanCommand(), output) run_command(scanner, server_info, SessionRenegotiationScanCommand(), output) run_command(scanner, server_info, SessionResumptionSupportScanCommand(), output) run_command(scanner, server_info, SessionResumptionRateScanCommand(), output) """ Closing """ output.close() print("\n[*] Check output file for more details") print("[*] Test completed!")