Last month (october 2024), LambdaClass and Fuzzinglabs teams discovered an Out of Memory (OOM) vulnerability within the Gnark library, one of the most popular Go library for zk-SNARKS. During the deserialization of Verifying Keys, we can trigger a fatal error that can lead to DoS (Denial of Service). This discovery led to the assignment of CVE-2024-50354, and our collaboration with the Gnark team resulted in a fix quickly deployed on main version.
This post details our journey from uncovering this vulnerability to working alongside the Gnark developers to address it. We’ll explore the technical background, our analysis of the root cause, the solution implemented, and the broader significance of addressing such flaws in cryptographic libraries.
A Zero-Knowledge Proof (ZKP) is a cryptographic technique that allows one party, the prover, to demonstrate knowledge of specific information (like a secret key) to another party, the verifier, without revealing the information itself.
How ZKPs Work:
A Zero-Knowledge Proof (ZKP) allows someone to prove they know a solution without revealing it. This technology enables private transactions, secure authentication, and confidential voting by ensuring privacy and trust.
SNARKs (Succinct Non-Interactive Arguments of Knowledge) are a type of ZKP that provide both succinctness and non-interactiveness:
In ZK-SNARK systems, two essential keys handle the verification process:
When deserializing the Verifying Key in the Gnark library, we found an Out of Memory (OOM) vulnerability. This issue arises if the program attempts an excessive memory allocation, leading to crashes. The flaw particularly affected applications using the Groth16 proving scheme and was also possible with Proving Keys.
During testing, we observed abnormal memory usage when loading a Verifying Key. This memory surge was due to an incorrect number of commitments (sometimes millions) being read from the serialized file. The original implementation allocated a list based on file data, potentially causing excessive memory allocations. In one instance, the list allocation for commitments, intended for only a few elements, attempted to create billions, which quickly overwhelmed the system.
Example code snippet triggering the error:
The vulnerability stemmed from the ReadFrom function in marshal.go, within the bn254 elliptic curve implementation in Gnark, however, this vulnerability appears for all elliptic curves implemented in gnark, not only bn254. When reading a Verifying Key, this function extracted the nbCommitments value directly from the deserialized file. In our test file, nbCommitments was a staggering 2,327,186,600, leading to memory allocations around ±1 TB – well beyond typical system limits.
The resulting error output highlighted an unrecoverable memory state:
To address the issue, the Gnark developers implemented a safer, iterative approach for deserializing Verifying Keys. Here’s a summary of the fix:
By deserializing keys one by one and validating at each step, Gnark avoids the OOM vulnerability, enhancing stability and resilience.
This fix ensures the inability to compromise the availability of the service, one of the four foundational principles of cybersecurity.
This experience highlights the importance of efficient memory management in cryptographic libraries, where even minor flaws can have significant security implications. Addressing this vulnerability in Gnark contributes to the security of ZK-SNARK implementations, enabling reliable, resource-conscious cryptographic applications.
Our work with the Gnark developers exemplifies the collaborative spirit needed to strengthen the cryptographic ecosystem.
Founded in 2021 and headquartered in Paris, FuzzingLabs is a cybersecurity startup specializing in vulnerability research, fuzzing, and blockchain security. We combine cutting-edge research with hands-on expertise to secure some of the most critical components in the blockchain ecosystem.
Contact us for an audit or long term partnership!