From edf5bf79a467cb1b7ceac0de801d8de6b6a8f4af Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Wed, 4 Sep 2024 11:47:44 +0200 Subject: [PATCH] Fix CVE-2024-6119: Possible denial of service in X.509 name checks Resolves: RHEL-55303 --- 0139-CVE-2024-6119.patch | 233 +++++++++++++++++++++++++++++++++++++++ openssl.spec | 7 +- 2 files changed, 239 insertions(+), 1 deletion(-) create mode 100644 0139-CVE-2024-6119.patch diff --git a/0139-CVE-2024-6119.patch b/0139-CVE-2024-6119.patch new file mode 100644 index 0000000..a39106a --- /dev/null +++ b/0139-CVE-2024-6119.patch @@ -0,0 +1,233 @@ +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/openssl.spec b/openssl.spec index 2cba14c..9aefbb8 100644 --- a/openssl.spec +++ b/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.2.2 -Release: 11%{?dist} +Release: 12%{?dist} Epoch: 1 Source: openssl-%{version}.tar.gz Source2: Makefile.certificate @@ -180,6 +180,7 @@ Patch135: 0135-Correct-return-values-for-tls_construct_stoc_next_pr.patch Patch136: 0136-Add-ALPN-validation-in-the-client.patch Patch137: 0137-Add-explicit-testing-of-ALN-and-NPN-in-sslapitest.patch Patch138: 0138-Add-a-test-for-an-empty-NextProto-message.patch +Patch139: 0139-CVE-2024-6119.patch License: Apache-2.0 URL: http://www.openssl.org/ @@ -525,6 +526,10 @@ ln -s /etc/crypto-policies/back-ends/openssl_fips.config $RPM_BUILD_ROOT%{_sysco %ldconfig_scriptlets libs %changelog +* Wed Sep 04 2024 Dmitry Belyavskiy - 1:3.2.2-12 +- Fix CVE-2024-6119: Possible denial of service in X.509 name checks + Resolves: RHEL-55303 + * Wed Aug 21 2024 Clemens Lang - 1:3.2.2-11 - Fix CVE-2024-5535: SSL_select_next_proto buffer overread Resolves: RHEL-45692