def get_all_cipher_suites(cls, tls_version: TlsVersionEnum) -> Set[CipherSuite]: """Get the list of cipher suites supported by OpenSSL for the given SSL/TLS version. """ if tls_version in [ TlsVersionEnum.SSL_2_0, TlsVersionEnum.SSL_3_0, TlsVersionEnum.TLS_1_0, TlsVersionEnum.TLS_1_1, ]: openssl_cipher_strings = cls._get_all_cipher_suites_with_legacy_openssl( tls_version) elif tls_version == TlsVersionEnum.TLS_1_2: # For TLS 1.2, we have to use both the legacy and modern OpenSSL to cover all cipher suites cipher_suites_from_legacy_openssl = cls._get_all_cipher_suites_with_legacy_openssl( tls_version) ssl_client_modern = SslClient( ssl_version=OpenSslVersionEnum(tls_version.value)) ssl_client_modern.set_cipher_list("ALL:COMPLEMENTOFALL:-PSK:-SRP") ssl_client_modern.set_ciphersuites( "") # Disable TLS 1.3 cipher suites cipher_suites_from_modern_openssl = set( ssl_client_modern.get_cipher_list()) # Combine the two sets of cipher suites openssl_cipher_strings = cipher_suites_from_legacy_openssl.union( cipher_suites_from_modern_openssl) elif tls_version == TlsVersionEnum.TLS_1_3: ssl_client_modern = SslClient( ssl_version=OpenSslVersionEnum(tls_version.value)) ssl_client_modern.set_cipher_list( "") # Disable NON-TLS-1.3 cipher suites ssl_client_modern.set_ciphersuites( "TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:" "TLS_AES_128_CCM_SHA256:TLS_AES_128_CCM_8_SHA256" ) # Enable all TLS 1.3 cipher suites openssl_cipher_strings = set(ssl_client_modern.get_cipher_list()) else: raise ValueError("Should never happen") return { CipherSuite.from_openssl(cipher_str, tls_version) for cipher_str in openssl_cipher_strings }
def process_task(self, server_connectivity_info, plugin_command, options_dict=None): if options_dict and "verbose" in options_dict.keys(): verbose_mode = options_dict["verbose"] else: verbose_mode = False test_protocols = {"SSLv3", "TLSv1"} thread_pool = ThreadPool() ciphers_list = [] support_protocol_list = [] for proto in test_protocols: if self.test_protocol_support(PROTOCOL_VERSION[proto], server_connectivity_info): ssl_client = SslClient(ssl_version=PROTOCOL_VERSION[proto]) ssl_client.set_cipher_list(proto) ciphers_list = ssl_client.get_cipher_list() for cipher in ciphers_list: thread_pool.add_job( (self._test_ciphersuite, (server_connectivity_info, PROTOCOL_VERSION[proto], cipher)) ) support_protocol_list.append(proto) thread_pool.start(nb_threads=min(len(ciphers_list), self.MAX_THREADS)) accept_ciphers = [] reject_ciphers = [] if verbose_mode: print " VERBOSE MODE PRINT" print " ------------------" for completed_job in thread_pool.get_result(): (job, cipher_result) = completed_job if isinstance(cipher_result, AcceptCipher): accept_ciphers.append(cipher_result) elif isinstance(cipher_result, RejectCipher): reject_ciphers.append(cipher_result) else: raise ValueError("Unexpected result") if verbose_mode: cipher_result.print_cipher() if verbose_mode: print " ----------------------" print " END VERBOSE MODE PRINT" print " ----------------------" for error_job in thread_pool.get_error(): (_, exception) = error_job raise exception thread_pool.join() support_vulnerable_ciphers_set = self.get_vulnerable_ciphers(accept_ciphers) is_vulnerable = True if len(support_vulnerable_ciphers_set) > 0 else False return BEASTVulnerabilityTesterResult( server_connectivity_info, plugin_command, options_dict, support_vulnerable_ciphers_set, is_vulnerable, support_protocol_list, )
def _parse_all_cipher_suites() -> Dict[TlsVersionEnum, Set[CipherSuite]]: tls_version_to_cipher_suites: Dict[TlsVersionEnum, Set[CipherSuite]] = {} for tls_version in [ TlsVersionEnum.SSL_2_0, TlsVersionEnum.SSL_3_0, TlsVersionEnum.TLS_1_0, TlsVersionEnum.TLS_1_1, ]: openssl_cipher_strings = _parse_all_cipher_suites_with_legacy_openssl(tls_version) tls_version_to_cipher_suites[tls_version] = set() for cipher_suite_openssl_name in openssl_cipher_strings: cipher_suite_rfc_name = _OPENSSL_TO_RFC_NAMES_MAPPING[tls_version][cipher_suite_openssl_name] tls_version_to_cipher_suites[tls_version].add( CipherSuite( name=cipher_suite_rfc_name, openssl_name=cipher_suite_openssl_name, is_anonymous=True if "anon" in cipher_suite_rfc_name else False, key_size=_RFC_NAME_TO_KEY_SIZE_MAPPING[cipher_suite_rfc_name], ) ) # For TLS 1.2, we have to use both the legacy and modern OpenSSL to cover all cipher suites cipher_suites_from_legacy_openssl = _parse_all_cipher_suites_with_legacy_openssl(TlsVersionEnum.TLS_1_2) ssl_client_modern = SslClient(ssl_version=OpenSslVersionEnum(TlsVersionEnum.TLS_1_2.value)) ssl_client_modern.set_cipher_list("ALL:COMPLEMENTOFALL:-PSK:-SRP") cipher_suites_from_modern_openssl = set(ssl_client_modern.get_cipher_list()) # Combine the two sets of cipher suites openssl_cipher_strings = cipher_suites_from_legacy_openssl.union(cipher_suites_from_modern_openssl) tls_version_to_cipher_suites[TlsVersionEnum.TLS_1_2] = set() for cipher_suite_openssl_name in openssl_cipher_strings: # Ignore TLS 1.3 cipher suites if cipher_suite_openssl_name in _TLS_1_3_CIPHER_SUITES: continue cipher_suite_rfc_name = _OPENSSL_TO_RFC_NAMES_MAPPING[TlsVersionEnum.TLS_1_2][cipher_suite_openssl_name] tls_version_to_cipher_suites[TlsVersionEnum.TLS_1_2].add( CipherSuite( name=cipher_suite_rfc_name, openssl_name=cipher_suite_openssl_name, is_anonymous=True if "anon" in cipher_suite_rfc_name else False, key_size=_RFC_NAME_TO_KEY_SIZE_MAPPING[cipher_suite_rfc_name], ) ) # TLS 1.3 - the list is just hardcoded tls_version_to_cipher_suites[TlsVersionEnum.TLS_1_3] = { CipherSuite( # For TLS 1.3 OpenSSL started using the official names name=cipher_suite_name, openssl_name=cipher_suite_name, is_anonymous=False, key_size=_RFC_NAME_TO_KEY_SIZE_MAPPING[cipher_suite_name], ) for cipher_suite_name in _TLS_1_3_CIPHER_SUITES } return tls_version_to_cipher_suites
def get_cipher_list(self, ssl_protocol): """Returns list of cipher suites available for protocol version, saves in parameter ssl_protocol. Args: ssl_protocol (str):. """ ssl_client = SslClient(ssl_version=PROTOCOL_VERSION[ssl_protocol]) ssl_client.set_cipher_list('ALL:COMPLEMENTOFALL') return ssl_client.get_cipher_list()
def process_task(self, server_connectivity_info, plugin_command, options_dict=None): ssl_version = self.SSL_VERSIONS_MAPPING[plugin_command] # Get the list of available cipher suites for the given ssl version ssl_client = SslClient(ssl_version=ssl_version) ssl_client.set_cipher_list('ALL:COMPLEMENTOFALL') cipher_list = ssl_client.get_cipher_list() # Scan for every available cipher suite thread_pool = ThreadPool() for cipher in cipher_list: thread_pool.add_job( (self._test_cipher_suite, (server_connectivity_info, ssl_version, cipher))) # Start processing the jobs; One thread per cipher thread_pool.start(nb_threads=min(len(cipher_list), self.MAX_THREADS)) accepted_cipher_list = [] rejected_cipher_list = [] errored_cipher_list = [] # Store the results as they come for completed_job in thread_pool.get_result(): (job, cipher_result) = completed_job if isinstance(cipher_result, AcceptedCipherSuite): accepted_cipher_list.append(cipher_result) elif isinstance(cipher_result, RejectedCipherSuite): rejected_cipher_list.append(cipher_result) elif isinstance(cipher_result, ErroredCipherSuite): errored_cipher_list.append(cipher_result) else: raise ValueError('Unexpected result') # Store thread pool errors; only something completely unexpected would trigger an error for failed_job in thread_pool.get_error(): (_, exception) = failed_job raise exception thread_pool.join() # Test for the cipher suite preference preferred_cipher = self._get_preferred_cipher_suite( server_connectivity_info, ssl_version, accepted_cipher_list) # Generate the results plugin_result = OpenSSLCipherSuitesResult(server_connectivity_info, plugin_command, options_dict, preferred_cipher, accepted_cipher_list, rejected_cipher_list, errored_cipher_list) return plugin_result
def process_task(self, server_connectivity_info, plugin_command, options_dict=None): ssl_version = self.SSL_VERSIONS_MAPPING[plugin_command] # Get the list of available cipher suites for the given ssl version ssl_client = SslClient(ssl_version=ssl_version) ssl_client.set_cipher_list('ALL:COMPLEMENTOFALL') cipher_list = ssl_client.get_cipher_list() # Scan for every available cipher suite thread_pool = ThreadPool() for cipher in cipher_list: thread_pool.add_job((self._test_cipher_suite, (server_connectivity_info, ssl_version, cipher))) # Start processing the jobs; One thread per cipher thread_pool.start(nb_threads=min(len(cipher_list), self.MAX_THREADS)) accepted_cipher_list = [] rejected_cipher_list = [] errored_cipher_list = [] # Store the results as they come for completed_job in thread_pool.get_result(): (job, cipher_result) = completed_job if isinstance(cipher_result, AcceptedCipherSuite): accepted_cipher_list.append(cipher_result) elif isinstance(cipher_result, RejectedCipherSuite): rejected_cipher_list.append(cipher_result) elif isinstance(cipher_result, ErroredCipherSuite): errored_cipher_list.append(cipher_result) else: raise ValueError('Unexpected result') # Store thread pool errors; only something completely unexpected would trigger an error for failed_job in thread_pool.get_error(): (_, exception) = failed_job raise exception thread_pool.join() # Test for the cipher suite preference preferred_cipher = self._get_preferred_cipher_suite(server_connectivity_info, ssl_version, accepted_cipher_list) # Generate the results plugin_result = OpenSSLCipherSuitesResult(server_connectivity_info, plugin_command, options_dict, preferred_cipher, accepted_cipher_list, rejected_cipher_list, errored_cipher_list) return plugin_result
def test_set_ciphersuites(self): # Given an SslClient for TLS 1.3 ssl_client = SslClient( ssl_version=OpenSslVersionEnum.TLSV1_3, ssl_verify=OpenSslVerifyEnum.NONE, ignore_client_authentication_requests=True, ) # With the default list of cipher disabled ssl_client.set_cipher_list("") # When setting a specific TLS 1.3 cipher suite as the list of supported ciphers ssl_client.set_ciphersuites("TLS_CHACHA20_POLY1305_SHA256") # That one cipher suite is the only one enabled ciphers = ssl_client.get_cipher_list() assert ["TLS_CHACHA20_POLY1305_SHA256"] == ciphers
def test_set_ciphersuites(self): # Given an SslClient for TLS 1.3 ssl_client = SslClient( ssl_version=OpenSslVersionEnum.TLSV1_3, ssl_verify=OpenSslVerifyEnum.NONE, ignore_client_authentication_requests=True, ) # With the default list of cipher disabled ssl_client.set_cipher_list('') # When setting a specific TLS 1.3 cipher suite as the list of supported ciphers ssl_client.set_ciphersuites('TLS_CHACHA20_POLY1305_SHA256') # That one cipher suite is the only one enabled ciphers = ssl_client.get_cipher_list() assert ['TLS_CHACHA20_POLY1305_SHA256'] == ciphers
def get_ssl3_cipher_list(self): """Returns list of cipher suites available for protocol SSL 3.0 """ ssl_client = SslClient(ssl_version=SSLV3) ssl_client.set_cipher_list('SSLv3') return ssl_client.get_cipher_list()
def process_task(self, server_connectivity_info, plugin_command, options_dict=None): if options_dict and 'verbose' in options_dict.keys(): verbose_mode = options_dict['verbose'] else: verbose_mode = False test_protocols = {'SSLv3', 'TLSv1'} thread_pool = ThreadPool() ciphers_list = [] support_protocol_list = [] for proto in test_protocols: if self.test_protocol_support(PROTOCOL_VERSION[proto], server_connectivity_info): ssl_client = SslClient(ssl_version=PROTOCOL_VERSION[proto]) ssl_client.set_cipher_list(proto) ciphers_list = ssl_client.get_cipher_list() for cipher in ciphers_list: thread_pool.add_job((self._test_ciphersuite, (server_connectivity_info, PROTOCOL_VERSION[proto], cipher))) support_protocol_list.append(proto) thread_pool.start(nb_threads=min(len(ciphers_list), self.MAX_THREADS)) accept_ciphers = [] reject_ciphers = [] if verbose_mode: print ' VERBOSE MODE PRINT' print ' ------------------' for completed_job in thread_pool.get_result(): (job, cipher_result) = completed_job if isinstance(cipher_result, AcceptCipher): accept_ciphers.append(cipher_result) elif isinstance(cipher_result, RejectCipher): reject_ciphers.append(cipher_result) else: raise ValueError("Unexpected result") if verbose_mode: cipher_result.print_cipher() if verbose_mode: print ' ----------------------' print ' END VERBOSE MODE PRINT' print ' ----------------------' for error_job in thread_pool.get_error(): (_, exception) = error_job raise exception thread_pool.join() support_vulnerable_ciphers_set = self.get_vulnerable_ciphers( accept_ciphers) is_vulnerable = True \ if len(support_vulnerable_ciphers_set) > 0 \ else False return BEASTVulnerabilityTesterResult(server_connectivity_info, plugin_command, options_dict, support_vulnerable_ciphers_set, is_vulnerable, support_protocol_list)
def _parse_all_cipher_suites() -> Dict[TlsVersionEnum, Set[CipherSuite]]: tls_version_to_cipher_suites: Dict[TlsVersionEnum, Set[CipherSuite]] = {} for tls_version in [ TlsVersionEnum.SSL_2_0, TlsVersionEnum.SSL_3_0, TlsVersionEnum.TLS_1_0, TlsVersionEnum.TLS_1_1, ]: openssl_cipher_strings = _parse_all_cipher_suites_with_legacy_openssl(tls_version) tls_version_to_cipher_suites[tls_version] = set() for cipher_suite_openssl_name in openssl_cipher_strings: cipher_suite_rfc_name = _OPENSSL_TO_RFC_NAMES_MAPPING[tls_version][cipher_suite_openssl_name] tls_version_to_cipher_suites[tls_version].add( CipherSuite( name=cipher_suite_rfc_name, openssl_name=cipher_suite_openssl_name, is_anonymous=True if "anon" in cipher_suite_rfc_name else False, key_size=_RFC_NAME_TO_KEY_SIZE_MAPPING[cipher_suite_rfc_name], ) ) # For TLS 1.2, we have to use both the legacy and modern OpenSSL to cover all cipher suites cipher_suites_from_legacy_openssl = _parse_all_cipher_suites_with_legacy_openssl(TlsVersionEnum.TLS_1_2) ssl_client_modern = SslClient(ssl_version=OpenSslVersionEnum(TlsVersionEnum.TLS_1_2.value)) ssl_client_modern.set_cipher_list("ALL:COMPLEMENTOFALL:-PSK:-SRP") ssl_client_modern.set_ciphersuites("") # Disable TLS 1.3 cipher suites cipher_suites_from_modern_openssl = set(ssl_client_modern.get_cipher_list()) # Combine the two sets of cipher suites openssl_cipher_strings = cipher_suites_from_legacy_openssl.union(cipher_suites_from_modern_openssl) tls_version_to_cipher_suites[TlsVersionEnum.TLS_1_2] = set() for cipher_suite_openssl_name in openssl_cipher_strings: cipher_suite_rfc_name = _OPENSSL_TO_RFC_NAMES_MAPPING[TlsVersionEnum.TLS_1_2][cipher_suite_openssl_name] tls_version_to_cipher_suites[TlsVersionEnum.TLS_1_2].add( CipherSuite( name=cipher_suite_rfc_name, openssl_name=cipher_suite_openssl_name, is_anonymous=True if "anon" in cipher_suite_rfc_name else False, key_size=_RFC_NAME_TO_KEY_SIZE_MAPPING[cipher_suite_rfc_name], ) ) # TLS 1.3 ssl_client_modern = SslClient(ssl_version=OpenSslVersionEnum(TlsVersionEnum.TLS_1_3.value)) ssl_client_modern.set_cipher_list("") # Disable NON-TLS-1.3 cipher suites ssl_client_modern.set_ciphersuites( "TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:" "TLS_AES_128_CCM_SHA256:TLS_AES_128_CCM_8_SHA256" ) # Enable all TLS 1.3 cipher suites openssl_cipher_strings = set(ssl_client_modern.get_cipher_list()) tls_version_to_cipher_suites[TlsVersionEnum.TLS_1_3] = { CipherSuite( # For TLS 1.3 OpenSSL started using the official names name=cipher_suite_openssl_name, openssl_name=cipher_suite_openssl_name, is_anonymous=False, key_size=_RFC_NAME_TO_KEY_SIZE_MAPPING[cipher_suite_openssl_name], ) for cipher_suite_openssl_name in openssl_cipher_strings } return tls_version_to_cipher_suites