From 95ff7a66ab5898a86e8b082bff66afe9c1f43647 Mon Sep 17 00:00:00 2001 From: Jonathan Wright Date: Tue, 3 Sep 2024 09:36:43 -0500 Subject: [PATCH] Fix Possible DOS in X.509 name checks (CVE-2024-6119) --- SOURCES/0136-CVE-2024-6119.patch | 265 +++++++++++++++++++++++++++++++ SPECS/openssl.spec | 7 +- 2 files changed, 271 insertions(+), 1 deletion(-) create mode 100644 SOURCES/0136-CVE-2024-6119.patch diff --git a/SOURCES/0136-CVE-2024-6119.patch b/SOURCES/0136-CVE-2024-6119.patch new file mode 100644 index 0000000..74941f3 --- /dev/null +++ b/SOURCES/0136-CVE-2024-6119.patch @@ -0,0 +1,265 @@ +From 97ebe37033e8884f4cca5544a74376633c665e11 Mon Sep 17 00:00:00 2001 +From: Viktor Dukhovni +Date: Wed, 19 Jun 2024 21:04:11 +1000 +Subject: [PATCH] Avoid type errors in EAI-related name check logic. + +The incorrectly typed data is read only, used in a compare operation, so +neither remote code execution, nor memory content disclosure were possible. +However, applications performing certificate name checks were vulnerable to +denial of service. + +The GENERAL_TYPE data type is a union, and we must take care to access the +correct member, based on `gen->type`, not all the member fields have the same +structure, and a segfault is possible if the wrong member field is read. + +The code in question was lightly refactored with the intent to make it more +obviously correct. + +CVE-2024-6119 + +(cherry picked from commit 1486960d6cdb052e4fc0109a56a0597b4e902ba1) +--- + crypto/x509/v3_utl.c | 78 +++++++++++++------ + test/recipes/25-test_eai_data.t | 12 ++- + test/recipes/25-test_eai_data/kdc-cert.pem | 21 +++++ + .../25-test_eai_data/kdc-root-cert.pem | 16 ++++ + test/recipes/25-test_eai_data/kdc.sh | 41 ++++++++++ + 5 files changed, 142 insertions(+), 26 deletions(-) + create mode 100644 test/recipes/25-test_eai_data/kdc-cert.pem + create mode 100644 test/recipes/25-test_eai_data/kdc-root-cert.pem + create mode 100755 test/recipes/25-test_eai_data/kdc.sh + +diff --git a/crypto/x509/v3_utl.c b/crypto/x509/v3_utl.c +index 1a18174995..a09414c972 100644 +--- a/crypto/x509/v3_utl.c ++++ b/crypto/x509/v3_utl.c +@@ -916,36 +916,64 @@ static int do_x509_check(X509 *x, const char *chk, size_t chklen, + ASN1_STRING *cstr; + + gen = sk_GENERAL_NAME_value(gens, i); +- if ((gen->type == GEN_OTHERNAME) && (check_type == GEN_EMAIL)) { +- if (OBJ_obj2nid(gen->d.otherName->type_id) == +- NID_id_on_SmtpUTF8Mailbox) { +- san_present = 1; +- +- /* +- * If it is not a UTF8String then that is unexpected and we +- * treat it as no match +- */ +- if (gen->d.otherName->value->type == V_ASN1_UTF8STRING) { +- cstr = gen->d.otherName->value->value.utf8string; +- +- /* Positive on success, negative on error! */ +- if ((rv = do_check_string(cstr, 0, equal, flags, +- chk, chklen, peername)) != 0) +- break; +- } +- } else ++ switch (gen->type) { ++ default: ++ continue; ++ case GEN_OTHERNAME: ++ switch (OBJ_obj2nid(gen->d.otherName->type_id)) { ++ default: + continue; +- } else { +- if ((gen->type != check_type) && (gen->type != GEN_OTHERNAME)) ++ case NID_id_on_SmtpUTF8Mailbox: ++ /*- ++ * https://datatracker.ietf.org/doc/html/rfc8398#section-3 ++ * ++ * Due to name constraint compatibility reasons described ++ * in Section 6, SmtpUTF8Mailbox subjectAltName MUST NOT ++ * be used unless the local-part of the email address ++ * contains non-ASCII characters. When the local-part is ++ * ASCII, rfc822Name subjectAltName MUST be used instead ++ * of SmtpUTF8Mailbox. This is compatible with legacy ++ * software that supports only rfc822Name (and not ++ * SmtpUTF8Mailbox). [...] ++ * ++ * SmtpUTF8Mailbox is encoded as UTF8String. ++ * ++ * If it is not a UTF8String then that is unexpected, and ++ * we ignore the invalid SAN (neither set san_present nor ++ * consider it a candidate for equality). This does mean ++ * that the subject CN may be considered, as would be the ++ * case when the malformed SmtpUtf8Mailbox SAN is instead ++ * simply absent. ++ * ++ * When CN-ID matching is not desirable, applications can ++ * choose to turn it off, doing so is at this time a best ++ * practice. ++ */ ++ if (check_type != GEN_EMAIL ++ || gen->d.otherName->value->type != V_ASN1_UTF8STRING) ++ continue; ++ alt_type = 0; ++ cstr = gen->d.otherName->value->value.utf8string; ++ break; ++ } ++ break; ++ case GEN_EMAIL: ++ if (check_type != GEN_EMAIL) + continue; +- } +- san_present = 1; +- if (check_type == GEN_EMAIL) + cstr = gen->d.rfc822Name; +- else if (check_type == GEN_DNS) ++ break; ++ case GEN_DNS: ++ if (check_type != GEN_DNS) ++ continue; + cstr = gen->d.dNSName; +- else ++ break; ++ case GEN_IPADD: ++ if (check_type != GEN_IPADD) ++ continue; + cstr = gen->d.iPAddress; ++ break; ++ } ++ san_present = 1; + /* Positive on success, negative on error! */ + if ((rv = do_check_string(cstr, alt_type, equal, flags, + chk, chklen, peername)) != 0) +diff --git a/test/recipes/25-test_eai_data.t b/test/recipes/25-test_eai_data.t +index 522982ddfb..e18735d89a 100644 +--- a/test/recipes/25-test_eai_data.t ++++ b/test/recipes/25-test_eai_data.t +@@ -21,16 +21,18 @@ setup("test_eai_data"); + #./util/wrap.pl apps/openssl verify -nameopt utf8 -no_check_time -CAfile test/recipes/25-test_eai_data/utf8_chain.pem test/recipes/25-test_eai_data/ascii_leaf.pem + #./util/wrap.pl apps/openssl verify -nameopt utf8 -no_check_time -CAfile test/recipes/25-test_eai_data/ascii_chain.pem test/recipes/25-test_eai_data/utf8_leaf.pem + +-plan tests => 12; ++plan tests => 16; + + require_ok(srctop_file('test','recipes','tconversion.pl')); + my $folder = "test/recipes/25-test_eai_data"; + + my $ascii_pem = srctop_file($folder, "ascii_leaf.pem"); + my $utf8_pem = srctop_file($folder, "utf8_leaf.pem"); ++my $kdc_pem = srctop_file($folder, "kdc-cert.pem"); + + my $ascii_chain_pem = srctop_file($folder, "ascii_chain.pem"); + my $utf8_chain_pem = srctop_file($folder, "utf8_chain.pem"); ++my $kdc_chain_pem = srctop_file($folder, "kdc-root-cert.pem"); + + my $out; + my $outcnt = 0; +@@ -56,10 +58,18 @@ SKIP: { + + ok(run(app(["openssl", "verify", "-nameopt", "utf8", "-no_check_time", "-CAfile", $ascii_chain_pem, $ascii_pem]))); + ok(run(app(["openssl", "verify", "-nameopt", "utf8", "-no_check_time", "-CAfile", $utf8_chain_pem, $utf8_pem]))); ++ok(run(app(["openssl", "verify", "-nameopt", "utf8", "-no_check_time", "-CAfile", $kdc_chain_pem, $kdc_pem]))); + + ok(!run(app(["openssl", "verify", "-nameopt", "utf8", "-no_check_time", "-CAfile", $ascii_chain_pem, $utf8_pem]))); + ok(!run(app(["openssl", "verify", "-nameopt", "utf8", "-no_check_time", "-CAfile", $utf8_chain_pem, $ascii_pem]))); + ++# Check an otherName does not get misparsed as an DNS name, (should trigger ASAN errors if violated). ++ok(run(app(["openssl", "verify", "-nameopt", "utf8", "-no_check_time", "-verify_hostname", 'mx1.example.com', "-CAfile", $kdc_chain_pem, $kdc_pem]))); ++# Check an otherName does not get misparsed as an email address, (should trigger ASAN errors if violated). ++ok(run(app(["openssl", "verify", "-nameopt", "utf8", "-no_check_time", "-verify_email", 'joe@example.com', "-CAfile", $kdc_chain_pem, $kdc_pem]))); ++# We expect SmtpUTF8Mailbox to be a UTF8 String, not an IA5String. ++ok(!run(app(["openssl", "verify", "-nameopt", "utf8", "-no_check_time", "-verify_email", 'moe@example.com', "-CAfile", $kdc_chain_pem, $kdc_pem]))); ++ + #Check that we get the expected failure return code + with({ exit_checker => sub { return shift == 2; } }, + sub { +diff --git a/test/recipes/25-test_eai_data/kdc-cert.pem b/test/recipes/25-test_eai_data/kdc-cert.pem +new file mode 100644 +index 0000000000..e8a2c6f55d +--- /dev/null ++++ b/test/recipes/25-test_eai_data/kdc-cert.pem +@@ -0,0 +1,21 @@ ++-----BEGIN CERTIFICATE----- ++MIIDbDCCAlSgAwIBAgIBAjANBgkqhkiG9w0BAQsFADAPMQ0wCwYDVQQDDARSb290 ++MCAXDTI0MDYyMDA2MTQxNVoYDzIxMjQwNjIwMDYxNDE1WjAXMRUwEwYDVQQDDAxU ++RVNULkVYQU1QTEUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC6wfP+ ++6go79dkpo/dGLMlPZ7Gw/Q6gUYrCWZWUEgEeRVHCrqOlgUEyA+PcWas/XDPUxXry ++BQlJHLvlqamAQn8gs4QPBARFYWKNiTVGyaRkgNA1N5gqyZdrP9UE+ZJmdqxRAAe8 ++vvpGZWSgevPhLUiSCFYDiD0Rtji2Hm3rGUrReQFBQDEw2pNGwz9zIaxUs08kQZcx ++Yzyiplz5Oau+R/6sAgUwDlrD9xOlUxx/tA/MSDIfkK8qioU11uUZtO5VjkNQy/bT ++7zQMmXxWgm2MIgOs1u4YN7YGOtgqHE9v9iPHHfgrkbQDtVDGQsa8AQEhkUDSCtW9 ++3VFAKx6dGNXYzFwfAgMBAAGjgcgwgcUwHQYDVR0OBBYEFFR5tZycW19DmtbL4Zqj ++te1c2vZLMAkGA1UdIwQCMAAwCQYDVR0TBAIwADCBjQYDVR0RBIGFMIGCoD8GBisG ++AQUCAqA1MDOgDhsMVEVTVC5FWEFNUExFoSEwH6ADAgEBoRgwFhsGa3JidGd0GwxU ++RVNULkVYQU1QTEWgHQYIKwYBBQUHCAmgERYPbW9lQGV4YW1wbGUuY29tgQ9qb2VA ++ZXhhbXBsZS5jb22CD214MS5leGFtcGxlLmNvbTANBgkqhkiG9w0BAQsFAAOCAQEA ++T0xzVtVpRtaOzIhgzw7XQUdzWD5UEGSJJ1cBCOmKUWwDLTAouCYLFB4TbEE7MMUb ++iuMy60bjmVtvfJIXorGUgSadRe5RWJ5DamJWvPA0Q9x7blnEcXqEF+9Td+ypevgU ++UYHFmg83OYwxOsFXZ5cRuXMk3WCsDHQIBi6D1L6oDDZ2pfArs5mqm3thQKVlqyl1 ++El3XRYEdqAz/5eCOFNfwxF0ALxjxVr/Z50StUZU8I7Zfev6+kHhyrR7dqzYJImv9 ++0fTCOBEMjIETDsrA70OxAMu4V16nrWZdJdvzblS2qrt97Omkj+2kiPAJFB76RpwI ++oDQ9fKfUOAmUFth2/R/eGA== ++-----END CERTIFICATE----- +diff --git a/test/recipes/25-test_eai_data/kdc-root-cert.pem b/test/recipes/25-test_eai_data/kdc-root-cert.pem +new file mode 100644 +index 0000000000..a74c96bf31 +--- /dev/null ++++ b/test/recipes/25-test_eai_data/kdc-root-cert.pem +@@ -0,0 +1,16 @@ ++-----BEGIN CERTIFICATE----- ++MIICnDCCAYQCCQCBswYcrlZSHjANBgkqhkiG9w0BAQsFADAPMQ0wCwYDVQQDDARS ++b290MCAXDTI0MDYyMDA2MTQxNVoYDzIxMjQwNjIwMDYxNDE1WjAPMQ0wCwYDVQQD ++DARSb290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqRj8S4kBbIUj ++61kZfi6nE35Q38U140+qt4uAiwAhKumfVHlBM0zQ98WFt5zMHIBQwIb3yjc2zj+0 ++qzUnQfwm1r/RfcMmBPEti9Ge+aEMSsds2gMXziOFM8wd2aAFPy7UVE0XpEWofsRK ++MGi61MKVdPSbGIxBwY9VW38/7D/wf1HtJe7y0xpuecR7GB2XAs+qST59NjuF+7wS ++dLM8Hb3TATgeYbXXWsRJgwz+SPzExg5WmLnU+7y4brZ32dHtdSmkRVSgSlaIf7Xj ++3Tc6Zi7I+W/JYk7hy1zUexVdWCak4PHcoWrXe0gNNN/t8VfLfMExt5z/HIylXnU7 ++pGUyqZlTGQIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQAHpLF1UCRy7b6Hk0rLokxI ++lgwiH9BU9mktigAGASvkbllpt+YbUbWnuYAvpHBGiP1qZtfX2r96UrSJaGO9BEzT ++Gp9ThnSjoj4Srul0+s/NArU22irFLmDzbalgevAmm9gMGkdqkiIm/mXbwrPj0ncl ++KGicevXryVpvaP62eZ8cc3C4p97frMmXxRX8sTdQpD/gRI7prdEILRSKveqT+AEW ++7rFGM5AOevb4U8ddop8A3D/kX0wcCAIBF6jCNk3uEJ57jVcagL04kPnVfdRiedTS ++vfq1DRNcD29d1H/9u0fHdSn1/+8Ep3X+afQ3C6//5NvOEaXcIGO4QSwkprQydfv8 ++-----END CERTIFICATE----- +diff --git a/test/recipes/25-test_eai_data/kdc.sh b/test/recipes/25-test_eai_data/kdc.sh +new file mode 100755 +index 0000000000..7a8dbc719f +--- /dev/null ++++ b/test/recipes/25-test_eai_data/kdc.sh +@@ -0,0 +1,41 @@ ++#! /usr/bin/env bash ++ ++# Create a root CA, signing a leaf cert with a KDC principal otherName SAN, and ++# also a non-UTF8 smtpUtf8Mailbox SAN followed by an rfc822Name SAN and a DNS ++# name SAN. In the vulnerable EAI code, the KDC principal `otherName` should ++# trigger ASAN errors in DNS name checks, while the non-UTF8 `smtpUtf8Mailbox` ++# should likewise lead to ASAN issues with email name checks. ++ ++rm -f root-key.pem root-cert.pem ++openssl req -nodes -new -newkey rsa:2048 -keyout kdc-root-key.pem \ ++ -x509 -subj /CN=Root -days 36524 -out kdc-root-cert.pem ++ ++exts=$( ++ printf "%s\n%s\n%s\n%s = " \ ++ "subjectKeyIdentifier = hash" \ ++ "authorityKeyIdentifier = keyid" \ ++ "basicConstraints = CA:false" \ ++ "subjectAltName" ++ printf "%s, " "otherName:1.3.6.1.5.2.2;SEQUENCE:kdc_princ_name" ++ printf "%s, " "otherName:1.3.6.1.5.5.7.8.9;IA5:moe@example.com" ++ printf "%s, " "email:joe@example.com" ++ printf "%s\n" "DNS:mx1.example.com" ++ printf "[kdc_princ_name]\n" ++ printf "realm = EXP:0, GeneralString:TEST.EXAMPLE\n" ++ printf "principal_name = EXP:1, SEQUENCE:kdc_principal_seq\n" ++ printf "[kdc_principal_seq]\n" ++ printf "name_type = EXP:0, INTEGER:1\n" ++ printf "name_string = EXP:1, SEQUENCE:kdc_principal_components\n" ++ printf "[kdc_principal_components]\n" ++ printf "princ1 = GeneralString:krbtgt\n" ++ printf "princ2 = GeneralString:TEST.EXAMPLE\n" ++ ) ++ ++printf "%s\n" "$exts" ++ ++openssl req -nodes -new -newkey rsa:2048 -keyout kdc-key.pem \ ++ -subj "/CN=TEST.EXAMPLE" | ++ openssl x509 -req -out kdc-cert.pem \ ++ -CA "kdc-root-cert.pem" -CAkey "kdc-root-key.pem" \ ++ -set_serial 2 -days 36524 \ ++ -extfile <(printf "%s\n" "$exts") + diff --git a/SPECS/openssl.spec b/SPECS/openssl.spec index 944551b..0e6ce4b 100644 --- a/SPECS/openssl.spec +++ b/SPECS/openssl.spec @@ -29,7 +29,7 @@ print(string.sub(hash, 0, 16)) Summary: Utilities from the general purpose cryptography library with TLS implementation Name: openssl Version: 3.0.7 -Release: 27%{?dist} +Release: 27%{?dist}.alma.1 Epoch: 1 # We have to remove certain patented algorithms from the openssl source # tarball with the hobble-openssl script which is included below. @@ -214,6 +214,8 @@ Patch133: 0133-CVE-2023-6237.patch Patch134: 0134-engine-based-ECDHE-kex.patch # https://github.com/openssl/openssl/pull/23362 Patch135: 0135-CVE-2024-0727.patch +# https://github.com/openssl/openssl/security/advisories/GHSA-5qrj-vq78-58fj +Patch136: 0136-CVE-2024-6119.patch License: ASL 2.0 URL: http://www.openssl.org/ @@ -553,6 +555,9 @@ ln -s /etc/crypto-policies/back-ends/openssl_fips.config $RPM_BUILD_ROOT%{_sysco %ldconfig_scriptlets libs %changelog +* Tue Sep 03 2024 Jonathan Wright - 1:3.0.7-27.alma.1 +- Fix Possible denial of service in X.509 name checks (CVE-2024-6119) + * Wed Feb 21 2024 Dmitry Belyavskiy - 1:3.0.7-27 - Use certified FIPS module instead of freshly built one in Red Hat distribution Related: RHEL-23474 -- 2.43.5