def _check_vulnerabilities(self): errors = [] result = self._scan( HeartbleedScanCommand()) # type: HeartbleedScanResult if result.is_vulnerable_to_heartbleed: errors.append(f"Server is vulnerable to Heartbleed attack") result = self._scan(OpenSslCcsInjectionScanCommand() ) # type: OpenSslCcsInjectionScanResult if result.is_vulnerable_to_ccs_injection: errors.append( f"Server is vulnerable to OpenSSL CCS Injection (CVE-2014-0224)" ) result = self._scan(RobotScanCommand()) # type: RobotScanResult if result.robot_result_enum in [ RobotScanResultEnum.VULNERABLE_WEAK_ORACLE, RobotScanResultEnum.VULNERABLE_STRONG_ORACLE, ]: errors.append(f"Server is vulnerable to ROBOT attack.") return errors
def test_succeeds_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 works even when a client cert was not supplied plugin = HeartbleedPlugin() plugin_result = plugin.process_task(server_info, HeartbleedScanCommand()) except NotOnLinux64Error: logging.warning('WARNING: Not on Linux - skipping test') return self.assertTrue(plugin_result.is_vulnerable_to_heartbleed) self.assertTrue(plugin_result.as_text()) self.assertTrue(plugin_result.as_xml())
def run_heartbleed_command(self, server_info, synchronous_scanner): command = HeartbleedScanCommand() try: scan_result = synchronous_scanner.run_scan_command( server_info, command) #print('heartbleed obtained for ',server_info) return scan_result.is_vulnerable_to_heartbleed except: #print('heartbleed obtained for ',server_info) return None
def test_heartbleed_good(self): server_info = ServerConnectivityInfo(hostname=u'www.google.com') server_info.test_connectivity_to_server() plugin = HeartbleedPlugin() plugin_result = plugin.process_task(server_info, HeartbleedScanCommand()) self.assertFalse(plugin_result.is_vulnerable_to_heartbleed) 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_heartbleed_good(self): server_test = ServerConnectivityTester(hostname='www.google.com') server_info = server_test.perform() plugin = HeartbleedPlugin() plugin_result = plugin.process_task(server_info, HeartbleedScanCommand()) self.assertFalse(plugin_result.is_vulnerable_to_heartbleed) 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_heartbleed_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 = HeartbleedPlugin() plugin_result = plugin.process_task(server_info, HeartbleedScanCommand()) self.assertTrue(plugin_result.is_vulnerable_to_heartbleed) 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_succeeds_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 works even when a client cert was not supplied plugin = HeartbleedPlugin() plugin_result = plugin.process_task(server_info, HeartbleedScanCommand()) assert plugin_result.is_vulnerable_to_heartbleed assert plugin_result.as_text() assert plugin_result.as_xml()
def test_heartbleed_bad(self): try: with VulnerableOpenSslServer() as server: server_info = ServerConnectivityInfo(hostname=server.hostname, ip_address=server.ip_address, port=server.port) server_info.test_connectivity_to_server() plugin = HeartbleedPlugin() plugin_result = plugin.process_task(server_info, HeartbleedScanCommand()) except NotOnLinux64Error: # The test suite only has the vulnerable OpenSSL version compiled for Linux 64 bits logging.warning('WARNING: Not on Linux - skipping test_heartbleed_bad() test') return self.assertTrue(plugin_result.is_vulnerable_to_heartbleed) 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_heartbleed_bad(self): try: server = VulnerableOpenSslServer(port=8011) except NotOnLinux64Error: # The test suite only has the vulnerable OpenSSL version compiled for Linux 64 bits logging.warning( 'WARNING: Not on Linux - skipping test_heartbleed_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 = HeartbleedPlugin() plugin_result = plugin.process_task(server_info, HeartbleedScanCommand()) server.terminate() self.assertTrue(plugin_result.is_vulnerable_to_heartbleed) self.assertTrue(plugin_result.as_text()) self.assertTrue(plugin_result.as_xml())
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!")
def __init__(self): super().__init__(HeartbleedScanCommand())
def check( hostname_user_input): try: print(u'hostname_user_input: '+hostname_user_input) # Strip http(s) m = re.search('^(https?://)?(.*?)(/.*)?$', hostname_user_input) if m.group(2): hostname_user_input = m.group(2) else: raise RuntimeError(u'Please provide non-empty host name!') server_tester = ServerConnectivityTester(hostname_user_input) server_info = server_tester.perform(network_timeout=10) # Could not establish an SSL connection to the server except ServerConnectivityError as e: raise RuntimeError(u'Error when connecting to {}: {}!'.format(hostname_user_input, e.error_message)) # No SSL used except IOError as e: raise RuntimeError(u'Protocol does not use SSL/TLS!') # If the call to test_connectivity_to_server() returns successfully, the server_info is then ready to be used for scanning the server. # The ConcurrentScanner uses a pool of processes to run ScanCommands concurrently. # It is very fast when scanning a large number of servers, and it has a dispatching mechanism to avoid DOS-ing a single server against which multiple ScanCommand are run at the same time. # The commands can be queued using the queue_scan_command() method, and the results can later be retrieved using the get_results() method: # Ref: https://nabla-c0d3.github.io/sslyze/documentation/running-scan-commands.html concurrent_scanner = ConcurrentScanner() # Put scans in queue - Put desired scans here # ROBOT concurrent_scanner.queue_scan_command(server_info, RobotScanCommand()) # Heartbleed concurrent_scanner.queue_scan_command(server_info, HeartbleedScanCommand()) # Detecting deprecated/weak ciphers 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, CompressionScanCommand()) # Process the results robot_txt = 'Scan could not be executed' heartbleed_txt = 'Scan could not be executed' drown_txt = 'Scan could not be executed' poodle_txt = 'Scan could not be executed' beast_txt = 'Scan could not be executed' compression_text = 'Scan could not be executed' lucky_text = 'Scan could not be executed' potential_weak_ciphers = set() print(u'\nProcessing results...') for scan_result in concurrent_scanner.get_results(): # Sometimes a scan command can unexpectedly fail (as a bug); it is returned as a PluginRaisedExceptionResult if isinstance(scan_result, PluginRaisedExceptionScanResult): raise RuntimeError(u'Scan command failed: Scan could not be executed!') continue # Each scan result has attributes with the information you're looking for, specific to each scan command # All these attributes are documented within each scan command's module if isinstance(scan_result.scan_command, RobotScanCommand): result_enum = scan_result.robot_result_enum if result_enum == RobotScanResultEnum.VULNERABLE_STRONG_ORACLE: robot_txt = 'Vulnerable - Strong oracle, a real attack is possible' elif result_enum == RobotScanResultEnum.VULNERABLE_WEAK_ORACLE: robot_txt = 'Vulnerable - Weak oracle, the attack would take too long' elif result_enum == RobotScanResultEnum.NOT_VULNERABLE_NO_ORACLE: robot_txt = 'Not vulnerable' elif result_enum == RobotScanResultEnum.NOT_VULNERABLE_RSA_NOT_SUPPORTED: robot_txt = 'Not vulnerable, RSA cipher suites not supported' elif result_enum == RobotScanResultEnum.UNKNOWN_INCONSISTENT_RESULTS: robot_txt = 'Unknown - Received inconsistent results' # Process CRIME elif isinstance(scan_result.scan_command, CompressionScanCommand): compression_text = "Vulnerable" result_compression = scan_result.compression_name if "None" == str(result_compression): compression_text = "Not vulnerable" # Process Heartbleed elif isinstance(scan_result.scan_command, HeartbleedScanCommand): result_heartbleed = scan_result.is_vulnerable_to_heartbleed heartbleed_txt = 'Not vulnerable' if result_heartbleed == True: heartbleed_txt = 'Vulnerable' # Process POODLE elif isinstance(scan_result.scan_command, Sslv30ScanCommand): poodle_txt = 'Not vulnerable' for cipher in scan_result.accepted_cipher_list: potential_weak_ciphers.add(cipher.name) if 'CBC' in cipher.name: poodle_txt = 'Vulnerable' beast_txt = "Not mitigated on server-side" # Process DROWN (a server is vulnerable to DROWN if it allows SSLv2 connections) Ref = https://drownattack.com/ elif isinstance(scan_result.scan_command, Sslv20ScanCommand): drown_txt = 'Not vulnerable' for cipher in scan_result.accepted_cipher_list: potential_weak_ciphers.add(cipher.name) drown_txt = 'Vulnerable' if 'CBC' in cipher.name: beast_txt = "Not mitigated on server-side" # Collect deprecated/weak ciphers elif isinstance(scan_result.scan_command, Tlsv10ScanCommand): beast_txt = "Not vulnerable" for cipher in scan_result.accepted_cipher_list: potential_weak_ciphers.add(cipher.name) if 'CBC' in cipher.name: beast_txt = "Not mitigated on server-side" ## Check for tls version and ciphers not sufficient to detect lucky13 vulnerability elif isinstance(scan_result.scan_command, Tlsv11ScanCommand): #if lucky_text != 'Vulnerable': # lucky_text = 'Not vulnerable' for cipher in scan_result.accepted_cipher_list: potential_weak_ciphers.add(cipher.name) # if 'CBC' in cipher.name: # lucky_text = 'Vulnerable' elif isinstance(scan_result.scan_command, Tlsv12ScanCommand): #if lucky_text != 'Vulnerable': # lucky_text = 'Not vulnerable' for cipher in scan_result.accepted_cipher_list: potential_weak_ciphers.add(cipher.name) # if 'CBC' in cipher.name: # lucky_text = 'Vulnerable' elif isinstance(scan_result.scan_command, Tlsv13ScanCommand): for cipher in scan_result.accepted_cipher_list: potential_weak_ciphers.add(cipher.name) # Process weak ciphers weak_ciphers = getWeakCiphers(potential_weak_ciphers) print("potential_weak_ciphers:") print(potential_weak_ciphers) print("\nweak_ciphers:") print(weak_ciphers) res = collections.OrderedDict() res["BEAST"] = str(beast_txt) res["CRIME"] = str(compression_text) res["DROWN"] = str(drown_txt) res["HEARTBLEED"] = str(heartbleed_txt) res["POODLE"] = str(poodle_txt) res["ROBOT"] = str(robot_txt) res["WEAKCIPHERS"] = 'Not vulnerable' if len(weak_ciphers) == 0 else '\n'.join(str(s) for s in weak_ciphers) #res["LUCKY13"] = str(lucky_text) details = getCertiDetails(hostname_user_input, potential_weak_ciphers) return (res, details)
def run(url): scan_result = { "name": __plugin__, "sequence": SEQUENCE, "result": [], } error_result = { "name": __plugin__, "sequence": SEQUENCE, "result": [], } error_result["result"] = [{ "name": "Error", "result": [{ "name": f"{__plugin__} can't scan this website" }] }] result_map = { "https": { "name": "Enabled HTTPS", "sequence": 0, "result": False }, "effective": { "name": "Effective", "sequence": 1, "result": False }, "match": { "name": "Leaf certificate subject matches hostname", "sequence": 2, "result": False }, "signature": { "name": "Signature security (use SHA256)", "sequence": 3, "result": False }, "public": { "name": "Public key security (use ECDSA_256+ or RSA_2048+)", "sequence": 4, "result": False, }, "tls1_2": { "name": "Support TLS1.2", "sequence": 5, "result": False }, "pfs": { "name": "Perfect Forward Secrecy (PFS)", "sequence": 6, "result": False }, "ats": { "name": "App Transport Security (ATS)", "sequence": 7, "result": False }, "ccs": { "name": "CCS Injection", "sequence": 8, "result": False }, "heartbleed": { "name": "HeartBleed", "sequence": 9, "result": False }, } mini_length = 256 start_time = None end_time = None try: server_tester = ServerConnectivityTester(hostname=url.netloc, port=url.port) server_info = server_tester.perform() except: return error_result synchronous_scanner = SynchronousScanner() certificate_result = synchronous_scanner.run_scan_command( server_info, CertificateInfoScanCommand()) cipher_result = synchronous_scanner.run_scan_command( server_info, Tlsv12ScanCommand()) ccs_result = synchronous_scanner.run_scan_command( server_info, OpenSslCcsInjectionScanCommand()) heartbleed_result = synchronous_scanner.run_scan_command( server_info, HeartbleedScanCommand()) if certificate_result.leaf_certificate_subject_matches_hostname: result_map["match"]["result"] = True for result in certificate_result.as_text(): result_list = [x.strip() for x in result.split(": ")] if len(result_list) == 2: result_map["https"]["result"] = True if result_list[0] == "Public Key Algorithm": if result_list[1] == "_RSAPublicKey": mini_length = 2048 if result_list[0] == "Key Size": if int(result_list[1]) >= mini_length: result_map["public"]["result"] = True if result_list[0] == "Signature Algorithm": if result_list[1] == "sha256": result_map["signature"]["result"] = True if result_list[0] == "Not Before": start_time = result_list[1] if result_list[0] == "Not After": end_time = result_list[1] if start_time and end_time: if (datetime.strptime(start_time, "%Y-%m-%d %H:%M:%S") < datetime.now() and datetime.strptime( end_time, "%Y-%m-%d %H:%M:%S") > datetime.now()): result_map["effective"]["result"] = True cipher_list = [ cipher.name for cipher in cipher_result.accepted_cipher_list ] if cipher_list: result_map["tls1_2"]["result"] = True for cipher in cipher_list: if "DHE" in cipher: result_map["pfs"]["result"] = True if set(cipher_list).intersection(ATS_CIPHER_SET): result_map["ats"]["result"] = True if not ccs_result.is_vulnerable_to_ccs_injection: result_map["ccs"]["result"] = True if not heartbleed_result.is_vulnerable_to_heartbleed: result_map["heartbleed"]["result"] = True scan_result["result"] = sorted([item for item in result_map.values()], key=lambda x: x.get("sequence", 0)) return scan_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 test_ssl_basic(self, hostname, port=443): ''' Uses the `ServerConnectivityTester` functionality of SSlyze to perform a basic test. Port defaults to 443 unless provided otherwise hostname is mandatory | test ssl basic | hostname | port (optional | ''' try: tester = ServerConnectivityTester(hostname=hostname, port=port) server_info = tester.perform() scanner = ConcurrentScanner() # scanner.queue_scan_command(info, certificate_info_plugin.CertificateInfoScanCommand()) scanner.queue_scan_command(server_info, Sslv20ScanCommand()) scanner.queue_scan_command(server_info, Sslv30ScanCommand()) scanner.queue_scan_command(server_info, Tlsv10ScanCommand()) scanner.queue_scan_command(server_info, Tlsv10ScanCommand()) scanner.queue_scan_command(server_info, Tlsv11ScanCommand()) scanner.queue_scan_command(server_info, Tlsv12ScanCommand()) scanner.queue_scan_command(server_info, HeartbleedScanCommand()) scanner.queue_scan_command(server_info, RobotScanCommand()) # scanner.queue_scan_command(server_info, CertificateInfoScanCommand()) for scan_result in scanner.get_results(): # logger.info("Scan result for: {} on hostname: {}".format(scan_result.scan_command.__class__.__name__, scan_result.server_info.hostname)) if isinstance(scan_result, PluginRaisedExceptionScanResult): raise Exception("Scan Command Failed: {}".format( scan_result.as_text())) if isinstance(scan_result.scan_command, Sslv20ScanCommand): if scan_result.accepted_cipher_list: logger.warn("SSLv2 ciphersuites accepted") for suite in scan_result.accepted_cipher_list: logger.info("\t{}".format(suite.name)) else: logger.info("SSLv2 ciphersuites not accepted") if isinstance(scan_result.scan_command, Sslv30ScanCommand): if scan_result.accepted_cipher_list: logger.warn("SSLv3 Cipher Suites accepted") for suite in scan_result.accepted_cipher_list: logger.info("\t{}".format(suite.name)) else: logger.info("SSLv3 ciphersuites not accepted") if isinstance(scan_result.scan_command, Tlsv10ScanCommand): if scan_result.accepted_cipher_list: logger.warn("TLSv1 Cipher Suites accepted") for suite in scan_result.accepted_cipher_list: logger.info("\t{}".format(suite.name)) else: logger.info("TLSv1 ciphersuites not accepted") if isinstance(scan_result.scan_command, Tlsv11ScanCommand): if scan_result.accepted_cipher_list: logger.info("TLSv1.1 Cipher Suites accepted") for suite in scan_result.accepted_cipher_list: logger.info("\t{}".format(suite.name)) else: logger.info("TLSv1.1 ciphersuites not accepted") if isinstance(scan_result.scan_command, Tlsv12ScanCommand): if scan_result.accepted_cipher_list: logger.info("TLSv1.2 Cipher Suites accepted") for suite in scan_result.accepted_cipher_list: logger.info("\t{}".format(suite.name)) else: logger.info("TLSv1.2 ciphersuites not accepted") if isinstance(scan_result.scan_command, HeartbleedScanCommand): if scan_result.is_vulnerable_to_heartbleed: logger.warn( "Server TLS implementation is vulnerable to Heartbleed" ) else: logger.info( "Server TLS Implementation not vulnerable to Heartbleed" ) if isinstance(scan_result.scan_command, RobotScanCommand): logger.info("Test for ROBOT Vulnerability") if scan_result.robot_result_enum.NOT_VULNERABLE_NO_ORACLE: logger.info( "\tNot Vulnerable: The server supports RSA cipher suites but does not act as an oracle" ) elif scan_result.robot_result_enum.VULNERABLE_WEAK_ORACLE: logger.warn( "\tVulnerable: The server is vulnerable but the attack would take too long" ) elif scan_result.robot_result_enum.VULNERABLE_STRONG_ORACLE: logger.warn( "\tVulnerable: The server is vulnerable and real attacks are feasible" ) elif scan_result.robot_result_enum.NOT_VULNERABLE_RSA_NOT_SUPPORTED: logger.info( "\tNot Vulnerable: The server does not supports RSA cipher suites" ) else: logger.info( "\tUnable to determine if implementation is vulnerable" ) # if isinstance(scan_result.scan_command, CertificateInfoScanCommand): # logger.info(u'Server Certificate CN: {}'.format( # dict(scan_result.certificate_chain[0])[u'subject'][u'commonName'] # )) except ServerConnectivityError as e: logger.error('Error when trying to connect to {}: {}'.format( e.server_info.hostname, e.error_message))