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_ccs_injection_good(self): server_test = ServerConnectivityTester(hostname='www.google.com') server_info = server_test.perform() plugin = OpenSslCcsInjectionPlugin() plugin_result = plugin.process_task(server_info, OpenSslCcsInjectionScanCommand()) assert not plugin_result.is_vulnerable_to_ccs_injection assert plugin_result.as_text() assert plugin_result.as_xml()
def run_openssl_ccs_injection_command(self, server_info, synchronous_scanner): command = OpenSslCcsInjectionScanCommand() try: scan_result = synchronous_scanner.run_scan_command( server_info, command) #print('openssl_ccs_injection obtained for ',server_info) return scan_result.is_vulnerable_to_ccs_injection except: #print('openssl_ccs_injection obtained for ',server_info) return None
def test_ccs_injection_good(self): server_info = ServerConnectivityInfo(hostname=u'www.google.com') server_info.test_connectivity_to_server() plugin = OpenSslCcsInjectionPlugin() plugin_result = plugin.process_task(server_info, OpenSslCcsInjectionScanCommand()) self.assertFalse(plugin_result.is_vulnerable_to_ccs_injection) 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_ccs_injection_bad(self): with LegacyOpenSslServer() as server: server_test = ServerConnectivityTester( hostname=server.hostname, ip_address=server.ip_address, port=server.port ) server_info = server_test.perform() plugin = OpenSslCcsInjectionPlugin() plugin_result = plugin.process_task(server_info, OpenSslCcsInjectionScanCommand()) assert plugin_result.is_vulnerable_to_ccs_injection assert plugin_result.as_text() assert plugin_result.as_xml()
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() # OpenSslCcsInjectionPlugin works even when a client cert was not supplied plugin = OpenSslCcsInjectionPlugin() plugin_result = plugin.process_task(server_info, OpenSslCcsInjectionScanCommand()) assert plugin_result.is_vulnerable_to_ccs_injection assert plugin_result.as_text() assert plugin_result.as_xml()
def test_ccs_injection_bad(self): try: server = VulnerableOpenSslServer(port=8012) except NotOnLinux64Error: # The test suite only has the vulnerable OpenSSL version compiled for Linux 64 bits logging.warning( 'WARNING: Not on Linux - skipping test_ccs_injection_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 = OpenSslCcsInjectionPlugin() plugin_result = plugin.process_task(server_info, OpenSslCcsInjectionScanCommand()) server.terminate() self.assertTrue(plugin_result.is_vulnerable_to_ccs_injection) self.assertTrue(plugin_result.as_text()) self.assertTrue(plugin_result.as_xml())
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 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__(OpenSslCcsInjectionScanCommand())
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