Listen to this Post
Tornado is vulnerable to a high-severity Denial-of-Service (DoS) attack due to improper handling of multipart/form-data payloads . In software versions prior to 6.5.5, the framework only enforced a `max_body_size` limit (default 100MB) on such requests, but placed no restrictions on the number of individual parts contained within that body . Because the parsing of these parts occurs synchronously on the main event loop thread, an attacker can craft a malicious request with a massive number of tiny parts. Even though the total body size remains under the 100MB threshold, the CPU cost of parsing each boundary and part sequentially can exhaust server resources, blocking the processing of legitimate traffic and causing a Denial-of-Service . The vulnerability is fixed in version 6.5.5, which introduces configurable limits via tornado.httputil.ParseMultipartConfig, including a default cap of 100 parts per request to mitigate the attack vector .
dailycve form:
Platform: Tornado
Version: <6.5.5
Vulnerability : multipart parsing DoS
Severity: High (CVSS:4.0 8.7)
date: March 11, 2026
Prediction: include expected Patch date. March 10, 2026
What Undercode Say:
Analytics:
The vulnerability stems from a missing algorithmic complexity control. By sending a multipart/form-data request with thousands of parts (e.g., thousands of small file fields or text fields), the server spends excessive CPU time iterating over boundaries. The following bash command can simulate a basic malicious request using curl:
Generate a large number of parts and send them
This creates a boundary and repeats 'field' thousands of times
curl -X POST http://target.com/upload \
-H "Content-Type: multipart/form-data; boundary=BOUNDARY" \
--data-binary @- << EOF
`for i in {1..5000}; do
echo "--BOUNDARY"
echo 'Content-Disposition: form-data; name="field'$i'"'
echo ""
echo "value"
done`
--BOUNDARY--
EOF
In Python, the vulnerable parsing logic resides in tornado.httputil.parse_multipart_form_data. Before the patch, the parser would iterate without a part limit. After the patch, the configuration object enforces a maximum:
Example of configuring the new limits in Tornado 6.5.5+ from tornado.httputil import ParseMultipartConfig Custom configuration to increase part limit if needed config = ParseMultipartConfig( max_parts=200, Default is 100 max_part_size=25 1024 1024 25MB per part ) In your handler, you can access the settings class UploadHandler(tornado.web.RequestHandler): def post(self): The parsing now respects the limits automatically pass
How Exploit:
An attacker sends a single HTTP POST request with a `Content-Type: multipart/form-data` header. The body contains an extremely large number of parts (e.g., 10,000 parts), each containing minimal data (like a single character). The server’s main thread becomes occupied parsing these parts synchronously, causing thread starvation and making the application unresponsive to other clients.
Protection from this CVE:
- Upgrade: Immediately update Tornado to version 6.5.5 or later .
- Configuration: If upgrading is not immediately possible, implement a reverse proxy (like Nginx) to inspect and limit multipart request structures before they reach the Tornado backend.
- Hard Limits: After upgrading, review the `ParseMultipartConfig` settings to ensure `max_parts` is set appropriately for your application’s needs (the default 100 is usually sufficient) .
- Disable Unused Features: If your application does not require file uploads or form multipart data, disable the parser entirely via the configuration settings .
Impact:
Successful exploitation leads to resource exhaustion (CPU spikes) and service unavailability. Since the attack requires only a single HTTP request with a relatively small total size (under 100MB), it is easily executed by a low-skilled attacker without the need for a botnet. Critical web services relying on Tornado for asynchronous operations are at risk of prolonged downtime until the malicious request is fully processed or the server is restarted.
🎯Let’s Practice Exploiting & Learn Patching For Free:
Sources:
Reported By: github.com
Extra Source Hub:
Undercode

