CVE-2023-34454 - Fatal Flaw in snappy-java’s Compression—How Integer Overflow Can Crash Your Java Application
snappy-java is a widely used, high-speed Java library for compression and decompression, especially valued in big data circles for its blazing fast performance. But in versions before 1.1.10.1, a simple unchecked multiplication in its code can lead to a catastrophic error. This post details the vulnerability, shows exploitable code paths, and explains with straightforward language how a miscalculation in memory allocation can take down your application.
What is CVE-2023-34454?
CVE-2023-34454 arises due to integer overflow. When snappy-java tries to process unusually large input, it can accidentally create a negative number where a positive one was expected. This can cause either a fatal Java runtime crash or an uncaught exception, making the bug not only exploitable, but also a risk for denial-of-service (DoS) attacks.
The following is a simplified version of the snappy-java bug
// In Snappy.java, vulnerable versions < 1.1.10.1:
public static byte[] compress(char[] input) throws IOException {
int len = input.length * 2; // <-- PROBLEM: possible integer overflow!
return rawCompress(input, , len);
}
// In rawCompress():
private static byte[] rawCompress(char[] input, int offset, int len) throws IOException {
int maxCompressedLength = impl.maxCompressedLength(len); // Native call
byte[] buf = new byte[maxCompressedLength]; // <-- Can cause NegativeArraySizeException!
// ...
}
len gets set to input.length * 2—no check for overflow.
- If input.length is large enough (e.g., slightly over Integer.MAX_VALUE / 2), multiplying by 2 wraps into a negative int!
- The native method maxCompressedLength doesn’t care about Java negative numbers (treats the value as unsigned).
If maxCompressedLength returns a negative value, Java throws NegativeArraySizeException.
- If by luck the value is positive but too low, compression overruns the buffer, causing a JVM Access Violation—an instant, fatal crash.
Exploiting the Bug
You don’t need to be a hacker to trigger this bug—just pass enormous arrays to the affected compression methods. For example:
// POC for NegativeArraySizeException
final int LARGE = Integer.MAX_VALUE / 2 + 1;
char[] bigInput = new char[LARGE];
try {
byte[] result = Snappy.compress(bigInput);
System.out.println("Success: " + result.length);
} catch (Exception e) {
System.err.println("Caught: " + e);
}
*This code will crash with a NegativeArraySizeException.*
compress(short[] input)
Each uses a multiplication factor (e.g. *4, *8) that can easily overflow for sufficiently large array sizes.
Native Side: Why Is This Fatal?
Java arrays cannot have negative sizes. But if you pass the negative length into a native method, it could return a value (thinking it's unsigned). Then, when Java tries to allocate the array, it throws an exception—or worse, an under-allocated buffer leads to memory writes beyond the array bounds, causing a fatal Java Access Violation.
Unrecoverable crash: Fatal JVM errors kill your application with a hard exit.
- Denial of Service risk: Attackers, or even just buggy code, can abuse this to repeatedly crash your app, leading to outages.
- Potential security implications: While remote code execution is unlikely, crashing server processes is a classic DoS technique.
Update your dependency
implementation 'org.xerial.snappy:snappy-java:1.1.10.1'
or
<dependency>
<groupId>org.xerial.snappy</groupId>
<artifactId>snappy-java</artifactId>
<version>1.1.10.1</version>
</dependency>
References
- Official CVE page: CVE-2023-34454
- Security Advisory on GitHub
- Commit that fixed the issue
Conclusion
snappy-java is lightning fast, but unchecked math can be dangerous. Always validate input sizes before performing arithmetic—especially if they’re going to native code! If you’re using snappy-java, update to 1.1.10.1 or later immediately to safeguard your Java apps from dead-simple crashes and denial-of-service exploits.
Timeline
Published on: 06/15/2023 17:15:00 UTC
Last modified on: 06/27/2023 16:04:00 UTC