def __init__( self, server_info, plugin_command, plugin_options, hsts_header, hpkp_header, hpkp_report_only, certificate_chain ): super(HttpHeadersResult, self).__init__(server_info, plugin_command, plugin_options) self.hsts_header = ParsedHstsHeader(hsts_header) if hsts_header else None self.hpkp_header = ParsedHpkpHeader(hpkp_header, hpkp_report_only) if hpkp_header else None # Hack: use function in CertificateInfoPlugin to get the verified certificate chain so we can check the pins self.verified_certificate_chain = None parsed_certificate_chain = [Certificate(x509_cert) for x509_cert in certificate_chain] if CertInfoFullResult._is_certificate_chain_order_valid(parsed_certificate_chain): self.verified_certificate_chain = CertInfoFullResult._build_verified_certificate_chain( parsed_certificate_chain ) # Is the pinning configuration valid? self.is_valid_pin_configured = None self.is_backup_pin_configured = None if self.verified_certificate_chain and self.hpkp_header: # Is one of the configured pins in the current server chain? self.is_valid_pin_configured = False server_pin_list = [cert.hpkp_pin for cert in self.verified_certificate_chain] for pin in self.hpkp_header.pin_sha256_list: if pin in server_pin_list: self.is_valid_pin_configured = True break # Is a backup pin configured? self.is_backup_pin_configured = set(self.hpkp_header.pin_sha256_list) != set(server_pin_list)
def as_text(self): txt_result = [self._format_title(u"HTTP Strict Transport Security (HSTS)")] if self.hsts_header: txt_result.append(self._format_field(u"Max Age:", self.hsts_header.max_age)) txt_result.append(self._format_field(u"Include Subdomains:", self.hsts_header.include_subdomains)) txt_result.append(self._format_field(u"Preload:", self.hsts_header.preload)) else: txt_result.append(self._format_field(u"NOT SUPPORTED - Server did not send an HSTS header", u"")) computed_hpkp_pins_text = ["", self._format_title("Computed HPKP Pins for Current Chain")] if self.verified_certificate_chain: for index, cert in enumerate(self.verified_certificate_chain, start=0): cert_subject = CertInfoFullResult._extract_subject_cn_or_oun(cert) if len(cert_subject) > 40: # Make the CN shorter when displaying it cert_subject = "{}...".format(cert_subject[:40]) computed_hpkp_pins_text.append( self.PIN_TXT_FORMAT(("{} - {}".format(index, cert_subject)), cert.hpkp_pin) ) else: computed_hpkp_pins_text.append(self._format_field(CertInfoFullResult.NO_VERIFIED_CHAIN_ERROR_TXT, u"")) txt_result.extend(["", self._format_title(u"HTTP Public Key Pinning (HPKP)")]) if self.hpkp_header: txt_result.append(self._format_field(u"Max Age:", self.hpkp_header.max_age)) txt_result.append(self._format_field(u"Include Subdomains:", self.hpkp_header.include_subdomains)) txt_result.append(self._format_field(u"Report URI:", self.hpkp_header.report_uri)) txt_result.append(self._format_field(u"Report Only:", self.hpkp_header.report_only)) txt_result.append(self._format_field(u"SHA-256 Pin List:", ", ".join(self.hpkp_header.pin_sha256_list))) if self.verified_certificate_chain: pin_validation_txt = ( u"OK - One of the configured pins was found in the certificate chain" if self.is_valid_pin_configured else u"FAILED - Could NOT find any of the configured pins in the certificate chain!" ) txt_result.append(self._format_field(u"Valid Pin:", pin_validation_txt)) backup_txt = ( u"OK - Backup pin found in the configured pins" if self.is_backup_pin_configured else u"FAILED - No backup pin found: all the configured pins are in the certificate chain!" ) txt_result.append(self._format_field(u"Backup Pin:", backup_txt)) else: txt_result.append(self._format_field(u"NOT SUPPORTED - Server did not send an HPKP header", u"")) # Dispay computed HPKP pins last txt_result.extend(computed_hpkp_pins_text) return txt_result
def __init__(self, server_info, plugin_command, plugin_options, hsts_header, hpkp_header, hpkp_report_only, certificate_chain): super(HttpHeadersResult, self).__init__(server_info, plugin_command, plugin_options) self.hsts_header = ParsedHstsHeader( hsts_header) if hsts_header else None self.hpkp_header = ParsedHpkpHeader( hpkp_header, hpkp_report_only) if hpkp_header else None # Hack: use function in CertificateInfoPlugin to get the verified certificate chain so we can check the pins self.verified_certificate_chain = None parsed_certificate_chain = [ Certificate(x509_cert) for x509_cert in certificate_chain ] if CertInfoFullResult._is_certificate_chain_order_valid( parsed_certificate_chain): self.verified_certificate_chain = CertInfoFullResult._build_verified_certificate_chain( parsed_certificate_chain) # Is the pinning configuration valid? self.is_valid_pin_configured = None self.is_backup_pin_configured = None if self.verified_certificate_chain and self.hpkp_header: # Is one of the configured pins in the current server chain? self.is_valid_pin_configured = False server_pin_list = [ cert.hpkp_pin for cert in self.verified_certificate_chain ] for pin in self.hpkp_header.pin_sha256_list: if pin in server_pin_list: self.is_valid_pin_configured = True break # Is a backup pin configured? self.is_backup_pin_configured = set( self.hpkp_header.pin_sha256_list) != set(server_pin_list)
def as_text(self): txt_result = [ self.PLUGIN_TITLE_FORMAT('HTTP Strict Transport Security (HSTS)') ] if self.hsts_header: txt_result.append( self.FIELD_FORMAT("Max Age:", self.hsts_header.max_age)) txt_result.append( self.FIELD_FORMAT("Include Subdomains:", self.hsts_header.include_subdomains)) txt_result.append( self.FIELD_FORMAT("Preload:", self.hsts_header.preload)) else: txt_result.append( self.FIELD_FORMAT( "NOT SUPPORTED - Server did not send an HSTS header", "")) computed_hpkp_pins_text = [ '', self.PLUGIN_TITLE_FORMAT('Computed HPKP Pins for Current Chain') ] if self.verified_certificate_chain: for index, cert in enumerate(self.verified_certificate_chain, start=0): cert_subject = CertInfoFullResult._extract_subject_cn_or_oun( cert) if len(cert_subject) > 40: # Make the CN shorter when displaying it cert_subject = '{}...'.format(cert_subject[:40]) computed_hpkp_pins_text.append( self.PIN_TXT_FORMAT( ('{} - {}'.format(index, cert_subject)), cert.hpkp_pin)) else: computed_hpkp_pins_text.append( self.FIELD_FORMAT( CertInfoFullResult.NO_VERIFIED_CHAIN_ERROR_TXT, "")) txt_result.extend( ['', self.PLUGIN_TITLE_FORMAT('HTTP Public Key Pinning (HPKP)')]) if self.hpkp_header: txt_result.append( self.FIELD_FORMAT("Max Age:", self.hpkp_header.max_age)) txt_result.append( self.FIELD_FORMAT("Include Subdomains:", self.hpkp_header.include_subdomains)) txt_result.append( self.FIELD_FORMAT("Report URI:", self.hpkp_header.report_uri)) txt_result.append( self.FIELD_FORMAT("Report Only:", self.hpkp_header.report_only)) txt_result.append( self.FIELD_FORMAT("SHA-256 Pin List:", ', '.join(self.hpkp_header.pin_sha256_list))) if self.verified_certificate_chain: pin_validation_txt = 'OK - One of the configured pins was found in the certificate chain' \ if self.is_valid_pin_configured \ else 'FAILED - Could NOT find any of the configured pins in the certificate chain!' txt_result.append( self.FIELD_FORMAT("Valid Pin:", pin_validation_txt)) backup_txt = 'OK - Backup pin found in the configured pins' \ if self.is_backup_pin_configured \ else 'FAILED - No backup pin found: all the configured pins are in the certificate chain!' txt_result.append(self.FIELD_FORMAT("Backup Pin:", backup_txt)) else: txt_result.append( self.FIELD_FORMAT( "NOT SUPPORTED - Server did not send an HPKP header", "")) # Dispay computed HPKP pins last txt_result.extend(computed_hpkp_pins_text) return txt_result