Target: MongoDB Wire Protocol (Port 27017)
Component: message_compressor_zlib.cpp
Vector: Pre-authentication Remote Network Access
MongoDB is the nervous system of modern infrastructure, handling unstructured data for millions of applications. Its communication layer, the Wire Protocol, sits directly on top of TCP/IP. While legacy implementations used OP_QUERY, modern versions utilize OP_MSG wrapped in a generic BSON envelope.
The vulnerability resides in the Compression Negotiation layer. Introduced in 2012 to optimize bandwidth, the OP_COMPRESSED opcode allows clients to send compressed payloads. While Snappy and Zstd implementations are safe, the Zlib implementation (ID 2)—often the default in package manager distributions—contained a fatal logic error in how it handled memory allocation.
The Context: This Zero-Day was disclosed on December 25, 2025. Attackers leveraged the “Holiday Freeze” fallacy, knowing SOC staffing would be minimal, to harvest credentials before defenders returned.
Root Cause: Information Disclosure via Heap Memory Bleed.
The flaw is a classic Trust-but-Verify failure in C++ memory management. When a client sends a compressed message, the header includes an uncompressedSize field. This field is intended to be a hint for the server to pre-allocate a buffer of the correct size.
The failure occurs in the return logic of the decompression wrapper:
tcmalloc). Crucially, this memory is “dirty”—it contains leftover data from previous operations (e.g., authentication hashes, API keys).output.length() (the allocated capacity of 1MB) instead of the actual bytes_written (1 Byte).The server then treats the entire 1MB buffer as valid response data and reflects it back to the client. The attacker receives their single ‘A’, followed by 1,048,575 bytes of uninitialized server memory.
Standard MongoDB drivers initiate a connection with a polite hello handshake. Exploit scripts are rude; they skip the handshake entirely and immediately transmit a malicious OP_COMPRESSED packet. This works because the wire protocol processes compression before authentication.
To maximize the value of the leak, the attacker must ensure the “dirty” memory contains sensitive data.
SCRAM-SHA-256 hashes, session tokens, and BSON documents.The attacker sends the payload:
uncompressedSize: 1048576zlib("A")The server responds with the massive buffer. The attacker captures the stream and parses it for high-value patterns:
SCRAM-SHA-256 (Authentication hashes)"user": (PII / Usernames)AWS_ACCESS_KEY (Infrastructure compromise)Impact: While primarily an Information Disclosure bug, leaked memory pointers can defeat ASLR (Address Space Layout Randomization), and leaked session tokens allow for immediate Auth Bypass, paving the way for full Remote Code Execution (RCE).
The remediation requires enforcing strict accounting of written bytes. The application must never trust the client’s declared size for the final response.
Vulnerable Logic:
Status swM = zlib::inflate(input, &output);
// FATAL: Returns the allocated capacity, not the actual data size.
return output.length();
Patched Logic:
size_t bytesWritten;
Status swM = zlib::inflate(input, &output, &bytesWritten);
// SECURITY FIX: Resize the buffer to match ONLY the valid data.
output.resize(bytesWritten);
return output.length();
Memory Safety is not solved. The internet runs on C++, and functions like output.length() can be deceptive. The developers assumed it returned the “used” size, but it returned the “reserved” size. This ambiguity caused a critical global vulnerability.
Immediate Action:
mongod.conf to remove zlib from net.compression.compressors.