GHSA-pw9p-v7r6-gx4p: Pip/tornado vulnerability
Summary
tornado.web.RedirectHandler builds its target URL by substituting parts of the request path into a template. Depending on where those substitutions appear in the template, an attacker can craft a request that redirects to a host of their choosing. This creates an open redirect on the application's domain, which can be used in phishing.
Impact
Applications are affected if they use RedirectHandler with a URL template where a regex capture group can influence the scheme or host of the redirect. This includes:
- A substitution at the start of the path, for example (r"/(.)/target", RedirectHandler, {"url": "/{0}/destination"}). A request to https://example.com//evil.com/target redirects to //evil.com/destination, a protocol-relative URL pointing to evil.com. Variants using backslashes or encoded characters have the same effect, because browsers treat them as equivalent to //. - A substitution directly after the host, for example (r"/old(.)", RedirectHandler, {"url": "https://new.example.com{0}"}). A request to /old.evil.com/ or /old@evil.com/ redirects to evil.com. - A template that begins with a substitution (such as "{0}"), which can be given an absolute URL.
Applications are not affected if their RedirectHandler templates use only static URLs, or if every substitution comes after a fixed host and a / (for example "/static/{0}" or "https://example.com/{0}"). Other uses of RequestHandler.redirect() are not affected by this advisory, although applications that pass user-controlled input to redirect() should validate it themselves.
Patches
Fixed in Tornado 6.6. RedirectHandler now returns a 400 error if the substituted values would change the scheme or host of the redirect from what the template specifies. As a result, substitutions can no longer be used in the scheme or host part of a template. The similar check in StaticFileHandler has also been hardened against backslash and whitespace variants.
Workarounds
- Change RedirectHandler templates so every substitution comes after a fixed prefix ending in /, or write capture-group regexes that cannot match characters such as /, \, @, . or : where they could affect the host. - Alternatively, replace RedirectHandler with a custom handler that validates the target before calling self.redirect().
Credit
Reported by Longwei Wang (@gn00295120).
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Upgrade
Upgrade
pip/tornadoto a version that resolves this vulnerability.Fixed in 6.6 - Upgrade
Upgrade
Tornadoto a version that resolves this vulnerability.Fixed in 6.6 - Configuration
Change RedirectHandler templates so every substitution follows a fixed prefix ending in `/`, such as `/static/{0}` or `https://example.com/{0}`, or use capture-group regexes that cannot match `/`, `\`, `@`, `.` or `:`. Alternatively replace RedirectHandler with a custom handler that validates the target before calling `self.redirect()`.
tornado.web.RedirectHandler redirect URL templates = No substitutions in scheme or host
Event History
Frequently Asked Questions
Which RedirectHandler routes should be prioritized for review?
Review URL templates in which a regex capture-group substitution can appear at the start of the redirect path, immediately after a host name, or at the beginning of the entire template. Examples include a template such as "/{0}/destination", "https://new.example.com{0}", or "{0}".
What must an attacker control to trigger the redirect?
The attacker needs to send a request whose path matches a vulnerable route and causes the relevant regex capture group to contain redirect-significant content. This can include values that form a protocol-relative URL, alter the host after a fixed host name, or use backslashes or encoded characters that browsers interpret like "//".
How can I determine whether an application is exposed?
Inspect RedirectHandler route definitions and compare each route's regex capture groups with its URL template. The application is affected when attacker-controlled captured text can influence the redirect scheme or host, rather than being confined to a safe path component.