OAUTH2_REDIRECT_URI_PATH_TRAVERSAL
security
auth_error
ai_generated
true
OAuth2 redirect_uri path traversal allows open redirect to attacker domain
ID: security/oauth2-redirect-uri-path-traversal
78%Fix Rate
85%Confidence
1Evidence
2024-03-12First Seen
Version Compatibility
| Version | Status | Introduced | Deprecated | Notes |
|---|---|---|---|---|
| Spring Security OAuth2 2.5.0 | active | — | — | — |
| OAuth2 Proxy 7.4.0 | active | — | — | — |
| Keycloak 21.0.0 | active | — | — | — |
| Apache Oltu 1.0.2 | active | — | — | — |
Root Cause
OAuth2 provider validates redirect_uri only by prefix match, allowing attacker to use a registered callback URL with a path traversal suffix like ../evil.com to redirect to an external domain.
generic中文
OAuth2提供者仅通过前缀匹配验证redirect_uri,允许攻击者使用注册的回调URL并附加路径遍历后缀如../evil.com重定向到外部域名。
Official Documentation
https://datatracker.ietf.org/doc/html/rfc6749#section-10.6Workarounds
-
92% success Use exact URI matching instead of prefix matching: verify that the redirect_uri exactly matches one of the registered URIs, including path and query parameters. Example in Python with Flask-OAuthlib: 'if redirect_uri not in client.redirect_uris: raise InvalidRedirectURI()'
Use exact URI matching instead of prefix matching: verify that the redirect_uri exactly matches one of the registered URIs, including path and query parameters. Example in Python with Flask-OAuthlib: 'if redirect_uri not in client.redirect_uris: raise InvalidRedirectURI()'
-
88% success Normalize the redirect_uri before validation: decode URL encoding, resolve path traversals, and reject if the normalized URI does not start with the registered base URI. Example: 'from urllib.parse import urlparse, urlunparse; parsed = urlparse(redirect_uri); if '..' in parsed.path: reject'
Normalize the redirect_uri before validation: decode URL encoding, resolve path traversals, and reject if the normalized URI does not start with the registered base URI. Example: 'from urllib.parse import urlparse, urlunparse; parsed = urlparse(redirect_uri); if '..' in parsed.path: reject'
-
85% success Use a whitelist of allowed hosts and enforce that redirect_uri's host matches exactly. Combine with path validation to prevent open redirect.
Use a whitelist of allowed hosts and enforce that redirect_uri's host matches exactly. Combine with path validation to prevent open redirect.
中文步骤
Use exact URI matching instead of prefix matching: verify that the redirect_uri exactly matches one of the registered URIs, including path and query parameters. Example in Python with Flask-OAuthlib: 'if redirect_uri not in client.redirect_uris: raise InvalidRedirectURI()'
Normalize the redirect_uri before validation: decode URL encoding, resolve path traversals, and reject if the normalized URI does not start with the registered base URI. Example: 'from urllib.parse import urlparse, urlunparse; parsed = urlparse(redirect_uri); if '..' in parsed.path: reject'
Use a whitelist of allowed hosts and enforce that redirect_uri's host matches exactly. Combine with path validation to prevent open redirect.
Dead Ends
Common approaches that don't work:
-
95% fail
Does not fix the root cause; attacker can still use path traversal on any registered URI.
-
80% fail
Attackers can use URL encoding (%2e%2e%2f) or double encoding to bypass simple character blacklists.
-
100% fail
Does not address the validation logic; timeout is unrelated to redirect URI validation.