Exemplo n.º 1
0
    def test(self):
        leaf_path = os.path.join(os.path.dirname(__file__), '..', 'utils',
                                 'github.com.pem')
        with open(leaf_path, 'rb') as leaf_file:
            leaf_pem = leaf_file.read()

        certificate = load_pem_x509_certificate(leaf_pem, default_backend())

        self.assertIsNone(
            CertificateUtils.matches_hostname(certificate, 'www.github.com'))
        with self.assertRaises(ssl.CertificateError):
            self.assertFalse(
                CertificateUtils.matches_hostname(certificate,
                                                  'notgithub.com'))

        self.assertEqual(
            CertificateUtils.get_common_names(certificate.subject),
            ['github.com'])
        self.assertEqual(
            CertificateUtils.get_dns_subject_alternative_names(certificate),
            ['github.com', 'www.github.com'])

        self.assertEqual(
            CertificateUtils.get_printable_name(certificate.issuer),
            'DigiCert SHA2 Extended Validation Server CA')
Exemplo n.º 2
0
    def test(self):
        leaf_path = Path(__file__).absolute().parent / '..' / 'utils' / 'github.com.pem'
        leaf_pem = leaf_path.read_bytes()
        certificate = load_pem_x509_certificate(leaf_pem, default_backend())

        assert CertificateUtils.matches_hostname(certificate, 'www.github.com') is None

        with pytest.raises(ssl.CertificateError):
            assert not CertificateUtils.matches_hostname(certificate, 'notgithub.com')

        assert CertificateUtils.get_common_names(certificate.subject) == ['github.com']
        assert CertificateUtils.get_dns_subject_alternative_names(certificate) == [
            'github.com', 'www.github.com'
        ]

        expected_name = 'DigiCert SHA2 Extended Validation Server CA'
        assert CertificateUtils.get_name_as_short_text(certificate.issuer) == expected_name
Exemplo n.º 3
0
    def test(self):
        leaf_path = os.path.join(os.path.dirname(__file__), '..', 'utils', 'github.com.pem')
        with open(leaf_path, 'rb') as leaf_file:
            leaf_pem = leaf_file.read()

        certificate = load_pem_x509_certificate(leaf_pem, default_backend())

        self.assertIsNone(CertificateUtils.matches_hostname(certificate, 'www.github.com'))
        with self.assertRaises(ssl.CertificateError):
            self.assertFalse(CertificateUtils.matches_hostname(certificate, 'notgithub.com'))

        self.assertEqual(CertificateUtils.get_common_names(certificate.subject), ['github.com'])
        self.assertEqual(CertificateUtils.get_dns_subject_alternative_names(certificate), ['github.com',
                                                                                           'www.github.com'])

        self.assertEqual(CertificateUtils.get_name_as_short_text(certificate.issuer),
                         'DigiCert SHA2 Extended Validation Server CA')
Exemplo n.º 4
0
    def test(self):
        leaf_path = Path(
            __file__).absolute().parent / '..' / 'utils' / 'github.com.pem'
        leaf_pem = leaf_path.read_bytes()
        certificate = load_pem_x509_certificate(leaf_pem, default_backend())

        assert CertificateUtils.matches_hostname(certificate,
                                                 'www.github.com') is None

        with pytest.raises(ssl.CertificateError):
            assert not CertificateUtils.matches_hostname(
                certificate, 'notgithub.com')

        assert CertificateUtils.get_common_names(
            certificate.subject) == ['github.com']
        assert CertificateUtils.get_dns_subject_alternative_names(
            certificate) == ['github.com', 'www.github.com']

        expected_name = 'DigiCert SHA2 Extended Validation Server CA'
        assert CertificateUtils.get_name_as_short_text(
            certificate.issuer) == expected_name
Exemplo n.º 5
0
    def __init__(
            self,
            server_info: ServerConnectivityInfo,
            scan_command: CertificateInfoScanCommand,
            certificate_chain: List[Certificate],
            path_validation_result_list: List[PathValidationResult],
            path_validation_error_list: List[PathValidationError],
            ocsp_response: OcspResponse
    ) -> None:
        super().__init__(server_info, scan_command)
        # Find the first trust store that successfully validated the certificate chain
        self.successful_trust_store = None

        # Sort the path_validation_result_list so the same successful_trust_store always get picked for a given server
        # because threading timings change the order of path_validation_result_list
        def sort_function(path_validation: PathValidationResult) -> str:
            return path_validation.trust_store.name.lower()

        path_validation_result_list.sort(key=sort_function)
        for path_result in path_validation_result_list:
            if path_result.is_certificate_trusted:
                self.successful_trust_store = path_result.trust_store

        self.ocsp_response = None
        self.is_ocsp_response_trusted = None
        self.ocsp_response_status = None
        if ocsp_response:
            self.ocsp_response_status = ocsp_response.status
            # We only keep the dictionary as a nassl.OcspResponse is not pickable
            self.ocsp_response = ocsp_response.as_dict()
            if self.successful_trust_store and self.ocsp_response_status == OcspResponseStatusEnum.SUCCESSFUL:
                try:
                    ocsp_response.verify(self.successful_trust_store.path)
                    self.is_ocsp_response_trusted = True
                except OcspResponseNotTrustedError:
                    self.is_ocsp_response_trusted = False

        self.certificate_chain = certificate_chain

        # Check if it is EV - we only have the EV OIDs for Mozilla
        self.is_leaf_certificate_ev = TrustStoresRepository.get_default().get_main_store().is_extended_validation(
            self.certificate_chain[0]
        )

        # Look for the Must-Staple extension
        has_must_staple = CertificateUtils.has_ocsp_must_staple_extension(self.certificate_chain[0])
        self.certificate_has_must_staple_extension = has_must_staple

        # Look for the certificate transparency extension
        self.certificate_included_scts_count = CertificateUtils.count_scts_in_sct_extension(self.certificate_chain[0])

        # Try to build the verified chain
        self.verified_certificate_chain: List[Certificate] = []
        self.is_certificate_chain_order_valid = True
        if self.successful_trust_store:
            try:
                self.verified_certificate_chain = self.successful_trust_store.build_verified_certificate_chain(
                    self.certificate_chain
                )
            except InvalidCertificateChainOrderError:
                self.is_certificate_chain_order_valid = False
            except AnchorCertificateNotInTrustStoreError:
                pass

        self.has_anchor_in_certificate_chain = None
        if self.verified_certificate_chain:
            self.has_anchor_in_certificate_chain = self.verified_certificate_chain[-1] in self.certificate_chain

        self.path_validation_result_list = path_validation_result_list
        self.path_validation_error_list = path_validation_error_list
        try:
            CertificateUtils.matches_hostname(certificate_chain[0], server_info.tls_server_name_indication)
            self.certificate_matches_hostname = True
        except CertificateError:
            self.certificate_matches_hostname = False

        # Check if a SHA1-signed certificate is in the chain
        # Root certificates can still be signed with SHA1 so we only check leaf and intermediate certificates
        self.has_sha1_in_certificate_chain = None
        if self.verified_certificate_chain:
            self.has_sha1_in_certificate_chain = False
            for cert in self.verified_certificate_chain[:-1]:
                if isinstance(cert.signature_hash_algorithm, hashes.SHA1):
                    self.has_sha1_in_certificate_chain = True
                    break

        # Check if this is a distrusted Symantec-issued chain
        self.symantec_distrust_timeline = _SymantecDistructTester.get_distrust_timeline(self.verified_certificate_chain)
Exemplo n.º 6
0
    def __init__(
            self,
            server_info,  # type: ServerConnectivityInfo
            scan_command,  # type: CertificateInfoScanCommand
            certificate_chain,  # type: List[cryptography.x509.Certificate]
            path_validation_result_list,  # type: List[PathValidationResult]
            path_validation_error_list,  # type: List[PathValidationError]
            ocsp_response  # type: OcspResponse
    ):
        # type: (...) -> None
        super(CertificateInfoScanResult,
              self).__init__(server_info, scan_command)
        # Find the first trust store that successfully validated the certificate chain
        self.successful_trust_store = None

        # Sort the path_validation_result_list so the same successful_trust_store always get picked for a given server
        # because threading timings change the order of path_validation_result_list
        def sort_function(path_validation):
            # type: (PathValidationResult) -> Text
            return path_validation.trust_store.name.lower()

        path_validation_result_list.sort(key=sort_function)
        for path_result in path_validation_result_list:
            if path_result.is_certificate_trusted:
                self.successful_trust_store = path_result.trust_store

        self.ocsp_response = None
        self.is_ocsp_response_trusted = None
        if ocsp_response:
            # We only keep the dictionary as a nassl.OcspResponse is not pickable
            self.ocsp_response = ocsp_response.as_dict()
            if self.successful_trust_store:
                try:
                    ocsp_response.verify(self.successful_trust_store.path)
                    self.is_ocsp_response_trusted = True
                except OcspResponseNotTrustedError:
                    self.is_ocsp_response_trusted = False

        self.certificate_chain = certificate_chain

        # Check if it is EV - we only have the EV OIDs for Mozilla
        self.is_leaf_certificate_ev = TrustStoresRepository.get_main(
        ).is_extended_validation(self.certificate_chain[0])

        # Try to build the verified chain
        self.verified_certificate_chain = []
        self.is_certificate_chain_order_valid = True
        if self.successful_trust_store:
            try:
                self.verified_certificate_chain = self.successful_trust_store.build_verified_certificate_chain(
                    self.certificate_chain)
            except InvalidCertificateChainOrderError:
                self.is_certificate_chain_order_valid = False
            except AnchorCertificateNotInTrustStoreError:
                pass

        self.has_anchor_in_certificate_chain = None
        if self.verified_certificate_chain:
            self.has_anchor_in_certificate_chain = self.verified_certificate_chain[
                -1] in self.certificate_chain

        self.path_validation_result_list = path_validation_result_list
        self.path_validation_error_list = path_validation_error_list
        try:
            CertificateUtils.matches_hostname(
                certificate_chain[0], server_info.tls_server_name_indication)
            self.certificate_matches_hostname = True
        except CertificateError:
            self.certificate_matches_hostname = False

        # Check if a SHA1-signed certificate is in the chain
        # Root certificates can still be signed with SHA1 so we only check leaf and intermediate certificates
        self.has_sha1_in_certificate_chain = None
        if self.verified_certificate_chain:
            self.has_sha1_in_certificate_chain = False
            for cert in self.verified_certificate_chain[:-1]:
                if isinstance(cert.signature_hash_algorithm, hashes.SHA1):
                    self.has_sha1_in_certificate_chain = True
                    break
Exemplo n.º 7
0
    def __init__(
            self,
            server_info: ServerConnectivityInfo,
            scan_command: CertificateInfoScanCommand,
            certificate_chain: List[Certificate],
            path_validation_result_list: List[PathValidationResult],
            path_validation_error_list: List[PathValidationError],
            ocsp_response: OcspResponse
    ) -> None:
        super().__init__(server_info, scan_command)
        # Find the first trust store that successfully validated the certificate chain
        self.successful_trust_store = None

        # Sort the path_validation_result_list so the same successful_trust_store always get picked for a given server
        # because threading timings change the order of path_validation_result_list
        def sort_function(path_validation: PathValidationResult) -> str:
            return path_validation.trust_store.name.lower()

        path_validation_result_list.sort(key=sort_function)
        for path_result in path_validation_result_list:
            if path_result.is_certificate_trusted:
                self.successful_trust_store = path_result.trust_store

        self.ocsp_response = None
        self.is_ocsp_response_trusted = None
        self.ocsp_response_status = None
        if ocsp_response:
            self.ocsp_response_status = ocsp_response.status
            # We only keep the dictionary as a nassl.OcspResponse is not pickable
            self.ocsp_response = ocsp_response.as_dict()
            if self.successful_trust_store and self.ocsp_response_status == OcspResponseStatusEnum.SUCCESSFUL:
                try:
                    ocsp_response.verify(self.successful_trust_store.path)
                    self.is_ocsp_response_trusted = True
                except OcspResponseNotTrustedError:
                    self.is_ocsp_response_trusted = False

        self.certificate_chain = certificate_chain

        # Check if it is EV - we only have the EV OIDs for Mozilla
        self.is_leaf_certificate_ev = TrustStoresRepository.get_default().get_main_store().is_extended_validation(
            self.certificate_chain[0]
        )

        # Look for the Must-Staple extension
        has_must_staple = CertificateUtils.has_ocsp_must_staple_extension(self.certificate_chain[0])
        self.certificate_has_must_staple_extension = has_must_staple

        # Look for the certificate transparency extension
        self.certificate_included_scts_count = CertificateUtils.count_scts_in_sct_extension(self.certificate_chain[0])

        # Try to build the verified chain
        self.verified_certificate_chain: List[Certificate] = []
        self.is_certificate_chain_order_valid = True
        if self.successful_trust_store:
            try:
                self.verified_certificate_chain = self.successful_trust_store.build_verified_certificate_chain(
                    self.certificate_chain
                )
            except InvalidCertificateChainOrderError:
                self.is_certificate_chain_order_valid = False
            except AnchorCertificateNotInTrustStoreError:
                pass

        self.has_anchor_in_certificate_chain = None
        if self.verified_certificate_chain:
            self.has_anchor_in_certificate_chain = self.verified_certificate_chain[-1] in self.certificate_chain

        self.path_validation_result_list = path_validation_result_list
        self.path_validation_error_list = path_validation_error_list
        try:
            CertificateUtils.matches_hostname(certificate_chain[0], server_info.tls_server_name_indication)
            self.certificate_matches_hostname = True
        except CertificateError:
            self.certificate_matches_hostname = False

        # Check if a SHA1-signed certificate is in the chain
        # Root certificates can still be signed with SHA1 so we only check leaf and intermediate certificates
        self.has_sha1_in_certificate_chain = None
        if self.verified_certificate_chain:
            self.has_sha1_in_certificate_chain = False
            for cert in self.verified_certificate_chain[:-1]:
                if isinstance(cert.signature_hash_algorithm, hashes.SHA1):
                    self.has_sha1_in_certificate_chain = True
                    break

        # Check if this is a distrusted Symantec-issued chain
        self.symantec_distrust_timeline = _SymantecDistructTester.get_distrust_timeline(self.verified_certificate_chain)
def sslyzeScan(threadname, connection, url):

    logfile_connection = 'log/' + scriptname + '-error-connections.log'
    logfile_other = 'log/' + scriptname + '-error-other.log'
    logfile_scan = 'log/' + scriptname + '-error-other.log'

    has_ip = 0
    is_reachable = 0

    has_ip = getIP(url)

    if has_ip:
        try:
            server_tester = ServerConnectivityTester(hostname=url)
            server_info = server_tester.perform()
            is_reachable = 1
        except ServerConnectivityError:
            with open(logfile_connection, 'a') as log:
                log.write('Error, ' + time.strftime("%Y-%m-%d %H:%M:%S") +
                          ', ' + threadname + ': Could not connect to host: ' +
                          url + '\n')
        except Exception:
            with open(logfile_other, 'a') as log:
                log.write('Error, ' + time.strftime("%Y-%m-%d %H:%M:%S") +
                          ', ' + threadname + ': Thrown error for host: ' +
                          url + '\n')
    else:
        with open(logfile_connection, 'a') as log:
            log.write('Error, ' + time.strftime("%Y-%m-%d %H:%M:%S") + ', ' +
                      threadname + ': Could not resolve host: ' + url + '\n')

    if (is_reachable):
        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,
                                              HeartbleedScanCommand())
        concurrent_scanner.queue_scan_command(server_info,
                                              HttpHeadersScanCommand())
        concurrent_scanner.queue_scan_command(server_info,
                                              CertificateInfoScanCommand())

        # Process the 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):
                with open(logfile_scan, 'a') as log:
                    log.write('Error, ' + time.strftime("%Y-%m-%d %H:%M:%S") +
                              ', Scan command failed: {}'.format(
                                  scan_result.as_text()) + '\n')

            if isinstance(scan_result.scan_command, Sslv20ScanCommand):
                ssl_version = "sslv2"
                try:
                    if len(scan_result.accepted_cipher_list) == 0:
                        supports_sslv2 = 0
                    else:
                        supports_sslv2 = 1
                        for cipher in scan_result.accepted_cipher_list:
                            cipher = (u'{}'.format(cipher.name))
                            sql_command = (
                                'insert into ' + tbl_supported_ciphers +
                                '(url,cipher,version) values (%s,%s,%s)')
                            sql_data = (url, cipher, ssl_version)
                            cur0 = connection.cursor()
                            cur0.execute(sql_command, sql_data)
                            connection.commit()
                            cur0.close()
                except AttributeError:
                    with open(logfile_scan, 'a') as log:
                        log.write(
                            'Error, ' + time.strftime("%Y-%m-%d %H:%M:%S") +
                            ', ' + threadname +
                            ': Could not get sslv2 attributes for host: ' +
                            url + '\n')
                    supports_sslv2 = 0

            if isinstance(scan_result.scan_command, Sslv30ScanCommand):
                ssl_version = "sslv3"
                try:
                    if len(scan_result.accepted_cipher_list) == 0:
                        supports_sslv3 = 0
                    else:
                        supports_sslv3 = 1
                        for cipher in scan_result.accepted_cipher_list:
                            cipher = (u'{}'.format(cipher.name))
                            sql_command = (
                                'insert into ' + tbl_supported_ciphers +
                                '(url,cipher,version) values (%s,%s,%s)')
                            sql_data = (url, cipher, ssl_version)
                            cur0 = connection.cursor()
                            cur0.execute(sql_command, sql_data)
                            connection.commit()
                            cur0.close()
                except AttributeError:
                    with open(logfile_scan, 'a') as log:
                        log.write(
                            'Error, ' + time.strftime("%Y-%m-%d %H:%M:%S") +
                            ', ' + threadname +
                            ': Could not get sslv3 attributes for host: ' +
                            url + '\n')
                    supports_sslv3 = 0

            if isinstance(scan_result.scan_command, Tlsv10ScanCommand):
                ssl_version = "tlsv10"
                try:
                    if len(scan_result.accepted_cipher_list) == 0:
                        supports_tlsv10 = 0
                    else:
                        supports_tlsv10 = 1
                        for cipher in scan_result.accepted_cipher_list:
                            cipher = (u'{}'.format(cipher.name))
                            sql_command = (
                                'insert into ' + tbl_supported_ciphers +
                                '(url,cipher,version) values (%s,%s,%s)')
                            sql_data = (url, cipher, ssl_version)
                            cur0 = connection.cursor()
                            cur0.execute(sql_command, sql_data)
                            connection.commit()
                            cur0.close()
                except AttributeError:
                    with open(logfile_scan, 'a') as log:
                        log.write(
                            'Error, ' + time.strftime("%Y-%m-%d %H:%M:%S") +
                            ', ' + threadname +
                            ': Could not get tlsv10 attributes for host: ' +
                            url + '\n')
                    supports_tlsv10 = 0

            if isinstance(scan_result.scan_command, Tlsv11ScanCommand):
                ssl_version = "tlsv11"
                try:
                    if len(scan_result.accepted_cipher_list) == 0:
                        supports_tlsv11 = 0
                    else:
                        supports_tlsv11 = 1
                        for cipher in scan_result.accepted_cipher_list:
                            cipher = (u'{}'.format(cipher.name))
                            sql_command = (
                                'insert into ' + tbl_supported_ciphers +
                                '(url,cipher,version) values (%s,%s,%s)')
                            sql_data = (url, cipher, ssl_version)
                            cur0 = connection.cursor()
                            cur0.execute(sql_command, sql_data)
                            connection.commit()
                            cur0.close()
                except AttributeError:
                    with open(logfile_scan, 'a') as log:
                        log.write(
                            'Error, ' + time.strftime("%Y-%m-%d %H:%M:%S") +
                            ', ' + threadname +
                            ': Could not get tlsv11 attributes for host: ' +
                            url + '\n')
                    supports_tlsv11 = 0

            if isinstance(scan_result.scan_command, Tlsv12ScanCommand):
                ssl_version = "tlsv12"
                try:
                    if len(scan_result.accepted_cipher_list) == 0:
                        supports_tlsv12 = 0
                    else:
                        supports_tlsv12 = 1
                        for cipher in scan_result.accepted_cipher_list:
                            cipher = (u'{}'.format(cipher.name))
                            sql_command = (
                                'insert into ' + tbl_supported_ciphers +
                                '(url,cipher,version) values (%s,%s,%s)')
                            sql_data = (url, cipher, ssl_version)
                            cur0 = connection.cursor()
                            cur0.execute(sql_command, sql_data)
                            connection.commit()
                            cur0.close()
                except AttributeError:
                    with open(logfile_scan, 'a') as log:
                        log.write(
                            'Error, ' + time.strftime("%Y-%m-%d %H:%M:%S") +
                            ', ' + threadname +
                            ': Could not get tlsv12 attributes for host: ' +
                            url + '\n')
                    supports_tlsv12 = 0

            if isinstance(scan_result.scan_command, Tlsv13ScanCommand):
                ssl_version = "tlsv13"
                try:
                    if len(scan_result.accepted_cipher_list) == 0:
                        supports_tlsv13 = 0
                    else:
                        supports_tlsv13 = 1
                        for cipher in scan_result.accepted_cipher_list:
                            cipher = (u'{}'.format(cipher.name))
                            sql_command = (
                                'insert into ' + tbl_supported_ciphers +
                                '(url,cipher,version) values (%s,%s,%s)')
                            sql_data = (url, cipher, ssl_version)
                            cur0 = connection.cursor()
                            cur0.execute(sql_command, sql_data)
                            connection.commit()
                            cur0.close()
                except AttributeError:
                    with open(logfile_scan, 'a') as log:
                        log.write(
                            'Error, ' + time.strftime("%Y-%m-%d %H:%M:%S") +
                            ', ' + threadname +
                            ': Could not get tlsv13 attributes for host: ' +
                            url + '\n')
                    supports_tlsv13 = 0

            if isinstance(scan_result.scan_command, HeartbleedScanCommand):
                vulnerable_heartbleed = 0
                try:
                    if (scan_result.is_vulnerable_to_heartbleed):
                        vulnerable_heartbleed = 1
                except AttributeError:
                    with open(logfile_scan, 'a') as log:
                        log.write(
                            'Error, ' + time.strftime("%Y-%m-%d %H:%M:%S") +
                            ', ' + threadname +
                            ': Could not get heartbleed attribute for host: ' +
                            url + '\n')
                    vulnerable_heartbleed = 0

            if isinstance(scan_result.scan_command, HttpHeadersScanCommand):
                hsts_preload_set = 0
                hsts_include_subdomains_set = 0
                hsts_max_age_set = 0
                hsts_supported = 0
                hpkp_supported = 0

                try:
                    if (scan_result.hsts_header):
                        hsts_supported = 1
                        if (scan_result.hsts_header.preload):
                            hsts_preload_set = 1
                        if (scan_result.hsts_header.include_subdomains
                            ) == True:
                            hsts_include_subdomains_set = 1
                        hsts_max_age_set = scan_result.hsts_header.max_age
                except AttributeError:
                    with open(logfile_scan, 'a') as log:
                        log.write(
                            'Error, ' + time.strftime("%Y-%m-%d %H:%M:%S") +
                            ', ' + threadname +
                            ': Could not get hsts attributes for host: ' +
                            url + '\n')
                    hsts_preload_set = 0
                    hsts_include_subdomains_set = 0
                    hsts_max_age_set = 0
                    hsts_supported = 0

                try:
                    if (scan_result.hpkp_header):
                        hpkp_supported = 1
                except AttributeError:
                    hpkp_supported = 0

            if isinstance(scan_result.scan_command,
                          CertificateInfoScanCommand):
                chain_is_trusted = 0
                try:
                    if (scan_result.verified_certificate_chain):
                        chain_is_trusted = 1
                except AttributeError:
                    with open(logfile_scan, 'a') as log:
                        log.write(
                            'Error, ' + time.strftime("%Y-%m-%d %H:%M:%S") +
                            ', ' + threadname +
                            ': Could not get hpkp attributes for host: ' +
                            url + '\n')
                    chain_is_trusted = 0

                cert_matches_hostname = 0
                cert_is_ev = False
                try:
                    CertificateUtils.matches_hostname(
                        scan_result.certificate_chain[0],
                        server_info.tls_server_name_indication)
                    cert_matches_hostname = 1
                except CertificateError:
                    cert_matches_hostname = 0
                except AttributeError:
                    with open(logfile_scan, 'a') as log:
                        log.write(
                            'Error, ' + time.strftime("%Y-%m-%d %H:%M:%S") +
                            ', ' + threadname +
                            ': Could not get certificate_chain attribute for host: '
                            + url + '\n')
                try:
                    cert_is_ev = TrustStoresRepository.get_default(
                    ).get_main_store().is_extended_validation(
                        scan_result.certificate_chain[0])
                except AttributeError:
                    with open(logfile_scan, 'a') as log:
                        log.write(
                            'Error, ' + time.strftime("%Y-%m-%d %H:%M:%S") +
                            ', ' + threadname +
                            ': Could not get extended_validation attribute for host: '
                            + url + '\n')

        sql_cmd = (
            'insert into ' + tbl_ssl_options +
            '(url,heartbleed_vulnerable,hsts_supported,hsts_preload_set,hsts_include_subdomains_set,hsts_max_age_set,hpkp_supported,chain_is_trusted,match_hostname,is_ev,sslv2,sslv3,tlsv10,tlsv11,tlsv12,tlsv13) values (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)'
        )
        sql_dat = (url, vulnerable_heartbleed, hsts_supported,
                   hsts_preload_set, hsts_include_subdomains_set,
                   hsts_max_age_set, hpkp_supported, chain_is_trusted,
                   cert_matches_hostname, cert_is_ev, supports_sslv2,
                   supports_sslv3, supports_tlsv10, supports_tlsv11,
                   supports_tlsv12, supports_tlsv13)
        cur = connection.cursor()
        cur.execute(sql_cmd, sql_dat)
        connection.commit()
        cur.close()
Exemplo n.º 9
0
    def perform(self) -> CertificateChainDeploymentAnalysisResult:
        """Run the analysis.
        """
        leaf_cert = self.received_certificate_chain[0]

        # OCSP Must-Staple
        has_ocsp_must_staple = False
        try:
            tls_feature_ext = leaf_cert.extensions.get_extension_for_oid(ExtensionOID.TLS_FEATURE)
            for feature_type in tls_feature_ext.value:
                if feature_type == cryptography.x509.TLSFeatureType.status_request:
                    has_ocsp_must_staple = True
                    break
        except ExtensionNotFound:
            pass

        # Received chain order
        is_chain_order_valid = True
        previous_issuer = None
        for index, cert in enumerate(self.received_certificate_chain):
            current_subject = cert.subject

            if index > 0:
                # Compare the current subject with the previous issuer in the chain
                if current_subject != previous_issuer:
                    is_chain_order_valid = False
                    break
            try:
                previous_issuer = cert.issuer
            except KeyError:
                # Missing issuer; this is okay if this is the last cert
                previous_issuer = u"missing issuer {}".format(index)

        # Check if it is EV - we only have the EV OIDs for Mozilla
        is_leaf_certificate_ev = TrustStoresRepository.get_default().get_main_store().is_extended_validation(
            self.received_certificate_chain[0]
        )

        # Check for Signed Timestamps
        number_of_scts: Optional[int] = 0
        try:
            # Look for the x509 extension
            sct_ext = leaf_cert.extensions.get_extension_for_oid(
                ExtensionOID.PRECERT_SIGNED_CERTIFICATE_TIMESTAMPS
            )

            if isinstance(sct_ext.value, cryptography.x509.UnrecognizedExtension):
                # The version of OpenSSL on the system is too old and can't parse the SCT extension
                number_of_scts = None

            # Count the number of entries in the extension
            number_of_scts = len(sct_ext.value)
        except ExtensionNotFound:
            pass

        # Check if the anchor was sent by the server
        has_anchor_in_certificate_chain = None
        if self.verified_certificate_chain:
            has_anchor_in_certificate_chain = self.verified_certificate_chain[-1] in self.received_certificate_chain

        # Check hostname validation
        try:
            CertificateUtils.matches_hostname(leaf_cert, self.server_hostname)
            certificate_matches_hostname = True
        except CertificateError:
            certificate_matches_hostname = False

        # Check if a SHA1-signed certificate is in the chain
        # Root certificates can still be signed with SHA1 so we only check leaf and intermediate certificates
        has_sha1_in_certificate_chain = None
        if self.verified_certificate_chain:
            has_sha1_in_certificate_chain = False
            for cert in self.verified_certificate_chain[:-1]:
                if isinstance(cert.signature_hash_algorithm, hashes.SHA1):
                    has_sha1_in_certificate_chain = True
                    break

        # Check if this is a distrusted Symantec-issued chain
        verified_chain_has_legacy_symantec_anchor = None
        if self.verified_certificate_chain:
            symantec_distrust_timeline = _SymantecDistructTester.get_distrust_timeline(self.verified_certificate_chain)
            verified_chain_has_legacy_symantec_anchor = True if symantec_distrust_timeline else False

        # Check the OCSP response if there is one
        is_ocsp_response_trusted = None
        ocsp_response_status = None
        if self.received_ocsp_response:
            ocsp_response_status = self.received_ocsp_response.status
            if self.trust_store_used_to_build_verified_chain \
                    and ocsp_response_status == OcspResponseStatusEnum.SUCCESSFUL:
                try:
                    self.received_ocsp_response.verify(self.trust_store_used_to_build_verified_chain.path)
                    is_ocsp_response_trusted = True
                except OcspResponseNotTrustedError:
                    is_ocsp_response_trusted = False

        return CertificateChainDeploymentAnalysisResult(
            leaf_certificate_subject_matches_hostname=certificate_matches_hostname,
            leaf_certificate_has_must_staple_extension=has_ocsp_must_staple,
            leaf_certificate_is_ev=is_leaf_certificate_ev,
            leaf_certificate_signed_certificate_timestamps_count=number_of_scts,
            received_chain_contains_anchor_certificate=has_anchor_in_certificate_chain,
            received_chain_has_valid_order=is_chain_order_valid,
            verified_chain_has_sha1_signature=has_sha1_in_certificate_chain,
            verified_chain_has_legacy_symantec_anchor=verified_chain_has_legacy_symantec_anchor,
            ocsp_response_is_trusted=is_ocsp_response_trusted,
            ocsp_response_status=ocsp_response_status,
        )