Mozilla has released a fix for a critical memory corruption flaw in its NSS cryptographic library that could have allowed an attacker to execute arbitrary code on vulnerable applications simply by supplying an overly large digital signature to the app.
Network Security Services (NSS) is an open-source library developed by Mozilla that is used for a variety of functions across a wide range of applications. Although it is not used in Firefox, it is used in Thunderbird, LibreOffice and many other applications. Researcher Tavis Ormandy of Google’s Project Zero discovered the vulnerability (CVE-2021-43527) with a custom fuzzer he wrote and reported the flaw to Mozilla, which released a fix for the bug in NSS 3.73 this week.
When a user supplies a digital signature encoded with ASN.1 to an application using NSS for verification, NSS creates a structure to store the signature. This is where the problem lies.
“The maximum size signature that this structure can handle is whatever the largest union member is, in this case that’s RSA at 2048 bytes. That’s 16384 bits, large enough to accommodate signatures from even the most ridiculously oversized keys,” Prmandy said in a post explaining the flaw.
“Okay, but what happens if you just....make a signature that’s bigger than that? Well, it turns out the answer is memory corruption. Yes, really. The untrusted signature is simply copied into this fixed-sized buffer, overwriting adjacent members with arbitrary attacker-controlled data.”
Although the vulnerability itself is a common buffer overflow and the exploitable code has been in NSS since 2012, none of internal testing and fuzzing that Mozilla does on a continuous basis, or the external fuzzing done through the oss-fuzz program caught it. Ormandy said this was not the result of poor tooling or processes, but rather the combination of a number of separate factors stemming from the ways in which NSS was fuzzed and tested. One issue is that because NSS is a modular library, each component is tested and fuzzed individually, and another is that fuzzers testing NSS had a limit of 10000 bytes of input.
“There is no such limit within NSS; many structures can exceed this size. This vulnerability demonstrates that errors happen at extremes, so this limit should be chosen thoughtfully,” Ormandy said.
“This issue demonstrates that even extremely well-maintained C/C++ can have fatal, trivial mistakes.”