Files

156 lines
4.8 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 客户端 / 现代 Web 靶场 Playbook(DOM XSS · 原型污染 · agent-browser)
> 来源:Gin & Juice / Juice Shop 类合法靶场实战摩擦(2026-07)
> 适用:PortSwigger scanner-eval、OWASP Juice Shop、BB 前端面
> **MUST** 先 scope + case-guard;命中≠打穿
## 0. 何时读本文件
```text
□ 页面有大量前端 JS(React/Angular/Vue)
□ 漏洞清单写着 DOM XSS / prototype pollution / CSTI
□ curl 只能摸到 API,需要浏览器确认 sink
□ Windows 上 URL 带 [] 被 curl 吃掉(见下)
```
## 1. Windows curl 坑(`[]` 被当范围)
**错误:**
```bash
curl "https://target/?__proto__[x]=1" # Windows curl: bad range in position ...
```
**正确(必须):**
```bash
curl.exe --globoff -sS "https://target/?__proto__[test]=polluted"
curl.exe --globoff -sS -G "https://target/catalog" --data-urlencode "__proto__[test]=polluted"
```
PowerShell 里优先:
```powershell
curl.exe --globoff -sS --data-urlencode "q=test" "https://target/search"
```
## 2. 三阶段:Surface → Sink → Chain
| 阶段 | 做什么 | 产出 |
|------|--------|------|
| Surface | 抓 HTML/JS,列 src、表单 action、API | `recon/js-urls.txt` |
| Sink | 搜 `innerHTML` / `eval` / `location.hash` / `document.write` / `__proto__` | 候选 sink 列表 |
| Chain | 找可控 source 能否到 sink(需 200 非数字 / 未转义反射 / merge 对象) | E-* + 是否 validated |
### 2.1 静态 sink 扫(本机)
```powershell
# 下载页面脚本后
rg -n "innerHTML|outerHTML|document\.write|eval\(|location\.hash|__proto__|parseFromString" recon\js\
```
### 2.2 agent-browser 最小环
```powershell
agent-browser open "https://target/page"
agent-browser wait 2000
agent-browser snapshot -i
agent-browser screenshot work\case\screenshots\page.png
agent-browser eval "document.getElementById('stockCheckResult')?.innerHTML"
agent-browser close
```
**纪律:**
```text
□ 每次页面变化后重新 snapshot(ref 会失效)
□ 用 eval 验证 sink,不要只靠猜
□ 截图进 evidence/ 或 screenshots/
```
## 3. DOM XSS:库存类 `innerHTML = fetchBody` 模式
典型代码(Gin & Juice 类):
```javascript
fetch(path, { method, headers: { 'Content-Type': window.contentType }, body: payload(data) })
.then(res => res.status === 200
? res.text().then(t => isNaN(t) ? t : t + " units")
: "Could not fetch stock levels!")
.then(res => document.getElementById("stockCheckResult").innerHTML = res)
```
**门闩:**
| 条件 | 结果 |
|------|------|
| status ≠ 200 | 固定错误文案,**无 XSS** |
| status = 200 且 body 为数字 | 显示 `N units`,**无 XSS** |
| status = 200 且 body 非数字 | **raw HTML → sink** |
**验证 sink(浏览器):**
```javascript
// agent-browser eval
var el = document.getElementById('stockCheckResult');
el.innerHTML = '<b id=xssmark>SINK</b>';
!!document.getElementById('xssmark'); // true => sink 实锤
```
**利用前提:** 找到使 API **200 + 非数字 body** 的输入(XXE 回显、错误被错误配置成 200、开放代理等)。
**没到利用仍要写 Evidence:** `status=observed`,写清门闩,避免假阳性「已 XSS」。
## 4. 原型污染(快检)
```powershell
# URL 编码括号,且 --globoff
curl.exe --globoff -sS "https://target/?__proto__%5Bpolluted%5D=yes"
# 浏览器
agent-browser open "https://target/?__proto__%5Bpolluted%5D=yes"
agent-browser eval "({}.polluted || Object.prototype.polluted || 'not-polluted')"
```
```text
□ not-polluted → 该路由没有浅合并 gadget,换 hash/postMessage/库入口
□ polluted → 继续找 gadgets(script src、transport_url、isAdmin 等)
```
## 5. 公共 demo 不稳时
```text
□ Heroku demo 503 → 换本地 Docker / 另一合法靶 / 缩小请求速率
□ Docker Desktop 已安装但 daemon 未 ready → 等引擎或跳过本地容器,记入 timeline
□ 公开实例限流 → 优先读 JS 静态面,少打爆破
```
## 6. Evidence 写法(防误报)
```text
validated: 可复现利用(弹窗/读文件/越权成功)+ repro_command
observed: sink/面存在,门闩未过(如仅 innerHTML 赋值能力、实体被拦)
```
```powershell
powershell -File skills\scripts\append-evidence.ps1 -CaseRoot work\case `
-Id E-005 -Title "DOM XSS sink: #el.innerHTML = apiBody" `
-ReproCommand "agent-browser eval ..." -Severity medium -Status observed `
-RawExcerpt "status===200 && !isNaN gate"
```
## 7. 与其他 skill
| 发现 | 交接 |
|------|------|
| 前端签名/加密参数 | `js-reverse/` |
| 复杂 SPA 交互验证 | `browser-automation/` |
| BOLA 已登录 API | `api-security/` |
## 8. 诚实完成标准
```text
□ 未打穿 ≠ skill 无效:必须留下 surface + sink + 失败原因
□ 禁止把 observed sink 写成 validated exploit
□ timeline 写清:公网 demo 挂了 / Docker 未起 / curl [] 坑
```