From 7742e918aa7349ef886a8700c009a10f914da112 Mon Sep 17 00:00:00 2001 From: Corey Bonnell Date: Wed, 2 Oct 2024 09:41:58 -0400 Subject: [PATCH] Add validator to flag HTML entities in subject attribute values (#116) * add HTML entity validator to serverauth and smime * modified the csv files because i was missing the source value * Update pkilint/cabf/smime/finding_metadata.csv Co-authored-by: Corey Bonnell * Update pkilint/cabf/serverauth/finding_metadata.csv Co-authored-by: Corey Bonnell --------- Co-authored-by: Michael Lettona Co-authored-by: Mike --- pkilint/cabf/cabf_name.py | 30 ++++++++++++ pkilint/cabf/serverauth/__init__.py | 1 + pkilint/cabf/serverauth/finding_metadata.csv | 1 + pkilint/cabf/smime/finding_metadata.csv | 1 + pkilint/cabf/smime/smime_name.py | 1 + .../org_name_contains_html_chrs.crttest | 49 +++++++++++++++++++ .../locality_contains_html_chrs.crttest | 41 ++++++++++++++++ 7 files changed, 124 insertions(+) create mode 100644 tests/integration_certificate/tls_br/ov_final_certificate/org_name_contains_html_chrs.crttest create mode 100644 tests/integration_certificate/tls_br/ov_pre_certificate/locality_contains_html_chrs.crttest diff --git a/pkilint/cabf/cabf_name.py b/pkilint/cabf/cabf_name.py index 7bd7455..0fc8a86 100644 --- a/pkilint/cabf/cabf_name.py +++ b/pkilint/cabf/cabf_name.py @@ -1,6 +1,7 @@ import typing import unicodedata +import html from iso3166 import countries_by_alpha2 from pyasn1_alt_modules import rfc5280 @@ -230,3 +231,32 @@ def validate(self, node): self.VALIDATION_INSIGNIFICANT_ATTRIUBTE_VALUE_PRESENT, f'Insignificant attribute value: "{value}"' ) + + +class HTMLEntitiesValidator(validation.Validator): + """Validates that attribute values do not contain HTML entities using html.unescape.""" + + VALIDATION_ATTRIBUTE_VALUE_CONTAINS_HTML_ENTITY = validation.ValidationFinding( + validation.ValidationFindingSeverity.ERROR, + 'cabf.name.attribute_value_contains_html_entity' + ) + + def __init__(self): + super().__init__( + validations=[self.VALIDATION_ATTRIBUTE_VALUE_CONTAINS_HTML_ENTITY], + pdu_class=rfc5280.AttributeTypeAndValue + ) + + def validate(self, node): + value_str = asn1_util.get_string_value_from_attribute_node(node) + + if not value_str: + return + + unescaped_value = html.unescape(value_str) + + if value_str != unescaped_value: + raise validation.ValidationFindingEncountered( + self.VALIDATION_ATTRIBUTE_VALUE_CONTAINS_HTML_ENTITY, + f'Attribute value contains HTML entity: "{value_str}"' + ) diff --git a/pkilint/cabf/serverauth/__init__.py b/pkilint/cabf/serverauth/__init__.py index c62ed07..5ffd6de 100644 --- a/pkilint/cabf/serverauth/__init__.py +++ b/pkilint/cabf/serverauth/__init__.py @@ -153,6 +153,7 @@ def create_subject_name_validators() -> List[validation.Validator]: cabf_name.CabfOrganizationIdentifierAttributeValidator(), serverauth_name.ServerauthRelativeDistinguishedNameContainsOneElementValidator(), cabf_name.SignificantAttributeValueValidator(), + cabf_name.HTMLEntitiesValidator(), ] diff --git a/pkilint/cabf/serverauth/finding_metadata.csv b/pkilint/cabf/serverauth/finding_metadata.csv index e5c2475..3dd23db 100644 --- a/pkilint/cabf/serverauth/finding_metadata.csv +++ b/pkilint/cabf/serverauth/finding_metadata.csv @@ -29,6 +29,7 @@ ERROR,cabf.invalid_subject_organization_identifier_format,The format of the subj ERROR,cabf.invalid_subject_organization_identifier_registration_scheme,Unrecognized Registration Scheme specified in the subject organizationIdentifier attribute. ERROR,cabf.invalid_subject_organization_identifier_state_province_for_scheme,A state/province has been specified in the subject organizationIdentifier where the Registration Scheme does not permit one. ERROR,cabf.invalid_subject_organization_identifier_state_province_format,The specified state/province value does not follow the ISO 3166-2 format. +ERROR,cabf.name.attribute_value_contains_html_entity,"""BR 7.1.4.2.2: validates that attribute values do not contain HTML entities.""" ERROR,cabf.rsa_exponent_prohibited_value,"""For RSA key pairs: the CA SHALL confirm that the value of the public exponent is an odd number equal to 3 or more.""" ERROR,cabf.rsa_modulus_invalid_length,"""For RSA key pairs the CA SHALL: Ensure that the modulus size, when encoded, is at least 2048 bits; and Ensure that the modulus size, in bits, is evenly divisible by 8""" ERROR,cabf.serverauth.aia_duplicate_location,"Validates that all URI locations in the AIA extension are unique, as per BR 7.1.2.10.3, 7.1.2.7.7, and 7.1.2.8.3." diff --git a/pkilint/cabf/smime/finding_metadata.csv b/pkilint/cabf/smime/finding_metadata.csv index 39a846b..fa90300 100644 --- a/pkilint/cabf/smime/finding_metadata.csv +++ b/pkilint/cabf/smime/finding_metadata.csv @@ -15,6 +15,7 @@ ERROR,cabf.invalid_subject_organization_identifier_format,SMBR 7.1.4.2.2 (d),The ERROR,cabf.invalid_subject_organization_identifier_registration_scheme,SMBR 7.1.4.2.2 (d),The inclusion of a scheme which is not recognized ERROR,cabf.invalid_subject_organization_identifier_state_province_for_scheme,SMBR 7.1.4.2.2 (d),The inclusion of a state/province value when the scheme does not permit such inclusion ERROR,cabf.invalid_subject_organization_identifier_state_province_format,SMBR 7.1.4.2.2 (d),"The inclusion of a state/province value that violates "" 2 character ISO 3166?2 identifier for the subdivision of the nation in which the Registration Scheme is operated""" +ERROR,cabf.name.attribute_value_contains_html_entity,SMBR 7.1.4.2.2,"""Validates that attribute values do not contain HTML entities.""" ERROR,cabf.no_http_crldp_uri,SMBR 7.1.2.3 (b),"""At least one uniformResourceIdentifier SHALL have the URI scheme HTTP""" ERROR,cabf.rsa_exponent_prohibited_value,SMBR 6.1.6,"""For RSA key pairs: the CA SHALL confirm that the value of the public exponent is an odd number equal to 3 or more.""" ERROR,cabf.rsa_modulus_invalid_length,SMBR 6.1.5,"""For RSA key pairs the CA SHALL: Ensure that the modulus size, when encoded, is at least 2048 bits; and Ensure that the modulus size, in bits, is evenly divisible by 8""" diff --git a/pkilint/cabf/smime/smime_name.py b/pkilint/cabf/smime/smime_name.py index 8fb7c90..dbf67b5 100644 --- a/pkilint/cabf/smime/smime_name.py +++ b/pkilint/cabf/smime/smime_name.py @@ -288,6 +288,7 @@ def create_subscriber_certificate_subject_validator_container( OrganizationIdentifierCountryNameConsistentValidator(), cabf_name.RelativeDistinguishedNameContainsOneElementValidator(), cabf_name.SignificantAttributeValueValidator(), + cabf_name.HTMLEntitiesValidator(), ] return certificate.create_subject_validator_container( diff --git a/tests/integration_certificate/tls_br/ov_final_certificate/org_name_contains_html_chrs.crttest b/tests/integration_certificate/tls_br/ov_final_certificate/org_name_contains_html_chrs.crttest new file mode 100644 index 0000000..5df9214 --- /dev/null +++ b/tests/integration_certificate/tls_br/ov_final_certificate/org_name_contains_html_chrs.crttest @@ -0,0 +1,49 @@ +-----BEGIN CERTIFICATE----- +MIIG9jCCBd6gAwIBAgIQayp2sr3yTpjm3qYZbqMiyTANBgkqhkiG9w0BAQsFADCB +lTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G +A1UEBxMHU2FsZm9yZDEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMT0wOwYDVQQD +EzRTZWN0aWdvIFJTQSBPcmdhbml6YXRpb24gVmFsaWRhdGlvbiBTZWN1cmUgU2Vy +dmVyIENBMB4XDTIzMTExMTAwMDAwMFoXDTI0MTExMDIzNTk1OVowWjELMAkGA1UE +BhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExHDAaBgNVBAoME1dlcnR6ICZhbXA7 +IENvbXBhbnkxGDAWBgNVBAMTD293YS53ZXJ0emNvLmNvbTCCASIwDQYJKoZIhvcN +AQEBBQADggEPADCCAQoCggEBAPEK5EPRotnUhYJdEMkMixf/aaojSGZUhMXqOcpx +ImEpaTLzZgJ5d1hoY4PzCbgorGiIzmjS8qwO1hivzy2PRkxZZc/p6y4ZGeu4TZPL +xfcPggTA2loPoFhIPlnjapd1ChPStl66LIm09boBDWZsZFR4NJoe899N5YJ46Did +7M15aL66pAlJRgB0Y6TFLPXDI8ApnuisdbYZIFQF+GI7yqH8DQVLrCSGSv5WdVfW +16P84N0eq2nfjJALikuKrMOMa6Rxbza8ctvSJPF8vYrddecuo81GCsj5PL/Jbk/d +kpYPgLmdAmoP1V1eKVVNUdFVHbACuFzqz8g4+UNgN+rSgNUCAwEAAaOCA3owggN2 +MB8GA1UdIwQYMBaAFBfZ1iUnZ/kxwklD2TA2RIxsqU/rMB0GA1UdDgQWBBSeTIz0 +/JCNa7ERva7O9GAAU0eg0zAOBgNVHQ8BAf8EBAMCBaAwDAYDVR0TAQH/BAIwADAd +BgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwSgYDVR0gBEMwQTA1BgwrBgEE +AbIxAQIBAwQwJTAjBggrBgEFBQcCARYXaHR0cHM6Ly9zZWN0aWdvLmNvbS9DUFMw +CAYGZ4EMAQICMFoGA1UdHwRTMFEwT6BNoEuGSWh0dHA6Ly9jcmwuc2VjdGlnby5j +b20vU2VjdGlnb1JTQU9yZ2FuaXphdGlvblZhbGlkYXRpb25TZWN1cmVTZXJ2ZXJD +QS5jcmwwgYoGCCsGAQUFBwEBBH4wfDBVBggrBgEFBQcwAoZJaHR0cDovL2NydC5z +ZWN0aWdvLmNvbS9TZWN0aWdvUlNBT3JnYW5pemF0aW9uVmFsaWRhdGlvblNlY3Vy +ZVNlcnZlckNBLmNydDAjBggrBgEFBQcwAYYXaHR0cDovL29jc3Auc2VjdGlnby5j +b20wggF9BgorBgEEAdZ5AgQCBIIBbQSCAWkBZwB2AHb/iD8KtvuVUcJhzPWHujS0 +pM27KdxoQgqf5mdMWjp0AAABi70jn7cAAAQDAEcwRQIgNBNhUkDlHpmXK5FDq8v8 +x5QxywzVrzQ/A+QJr62PrEECIQCTJqodfhcYx6/UHMqEhfsaO0goiS0PtcB9BkWk +6opnvAB2AD8XS0/XIkdYlB1lHIS+DRLtkDd/H4Vq68G/KIXs+GRuAAABi70joKUA +AAQDAEcwRQIgLlWbkniQ5OVMQe8nkZz9d+e+fK6fTI6iXv/gTUNXI40CIQCjXCdZ +ZoQf+UteHv/+5XkQQHVP8nB0jAtiYMZjbnTK7wB1AO7N0GTV2xrOxVy3nbTNE6Iy +h0Z8vOzew1FIWUZxH7WbAAABi70jn+QAAAQDAEYwRAIgJVk8+mU94ItoUulE52b1 +h7mVUIhrxHy0hldkxBs607gCIGnT637lK1Ri49KqQUnkS0elbq5+m8sKMEKeNe4D +sWuXMEEGA1UdEQQ6MDiCD293YS53ZXJ0emNvLmNvbYIYYXV0b2Rpc2NvdmVyLndl +cnR6Y28uY29tggt3ZXJ0emNvLmNvbTANBgkqhkiG9w0BAQsFAAOCAQEAmHteU4dt +EZfHVWaal5ulTZi2OFYxNcKYwmV+PHr0rnl+VwLvW3YhYFd0rtg2KUmaErIndNTj +bFdyKoo+Rl/BSfzK3/ndb2HE4eTsLtMA4sHYFK9NdJbDNC4U4rFsZd7xtVJ0l87Z +Ox+zu9OEmg/g3zvrmIAy6Oh10uNdOWIDcCIa0ynst/NMW4gDX0LQdZsQKJi0Xr1t +UxLAem2H87JM4/AnDP7+Mx+KIfLrAPpQ/66Rlb4ULbclEpYm9QJbQ10vG58wb0Hw +noi8Cli1aQhw8qQvnot2UkEzF6Xi/hgGsI6uAWfNKKsCd0MjbIZpdeFlSk8GInHg +SBoQVAomk0aUtw== +-----END CERTIFICATE----- + +node_path,validator,severity,code,message +certificate.tbsCertificate.subject.rdnSequence,OvSubscriberAttributeAllowanceValidator,WARNING,cabf.serverauth.ov.common_name_attribute_present, +certificate.tbsCertificate.subject.rdnSequence.2.0,HTMLEntitiesValidator,ERROR,cabf.name.attribute_value_contains_html_entity,"Attribute value contains HTML entity: ""Wertz & Company""" +certificate.tbsCertificate.extensions.1.extnValue.subjectKeyIdentifier,SubjectKeyIdentifierValidator,INFO,pkix.subject_key_identifier_method_1_identified, +certificate.tbsCertificate.extensions.2.extnValue.keyUsage,SubscriberKeyUsageValidator,WARNING,cabf.serverauth.subscriber_rsa_digitalsignature_and_keyencipherment_present, +certificate.tbsCertificate.extensions.5.extnValue.certificatePolicies,SubscriberPoliciesValidator,WARNING,cabf.serverauth.subscriber_first_policy_oid_not_reserved, +certificate.tbsCertificate.extensions.5.extnValue.certificatePolicies.0.policyQualifiers.0,CertificatePolicyQualifierValidator,WARNING,cabf.serverauth.certificate_policy_qualifier_present, +certificate.tbsCertificate.extensions,SubscriberExtensionAllowanceValidator,WARNING,cabf.serverauth.subscriber.subject_key_identifier_extension_present, diff --git a/tests/integration_certificate/tls_br/ov_pre_certificate/locality_contains_html_chrs.crttest b/tests/integration_certificate/tls_br/ov_pre_certificate/locality_contains_html_chrs.crttest new file mode 100644 index 0000000..a4088e8 --- /dev/null +++ b/tests/integration_certificate/tls_br/ov_pre_certificate/locality_contains_html_chrs.crttest @@ -0,0 +1,41 @@ +-----BEGIN CERTIFICATE----- +MIIFUjCCBDqgAwIBAgIQD91N/ePVYoMlE3GypbPR4jANBgkqhkiG9w0BAQsFADBP +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMSkwJwYDVQQDEyBE +aWdpQ2VydCBUTFMgUlNBIFNIQTI1NiAyMDIwIENBMTAeFw0yMzAyMDIwMDAwMDBa +Fw0yNDAyMjAyMzU5NTlaMF4xCzAJBgNVBAYTAkJFMR0wGwYDVQQHDBRCcmFpbmUt +bCYjMDM5O0FsbGV1ZDEVMBMGA1UEChMMU2VsbGlnZW50IFNBMRkwFwYDVQQDExBz +YWFzZnMxLnNsZ250LmV1MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA ++r9g7qbFeiB1t7PTn1NvomwnLNT2WhNebigiSLsIxsHtTWWIOgaA0jFUOut8N5vd +Cpyj2c8/kxOtzPwik7skPwfjJ5va7G8qJerCfFN2kozyuDur7nCovOoey1mmlSKe +/2b4mYwO6lw6ytTAioZxCJqfkAeVGggnUDgijiudCzDRbKHRLJqgFdNY+7qlMavA +X2lFi6M5EJmGQjZUFs5IKKAGF1K4LsOq0ervyZG9VKgnIjJF0/uaVvYNiukR6ldl +uGPvRORkXScSkg6pVXtNJk6zBitInBiglJ/7LMys3SegGYl7ew3C09blRI/EHVwb +pmkvN8NAjBUBBrNag0lK7QIDAQABo4ICGTCCAhUwHwYDVR0jBBgwFoAUt2ui6qiq +hIx56rTaD5iyxZV2ufQwHQYDVR0OBBYEFESYGRHZsOSacpKxKTkiGm56pIYCMDEG +A1UdEQQqMCiCEHNhYXNmczEuc2xnbnQuZXWCFHd3dy5zYWFzZnMxLnNsZ250LmV1 +MA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIw +gY8GA1UdHwSBhzCBhDBAoD6gPIY6aHR0cDovL2NybDMuZGlnaWNlcnQuY29tL0Rp +Z2lDZXJ0VExTUlNBU0hBMjU2MjAyMENBMS00LmNybDBAoD6gPIY6aHR0cDovL2Ny +bDQuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VExTUlNBU0hBMjU2MjAyMENBMS00LmNy +bDA+BgNVHSAENzA1MDMGBmeBDAECAjApMCcGCCsGAQUFBwIBFhtodHRwOi8vd3d3 +LmRpZ2ljZXJ0LmNvbS9DUFMwfwYIKwYBBQUHAQEEczBxMCQGCCsGAQUFBzABhhho +dHRwOi8vb2NzcC5kaWdpY2VydC5jb20wSQYIKwYBBQUHMAKGPWh0dHA6Ly9jYWNl +cnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFRMU1JTQVNIQTI1NjIwMjBDQTEtMS5j +cnQwCQYDVR0TBAIwADATBgorBgEEAdZ5AgQDAQH/BAIFADANBgkqhkiG9w0BAQsF +AAOCAQEAn3P7gHwovmGKYxW2Ddc9Z279gkm2eQ0K4b6OtxO+3I2NLAhLNUyH48ER +J0ojBg/jUceDjALwGueP89sNqqLri8H4v3DLyOxr0P0OnHDRHyjB2Frga1rAdQSn +XYkVibgXLC8SLgmKH3AHWVHw6FI7y/Bryx0bqydiGgob4ThU6rpeo6A2y1DXAgFz +xG/KgingJCwXXE9t3AkYZDnFtLH4N9qFS6UBtnHojkHjq0Rjlmz3UiKPthjTCIzh +fB+RCQlLTxQM2YpjOubV5/0E1vdAYjLSodQ0aEBf5DVEQZRs3NOL7cOAPvfidI8g +Jgm4n78e1ojrrKFDYY1DByfcvAkToQ== +-----END CERTIFICATE----- + +node_path,validator,severity,code,message +certificate.tbsCertificate.subject.rdnSequence,OvSubscriberAttributeAllowanceValidator,WARNING,cabf.serverauth.ov.common_name_attribute_present, +certificate.tbsCertificate.subject.rdnSequence.1.0,HTMLEntitiesValidator,ERROR,cabf.name.attribute_value_contains_html_entity,"Attribute value contains HTML entity: ""Braine-l'Alleud""" +certificate.tbsCertificate.extensions.1.extnValue.subjectKeyIdentifier,SubjectKeyIdentifierValidator,INFO,pkix.subject_key_identifier_method_1_identified, +certificate.tbsCertificate.extensions.3.extnValue.keyUsage,SubscriberKeyUsageValidator,WARNING,cabf.serverauth.subscriber_rsa_digitalsignature_and_keyencipherment_present, +certificate.tbsCertificate.extensions.5.extnValue.cRLDistributionPoints,CrlDpDistributionPointCountValidator,WARNING,cabf.serverauth.crldp_multiple_distributionpoints_present, +certificate.tbsCertificate.extensions.6.extnValue.certificatePolicies.0.policyQualifiers.0,CertificatePolicyQualifierValidator,WARNING,cabf.serverauth.certificate_policy_qualifier_present, +certificate.tbsCertificate.extensions.8,SubscriberExtensionCriticalityValidator,ERROR,cabf.serverauth.subscriber.non_critical_basic_constraints_extension, +certificate.tbsCertificate.extensions,SubscriberExtensionAllowanceValidator,WARNING,cabf.serverauth.subscriber.subject_key_identifier_extension_present,