Open Redirect & Unvalidated Forwards
Exploit open redirects in CTF web - filter bypasses, OAuth and SSO chains, and SSRF validation bypass via trusted-domain redirects.
Open Redirect & Unvalidated Forwards
Open redirect means the application sends the user to a URL taken from attacker-controlled input without strict validation (CWE-601). The victim clicks a trusted hostname, but ends up on attacker content - classic phishing. In CTF, redirects are also chain primitives: OAuth redirect_uri tricks, SSO, and SSRF “hop through” trusted domains.
OWASP: Open Redirect, Unvalidated Redirects and Forwards Cheat Sheet.
Typical Parameters
| Parameter | Context |
|---|---|
next, return, returnUrl, continue | After login / logout |
url, redirect, redir, goto | Marketing “exit” links, SSO |
redirect_uri | OAuth / OIDC (must match exact registered URI - misconfigurations happen) |
Example:
https://trusted.example/login?next=https://evil.example/phishBypass Techniques
Never validate URLs with naive string checks (startsWith("https://trusted.com")). Parsers disagree on edge cases.
| Technique | Payload idea |
|---|---|
| Protocol-relative | //evil.com |
| Userinfo | https://trusted.com@evil.com/ (parser-dependent) |
| Backslash | https://trusted.com\evil.com (older IE / odd parsers) |
| Encoding | %2f%2fevil.com, double encoding |
| Tab / CRLF | \t, %0d%0a if reflected into Location |
| Path-only then server joins badly | /\\evil.com |
Use your language’s URL parser (urllib.parse, URL(), java.net.URI) and enforce:
- Scheme is
https(if required) - Host is in an allowlist
- Path starts with
/and stays in-app or map IDs server-side
Attack Chains in CTF
OAuth / OpenID redirect_uri
If the server allows prefix match or wildcard, you may redirect the authorization code to an attacker-controlled endpoint. Always test exact vs substring registration.
SSRF + redirect
Backend fetches https://trusted.com/... (allowed host). trusted.com 302 redirects to http://169.254.169.254/. If the HTTP client follows redirects, you may hit metadata. Mitigation: do not follow redirects or re-validate each hop (SSRF).
Filter bypass for “same site”
Some apps allow https://trusted.com.evil.com when they meant exact host - depends on parser.
Vulnerable vs Fixed (Sketch)
Vulnerable (Python / Flask-style)
from flask import redirect, request
@app.route("/go")
def go():
url = request.args.get("url")
return redirect(url) # NEVERSafer: allowlist host after parsing
from urllib.parse import urlparse
ALLOWED = {"trusted.example"}
@app.route("/go")
def go():
url = request.args.get("url", "/")
p = urlparse(url)
if p.scheme in ("http", "https") and p.hostname in ALLOWED:
return redirect(url)
return redirect("/")Best for “only in-app”: only allow paths
if url.startswith("/") and not url.startswith("//"):
return redirect(url)Checklist
- Map every
redirect,next,return,urlparameter - Try external URLs and protocol-relative
// - Try encoding and slashes variants
- If OAuth exists, test
redirect_uriparsing end-to-end - If SSRF exists, test 302 from “allowed” host to internal IP
- Confirm whether
Locationheader reflects newline injection (historical)
Last updated on