triage-validation
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseTRIAGE & VALIDATION
分诊与验证
One wrong answer = STOP this finding. Kill the finding. Move on to the next test class.
Scope of "STOP" in this skill: This skill's gates kill INDIVIDUAL FINDINGS that fail validation. They do NOT authorize stopping the engagement. Killing a finding via the 7-Question Gate just means that finding doesn't get submitted — every other test class in the engagement is still pending. See"DO NOT STOP primary directive" for the coverage-axis rule.redteam-mindset
"N/A hurts your validity ratio. Informative is neutral. Only submit what passes all 7 questions."
任何一个问题回答错误 = 立即停止该漏洞发现。淘汰该漏洞发现。继续下一个测试类别。
本 skill 中“STOP”的适用范围: 本 skill 的各项门控会淘汰未通过验证的单个漏洞发现,但并不授权结束整个测试活动。通过 7-Question Gate 淘汰某个漏洞发现,只表示该漏洞发现不会提交——测试活动中的每个其他测试类别仍待测试。请参阅的“DO NOT STOP primary directive”(覆盖轴规则)。redteam-mindset
“N/A 比例过高会损害你的有效率。Informative 是中性结果。只提交通过全部 7 个问题的发现。”
THE 7-QUESTION GATE
7 问门控
Ask IN ORDER. One wrong answer = STOP immediately.
按顺序提问。任何一个问题回答错误 = 立即停止。
Q1: Can an attacker use this RIGHT NOW, step by step?
Q1:攻击者现在能否一步一步利用此漏洞?
Complete this template:
1. Setup: I need [own account / another user's ID / no account]
2. Request: [exact HTTP method, URL, headers, body — copy-paste ready]
3. Result: I can [read / modify / delete] [exact data shown in response]
4. Impact: The real-world consequence is [account takeover / PII read / money stolen]
5. Cost: Time: [X minutes], Capital: [$0 / $X subscription required]If you CANNOT write step 2 as a real HTTP request → KILL IT.
完成以下模板:
1. 环境准备:我需要 [自己的账户 / 另一个用户的 ID / 无需账户]
2. 请求: [准确的 HTTP method、URL、headers、body——可直接复制粘贴]
3. 结果: 我可以 [读取 / 修改 / 删除] [响应中显示的确切数据]
4. 影响: 现实世界后果是 [账户接管 / 读取 PII / 盗取资金]
5. 成本: 时间:[X 分钟],资金:[需要 $0 / $X 订阅]如果无法将第 2 步写成真实的 HTTP 请求 → 淘汰它。
Q2: Is the impact on the program's accepted impact list?
Q2:影响是否属于项目认可的影响清单?
Go to the program page. Find "Vulnerability Types" or "Out of Scope."
Common tiers:
- Critical: Any-user ATO without interaction, RCE, SQLi with data exfil, admin auth bypass
- High: Mass PII exfil, privilege escalation, internal SSRF with data, stored XSS all users
- Medium: IDOR on specific user non-critical data, XSS on sensitive page requiring click
- Low: Non-sensitive info disclosure, clickjacking with PoC
If your bug maps to a listed exclusion → KILL IT.
前往项目页面。查找“Vulnerability Types”或“Out of Scope”。
常见等级:
- 严重(Critical):无需交互的任意用户 ATO、RCE、伴随数据外泄的 SQLi、管理员 auth bypass
- 高危(High):大规模 PII 外泄、权限提升、可获取数据的内网 SSRF、影响所有用户的存储型 XSS
- 中危(Medium):访问特定用户非关键数据的 IDOR、需要点击才能利用的敏感页面 XSS
- 低危(Low):非敏感信息泄露、附带 PoC 的 clickjacking
如果你的漏洞对应某项明确排除项 → 淘汰它。
Q3: Is the root cause in an in-scope asset?
Q3:根本原因是否位于范围内资产中?
Confirm:
- Vulnerable domain is on the in-scope list (not )
*.internal.target.com - It's a production asset (not staging/dev unless explicitly in scope)
- It's not a third-party service the company just uses (not Stripe, Salesforce, Google Auth)
If out-of-scope → KILL IT.
确认:
- 存在漏洞的域名位于 in-scope 列表中(而不是 )
*.internal.target.com - 它是生产资产(除非明确纳入范围,否则不能是 staging/dev)
- 它不是公司仅使用的第三方服务(不能是 Stripe、Salesforce、Google Auth)
如果超出范围 → 淘汰它。
Q4: Does it require privileged access that an attacker can't realistically get?
Q4:它是否需要攻击者在现实中无法获得的特权访问?
- "Admin can do X" = centralization risk = KILL IT (on 99% of programs)
- "Non-admin can do X that only admin should do" = valid
- "Requires physical access / MFA device" = usually invalid
- "Requires compromised victim account to work" = questionable, low severity at best
- “Admin can do X” = 权限集中化风险 = 淘汰它(适用于 99% 的项目)
- “Non-admin can do X that only admin should do” = 有效
- “Requires physical access / MFA device” = 通常无效
- “Requires compromised victim account to work” = 存疑,最多是低严重性
Q5: Is this already known or accepted behavior?
Q5:这是否属于已知或已被接受的行为?
Search:
- Program's HackerOne/Bugcrowd disclosed reports: Ctrl+F endpoint name + bug class
- GitHub issues on target repo:
is:issue label:security ENDPOINT_NAME - Changelog/CHANGELOG.md — does it mention this behavior?
- API docs / design docs — is it documented as intended?
If acknowledged/design decision → KILL IT.
搜索:
- 项目在 HackerOne/Bugcrowd 上已公开的报告:Ctrl+F 搜索端点名称 + 漏洞类别
- 目标仓库的 GitHub issues:
is:issue label:security ENDPOINT_NAME - Changelog/CHANGELOG.md——是否提到了此行为?
- API 文档/设计文档——是否将其记录为预期行为?
如果这是已知问题或设计决策 → 淘汰它。
Q6: Can you prove impact beyond "technically possible"?
Q6:能否证明“技术上可行”之外的实际影响?
- XSS → show actual cookie theft or session hijack, not just or
alert(1)alert(document.domain) - SSRF → hit an internal endpoint that returns data, not just DNS ping
- SQLi → show actual data exfil from a real table, not just error message
- IDOR → show actual other-user's data in response, not just a 200 status code
If you can only show "technically possible" → DOWNGRADE severity, not kill.
- XSS → 展示实际的 cookie 窃取或 session 劫持,而不只是 或
alert(1)alert(document.domain) - SSRF → 命中会返回数据的内网端点,而不只是 DNS ping
- SQLi → 展示从真实表中实际外泄数据,而不只是错误消息
- IDOR → 展示响应中实际包含其他用户的数据,而不只是 200 状态码
如果只能证明“技术上可行” → 降低严重性,而不是淘汰。
Q7: Is this a known-invalid bug class?
Q7:这是否属于已知无效的漏洞类别?
Check the NEVER SUBMIT list below. If it's on this list without a chain → KILL IT.
检查下方的 NEVER SUBMIT 清单。如果它在清单中且没有利用链 → 淘汰它。
THE LAYER-ORDERING TRAP — read before claiming any auth bypass
层级顺序陷阱——声称任何 auth bypass 前必读
A validation error does NOT prove you passed authentication.
This is the highest-confidence false positive in the auth-bypass class, because the
evidence looks concrete. The reasoning that fails:
"I sent an unauthenticated request and got back. A validation error means the request cleared auth and reached business logic. Therefore auth is missing."400 — field X is required
That inference is only valid if auth runs before input handling. Many stacks put a
global input sanitiser, body parser, or schema filter in front of the auth
middleware. A malformed body is then rejected before auth is ever consulted, and
the response is indistinguishable from "auth passed, validation failed."
The test: re-send with a minimal WELL-FORMED body.
bash
undefined验证错误并不能证明你已通过身份验证。
这是 auth-bypass 类中置信度最高的误报,因为证据看似确凿。以下推理会失效:
“我发送了未认证请求,却收到。 验证错误意味着请求已越过 auth 并进入业务逻辑。 因此缺少 auth。”400 — field X is required
只有当 auth 位于输入处理之前时,这一推论才成立。许多 stack 会在
auth middleware 前放置 global input sanitiser、body parser 或 schema filter。
格式错误的 body 随后会在查询 auth 之前被拒绝,而且该响应与“auth 通过、验证失败”无法区分。
测试:使用最小且格式正确的 body 重新发送。
bash
undefinedmalformed body — trips the sanitiser, which runs FIRST
malformed body — trips the sanitiser, which runs FIRST
curl -s -X POST https://target/api/v1/resource -d '{'
curl -s -X POST https://target/api/v1/resource -d '{'
400 {"code":"ERR-INPUT-0001","message":"Invalid text. Only permitted
400 {"code":"ERR-INPUT-0001","message":"Invalid text. Only permitted
characters are allowed"} <- looks like auth bypass
characters are allowed"} <- looks like auth bypass
same endpoint, well-formed empty object — now auth is reached
same endpoint, well-formed empty object — now auth is reached
curl -s -X POST https://target/api/v1/resource -H 'Content-Type: application/json' -d '{}'
curl -s -X POST https://target/api/v1/resource -H 'Content-Type: application/json' -d '{}'
401 {"code":"ERR-AUTH-0001","message":"Not authenticated. Please log in."}
401 {"code":"ERR-AUTH-0001","message":"Not authenticated. Please log in."}
**Only the second response tells you where the auth layer sits.**
**Lesson from an authorized engagement.** On a production API, a malformed body
returned a validation-shaped `400` on the large majority of endpoints tested. Read
as an auth bypass, that is a Critical filed against production infrastructure
covering financial and administrative operations. It was a sanitiser reacting to
the `{` character before auth ran — every one of those endpoints returned `401` to
a well-formed `{}`. The false Critical was avoided only because someone re-tested.
**Rules:**
- Layer ordering is not observable from a single response. Never infer it.
- Probe auth with the *simplest valid* body the parser will accept, not a malformed one.
- If the error text is about **input shape or character class**, you are talking to a
parser or sanitiser, not to business logic.
- If the error text names a **domain field** (`accountId is required`) AND a
well-formed body still returns it, that is a real signal — proceed to Q6.
- Applies equally to WAF and CDN layers: an edge block is not an origin response.
---
**只有第二个响应能告诉你 auth 层位于何处。**
**来自一次授权测试的教训。** 在一个生产 API 上,格式错误的 body 在测试的大多数端点中返回了类似验证错误的 `400`。如果将其解读为 auth bypass,这会针对覆盖财务和管理操作的生产基础设施提交一份 Critical。实际情况是,sanitiser 在 auth 运行前对 `{` 字符作出反应——这些端点中的每一个在使用格式正确的 `{}` 时都返回 `401`。正因为有人重新测试,才避免了一次错误的 Critical 报告。
**规则:**
- 无法仅从一个响应观察出层级顺序。永远不要推断它。
- 使用 parser 能够接受的*最简单有效 body* 探测 auth,而不是使用格式错误的 body。
- 如果错误文本涉及 **input shape 或 character class**,说明你面对的是 parser 或 sanitiser,而不是业务逻辑。
- 如果错误文本明确指出 **domain field**(`accountId is required`),且格式正确的 body 仍返回该错误,这是一个真实信号——继续执行 Q6。
- 同样的规则也适用于 WAF 和 CDN 层:边缘拦截不是源站响应。
---4 PRE-SUBMISSION GATES
4 项提交前门控
Run in sequence. ALL 4 must PASS.
依次执行。4 项必须全部通过。
Gate 0: Reality Check (30 seconds)
Gate 0:真实性检查(30 秒)
[ ] Bug is REAL — confirmed with actual HTTP requests, not code reading alone
[ ] Bug is IN SCOPE — checked program scope page explicitly
[ ] Reproducible from scratch — can reproduce starting from fresh session
[ ] Evidence ready — screenshot, response body, or video[ ] 漏洞真实存在——已通过实际 HTTP 请求确认,而非仅阅读代码
[ ] 漏洞在范围内——已明确检查项目范围页面
[ ] 可从头复现——能够从全新 session 开始复现
[ ] 证据已准备好——截图、响应正文或视频Gate 1: Impact Validation (2 minutes)
Gate 1:影响验证(2 分钟)
[ ] Can answer: "What can attacker DO that they couldn't before?"
[ ] Answer is more than "see non-sensitive data" (unless program pays for info disclosure)
[ ] Real victim: another user's data, company's data, financial loss
[ ] Not relying on victim doing something unlikely[ ] 能回答:“攻击者现在能做到哪些以前做不到的事情?”
[ ] 答案不只是“看到非敏感数据”(除非项目为信息泄露付费)
[ ] 存在真实受害者:其他用户的数据、公司数据或财务损失
[ ] 不依赖受害者做出不太可能采取的行为Gate 2: Deduplication Check (5 minutes)
Gate 2:去重检查(5 分钟)
[ ] Searched HackerOne Hacktivity for this program + similar bug title/endpoint
[ ] Searched GitHub issues for target repo
[ ] Read most recent 5 disclosed reports for this program
[ ] Not a "known issue" in their changelog or public docs
[ ] Google: "TARGET_NAME ENDPOINT_NAME bug bounty"[ ] 已在 HackerOne Hacktivity 中搜索该项目的类似漏洞标题/端点
[ ] 已在目标仓库的 GitHub issues 中搜索
[ ] 已阅读该项目最近公开的 5 份报告
[ ] 它不是其 changelog 或公开文档中的“已知问题”
[ ] Google:“TARGET_NAME ENDPOINT_NAME bug bounty”Gate 3: Report Quality (10 minutes)
Gate 3:报告质量(10 分钟)
[ ] Title: [Bug Class] in [Endpoint] allows [actor] to [impact]
[ ] Steps to Reproduce: copy-pasteable HTTP request
[ ] Evidence: screenshot/video of actual impact (not just 200 status)
[ ] Severity: matches CVSS 3.1 score AND program's severity definitions
[ ] Remediation: 1-2 sentences of concrete fix
[ ] NEVER used "could potentially" or "may allow"[ ] 标题:[漏洞类别](位于 [端点])允许 [角色] 造成 [影响]
[ ] 复现步骤:可直接复制粘贴的 HTTP 请求
[ ] 证据:实际影响的截图/视频(而不只是 200 状态)
[ ] 严重性:同时符合 CVSS 3.1 分数和项目的严重性定义
[ ] 修复方案:用 1-2 句话给出具体修复措施
[ ] 绝不使用“可能会”或“可能允许”NEVER SUBMIT LIST
NEVER SUBMIT 清单
Submitting these destroys your validity ratio.
Missing CSP / HSTS / security headers
Missing SPF / DKIM / DMARC
GraphQL introspection alone (no auth bypass, no IDOR demonstrated)
Banner / version disclosure without working CVE exploit
Clickjacking on non-sensitive pages (no sensitive action PoC)
Tabnabbing
CSV injection (no actual code execution shown)
CORS wildcard (*) without credential exfil proof of concept
Logout CSRF
Self-XSS (only exploits own account)
Open redirect alone (no ATO or OAuth theft chain)
OAuth client_secret in mobile app (known, expected)
SSRF DNS callback only (no internal service access or data)
Host header injection alone (no password reset poisoning PoC)
Rate limit on non-critical forms (search, contact, login with Cloudflare)
Session not invalidated on logout
Concurrent sessions
Internal IP in error message
Mixed content
SSL weak ciphers
Missing HttpOnly / Secure cookie flags alone
Broken external links
Autocomplete on password fields
Pre-account takeover (usually — very specific conditions required)提交以下内容会毁掉你的有效率。
缺少 CSP / HSTS / security headers
缺少 SPF / DKIM / DMARC
仅存在 GraphQL introspection(未证明 auth bypass 或 IDOR)
没有可用 CVE exploit 的 Banner / version 泄露
非敏感页面上的 clickjacking(没有敏感操作 PoC)
Tabnabbing
CSV injection(未展示实际代码执行)
CORS wildcard (*)(没有凭据外泄 PoC)
Logout CSRF
Self-XSS(只能利用自己的账户)
单独的 Open redirect(没有 ATO 或 OAuth 窃取链)
移动应用中的 OAuth client_secret(已知且符合预期)
仅 DNS callback 的 SSRF(没有内网服务访问或数据返回)
单独的 Host header injection(没有 password reset poisoning PoC)
非关键表单上的 rate limit(搜索、联系、使用 Cloudflare 的登录)
退出登录时 session 未失效
并发 session
错误消息中包含内部 IP
Mixed content
SSL 弱加密套件
仅缺少 HttpOnly / Secure cookie flags
失效的外部链接
密码字段的 autocomplete
Pre-account takeover(通常无效——需要非常特定的条件)CONDITIONALLY VALID — CHAIN REQUIRED
有条件有效——必须提供利用链
Build the chain first, prove it works end to end, THEN report.
| Standalone Finding | Chain Required | Valid Result |
|---|---|---|
| Open redirect | + OAuth redirect_uri → auth code theft | ATO (Critical) |
| Clickjacking | + sensitive action + working PoC | Medium |
| CORS wildcard | + credentialed request exfils user PII | High |
| CSRF | + sensitive action (transfer funds, change email, delete account) | High |
| Rate limit bypass | + OTP/reset token brute force succeeds | Medium/High |
| SSRF DNS-only | + internal service access + data returned | Medium |
| Host header injection | + password reset email uses injected host | High |
| Prompt injection | + reads other user's data (IDOR) | High |
| S3 bucket listing | + JS bundles contain API keys or OAuth secrets | Medium/High |
| Self-XSS | + CSRF to trigger it on victim without their knowledge | Medium |
| Subdomain takeover | + OAuth redirect_uri registered at that subdomain | Critical |
| GraphQL introspection | + auth bypass mutation or IDOR on node() | High |
先构建利用链,端到端证明其有效,然后再提交报告。
| 独立发现 | 所需利用链 | 有效结果 |
|---|---|---|
| Open redirect | + OAuth redirect_uri → auth code 窃取 | ATO(严重) |
| Clickjacking | + 敏感操作 + 可用 PoC | 中危 |
| CORS wildcard | + 携带凭据的请求外泄用户 PII | 高危 |
| CSRF | + 敏感操作(转账、修改邮箱、删除账户) | 高危 |
| Rate limit bypass | + OTP/reset token 暴力破解成功 | 中危/高危 |
| 仅 DNS 的 SSRF | + 访问内网服务 + 返回数据 | 中危 |
| Host header injection | + password reset 邮件使用被注入的 host | 高危 |
| Prompt injection | + 读取其他用户的数据(IDOR) | 高危 |
| S3 bucket listing | + JS bundles 中包含 API keys 或 OAuth secrets | 中危/高危 |
| Self-XSS | + CSRF 在受害者不知情时触发 | 中危 |
| Subdomain takeover | + OAuth redirect_uri 注册在该子域名上 | 严重 |
| GraphQL introspection | + auth bypass mutation 或 node() 上的 IDOR | 高危 |
CVSS 3.1 QUICK REFERENCE
CVSS 3.1 快速参考
Common Score Examples
常见分数示例
| Finding | Score | Severity | Vector |
|---|---|---|---|
| IDOR read PII, any user, auth required | 6.5 | Medium | AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N |
| IDOR write/delete, any user | 7.5 | High | AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N |
| Auth bypass → admin panel | 9.8 | Critical | AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H |
| Stored XSS → cookie theft, stored | 8.5 | High | AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:L/A:N |
| SQLi → full DB dump | 9.1 | Critical | AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N |
| SSRF → cloud metadata | 9.1 | Critical | AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:N |
| Race → double spend | 7.5 | High | AV:N/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:N |
| GraphQL auth bypass | 8.1 | High | AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N |
| JWT none algorithm | 9.1 | Critical | AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H |
UI for stored XSS is a judgment call. Stored XSS that fires on page view is a long-standing CVSS gray area — NVD/FIRST frequently score it UI:R (which drops the stored-XSS row above to ~7.6). The UI:N above models "no extra action beyond normal page use"; if your triager expects UI:R, defend the choice or re-score before copying the number into a report.
| 发现 | 分数 | 严重性 | Vector |
|---|---|---|---|
| IDOR 读取 PII,任意用户,需要身份验证 | 6.5 | 中危 | AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N |
| IDOR 写入/删除,任意用户 | 7.5 | 高危 | AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N |
| Auth bypass → 管理员面板 | 9.8 | 严重 | AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H |
| 存储型 XSS → cookie 窃取 | 8.5 | 高危 | AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:L/A:N |
| SQLi → 完整数据库导出 | 9.1 | 严重 | AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N |
| SSRF → 云 metadata | 9.1 | 严重 | AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:N |
| Race → 重复消费 | 7.5 | 高危 | AV:N/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:N |
| GraphQL auth bypass | 8.1 | 高危 | AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N |
| JWT none algorithm | 9.1 | 严重 | AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H |
存储型 XSS 的 UI 是一项判断。 页面打开时触发的存储型 XSS 是 CVSS 长期存在的灰区——NVD/FIRST 经常评分为 UI:R(这会将上表的存储型 XSS 行降至约 7.6)。上表中的 UI:N 建模的是“除正常页面使用外无需额外操作”;如果你的漏洞审核人员预期 UI:R,请为该选择进行论证,或在把数字复制进报告前重新评分。
Metric Quick Guide
指标快速指南
| What you have | Metric | Value |
|---|---|---|
| Exploitable over internet | AV | Network (N) |
| No special timing or race | AC | Low (L) |
| Free account needed | PR | Low (L) |
| No login needed | PR | None (N) |
| Admin needed | PR | High (H) |
| No victim action | UI | None (N) |
| Victim must click | UI | Required (R) |
| Reads all data | C | High (H) |
| Reads some data | C | Low (L) |
| Modifies all data | I | High (H) |
| Crashes service | A | High (H) |
| Affects only app | S | Unchanged (U) |
| Affects browser/OS/cloud | S | Changed (C) |
| 你拥有的条件 | 指标 | 值 |
|---|---|---|
| 可通过互联网利用 | AV | Network (N) |
| 不需要特殊时序或竞态 | AC | Low (L) |
| 只需免费账户 | PR | Low (L) |
| 无需登录 | PR | None (N) |
| 需要管理员 | PR | High (H) |
| 无需受害者操作 | UI | None (N) |
| 受害者必须点击 | UI | Required (R) |
| 读取所有数据 | C | High (H) |
| 读取部分数据 | C | Low (L) |
| 修改所有数据 | I | High (H) |
| 使服务崩溃 | A | High (H) |
| 仅影响应用 | S | Unchanged (U) |
| 影响浏览器/OS/云 | S | Changed (C) |
KILL FAST RULES
快速淘汰规则
The goal is to QUICKLY disqualify bad leads so you hunt real bugs:
- 5-minute rule: If you can't fill in Q1's template in 5 minutes → move on
- Precondition count: More than 2 preconditions simultaneously required → kill it
- Impact test: "What does attacker walk away with?" — if nothing tangible → kill it
- Admin bypass: "Admin can do X" is NEVER a bug → kill it immediately
- Design doc test: If it's documented behavior → kill it immediately
- Rabbit hole signal: 30+ min on Q6 with no reproducible PoC → kill it
目标是迅速排除不良线索,从而集中寻找真实漏洞:
- 5 分钟规则:如果无法在 5 分钟内填写完 Q1 的模板 → 继续下一个
- 前置条件计数:同时需要超过 2 个前置条件 → 淘汰它
- 影响测试:“攻击者最终能带走什么?”——如果没有实质成果 → 淘汰它
- Admin bypass:“Admin can do X”永远不是漏洞 → 立即淘汰它
- Design doc 测试:如果这是已记录的行为 → 立即淘汰它
- Rabbit hole 信号:在 Q6 上花费 30 分钟以上仍没有可复现 PoC → 淘汰它
PRE-SEVERITY GATE
严重性判定前置门控
Before labelling any finding Critical or High anywhere in your notes or report — write out the answer to each of these as a one-liner. If you can't answer concretely, the severity is wrong.
- Have I validated the FULL chain to attacker-attainable impact, or only one primitive in the middle? — "Primitive confirmed at layer N" ≠ exploitable. Multi-stage chains require ALL stages validated before the severity matches the chain's top end.
- What does the attacker walk away with, in one concrete sentence? — "RCE on the SP front-end web server" is concrete. "Could lead to RCE" is not — that's High at best, often Medium.
- Have I personally reproduced the full chain end-to-end at least twice? — Twice = once during discovery, once for the report screenshot/PoC. Not "I'm sure it would work."
- Is there an inheritance gate, signature check, audience check, or other validation step still gating the chain? — If yes, the chain is not Critical. Document it as "primitive present" at lower severity until the gate is bypassed.
- Has the program rejected this severity class before? — Many programs cap "info disclosure with no concrete impact" at Low/Info regardless of the data type. Read the program scope.
Lesson from an authorized engagement: JWT was initially labelled Critical based on the signature-bypass primitive being confirmed at the audience-validation layer. Subsequent testing showed the issuer-trust check still rejected unsigned tokens — the full ATO chain did not complete. Finding had to be retracted. If the Pre-Severity Gate had been run on the original draft, Q1 would have killed the Critical label before submission.
alg:none在备注或报告中的任何位置,将任何发现标记为 Critical 或 High 之前——先用一行分别写出以下每个问题的答案。如果无法给出具体答案,严重性评级就是错误的。
- 我是否验证了从原始能力到攻击者可获得影响的完整利用链,还是只验证了链路中间的某个原语? — “在第 N 层确认了原语” ≠ 可利用。多阶段链必须验证所有阶段,严重性才可与链路上限一致。
- 攻击者最终能带走什么?请用一句具体的话回答。 — “SP 前端 Web 服务器上的 RCE”很具体。“可能导致 RCE”不是——这最多是 High,通常是 Medium。
- 我是否亲自至少两次端到端复现了完整链? — 两次 = 发现阶段一次,报告截图/PoC 阶段一次。不能只是“我确定它会奏效。”
- 链路上是否仍有继承校验门控、签名检查、受众检查或其他验证步骤? — 如果有,该链就不是 Critical。将其记录为较低严重性的“存在原语”,直到绕过该门控。
- 该项目此前是否拒绝过这一严重性级别? — 许多项目会将“没有具体影响的信息泄露”限制为 Low/Info,无论数据类型为何。请阅读项目范围说明。
来自一次授权测试的教训: JWT 最初被标记为 Critical,依据是在 audience-validation 层确认了 signature-bypass 原语。后续测试表明,issuer-trust check 仍会拒绝未签名 token——完整的 ATO 链并未完成。该发现最终不得不撤回。如果最初草稿执行了 Pre-Severity Gate,Q1 就会在提交前淘汰 Critical 评级。
alg:noneANTI-PATTERNS THAT LOSE MONEY
降低收益的反模式
Writing a report before confirming the bug exists (most common)
Submitting theoretical impact without proof
"The API returns more fields than necessary" (sensitivity matters — is it actually sensitive?)
Chaining A+B into one report when they're separate bugs (two separate payouts)
Reporting B saying "similar to A in my other report" — fresh Gate 0 for every bug
Overclaiming severity — triagers trust you less next time
Under-describing impact — triager doesn't understand why it matters在确认漏洞存在前编写报告(最常见)
提交理论上的影响而没有证据
“API 返回的字段比必要值更多”(敏感性很重要——它真的敏感吗?)
将 A+B 链成一份报告,但它们实际上是两个独立漏洞(对应两笔独立收益)
报告 B 时称“与我另一份报告中的 A 类似”——每个漏洞都要重新执行 Gate 0
夸大严重性——审核人员下次对你的可信度会降低
影响描述不足——审核人员无法理解它为什么重要RETRACTION DISCIPLINE
撤回纪律
When a previously-claimed finding fails reproduction — never silently drop it. Document the retraction in the report's appendix. This proves to the triager that you validate your own work, and it saves them from chasing a phantom you've already disproved.
Retraction entry template:
markdown
undefined当此前声称的漏洞无法复现时——永远不要静默删除它。 在报告附录中记录撤回。这能向审核人员证明你会验证自己的工作,也能避免他们追查一个已被你证伪的幻影漏洞。
撤回条目模板:
markdown
undefinedRetracted: <finding name>
已撤回:<finding name>
- Original signal: <one-line description of what looked like a bug>
- Disproving evidence: <concrete reproduction-step + observation that disproves it>
- Why it looked like a bug: <root cause of the false positive — e.g., natural marker collision, network jitter, status-code-only confidence>
- Retraction date: <YYYY-MM-DD>
**Concrete retractions from an authorized engagement — pattern reference:**
- **X-Forwarded-Proto reflection** — looked like header reflection across 4 pages; was the literal word `javascript` in SP help-link hrefs. Cause: non-unique marker.
- **Host header `:80@evil` bypass** — 200 OK on a path that normally 403s; body byte-identical to baseline (8341 bytes). Cause: status-code-only confidence; ELB Host normalisation dropped the `@evil` portion.
- **`download.aspx` file-existence oracle** — looked like a file-existence differentiator across path types; was SP's file-extension blocklist (`.ashx`/`.asmx`/`.svc`/`.config` always blocked regardless of existence). Cause: confusing server-side policy with file state.
- **`Administrator` timing leak** — single-shot 1527 ms vs ~700 ms control on Authentication.asmx Login; n=80 interleaved reproduction collapsed every group to 685-716 ms. Cause: single-sample statistical claim.
**Why this matters:** retracted findings put in an appendix demonstrate methodological honesty. Silently dropping them looks like you cherry-picked. A clean 11-finding report with a retraction appendix is more trustworthy than a 13-finding report where 2 fall apart at triage.
---- 原始信号: <用一行描述看起来像漏洞的现象>
- 反证证据: <具体的复现步骤 + 能够证伪它的观察结果>
- 它为何看起来像漏洞: <误报的根因——例如自然标记碰撞、网络抖动、仅依赖状态码的置信度>
- 撤回日期: <YYYY-MM-DD>
**来自授权测试的具体撤回案例——模式参考:**
- **X-Forwarded-Proto reflection**——看起来像是 4 个页面都存在 header reflection;实际上 SP help-link hrefs 中包含字面字符串 `javascript`。原因是标记不唯一。
- **Host header `:80@evil` bypass**——一个通常返回 403 的路径返回了 200 OK;正文与基线逐字节相同(8341 字节)。原因是仅依赖状态码判断置信度;ELB Host normalization 丢弃了 `@evil` 部分。
- **`download.aspx` file-existence oracle**——看起来像是不同路径类型之间存在文件存在性差异;实际上这是 SP 的文件扩展名 blocklist(无论文件是否存在,`.ashx`/`.asmx`/`.svc`/`.config` 始终被阻止)。原因是混淆了服务端策略与文件状态。
- **`Administrator` timing leak**——Authentication.asmx Login 的单次测量为 1527 ms,对照约 700 ms;采用 n=80 的交错复现后,所有组都收敛到 685-716 ms。原因是单样本统计声明。
**为什么这很重要:** 在附录中保留撤回记录能够体现方法论上的诚实。静默删除会让人觉得你是在挑选结果。一份包含 11 个有效发现并附有撤回附录的报告,比一份包含 13 个发现、其中 2 个在审核阶段崩塌的报告更值得信任。
---Related Skills & Chains
相关 Skills 与 Chains
- — When all 7 questions pass and the Pre-Severity Gate is clean. Workflow primitive: this skill is the gate that runs BEFORE
report-writing; only findings that clear all 7Q + 4 pre-submission gates get the report-template handoff.report-writing - — When a Bugcrowd VRT mapping is needed for an accepted finding. Workflow primitive: after this skill validates the finding,
bugcrowd-reportingdecides the VRT category and severity-request paragraph.bugcrowd-reporting - — When the validated finding needs PoC evidence captured. Workflow primitive: this skill says "Q6 requires proof of impact";
evidence-hygieneprovides the capture-and-redact protocol for that proof.evidence-hygiene - — When checking the always-rejected / conditionally-valid tables. Workflow primitive: this skill's "Never Submit List" and
security-arsenal's "Always Rejected" table are aligned; either entry-point lookup decides whether a primitive is reportable alone or only with a chain.security-arsenal - — When Phase 5 (Validate & Report) starts. Workflow primitive: Phase 5's pre-report gate explicitly invokes
bb-methodology(this skill's 7Q gate) before any report is drafted./validate
- ——当全部 7 个问题均通过且 Pre-Severity Gate 检查完成后使用。工作流原语:本 skill 是
report-writing之前运行的 gate;只有通过全部 7Q 和 4 项提交前 gate 的发现,才能移交给报告模板。report-writing - ——需要为已接受的发现建立 Bugcrowd VRT 映射时使用。工作流原语:本 skill 验证发现后,由
bugcrowd-reporting决定 VRT 类别和严重性申请段落。bugcrowd-reporting - ——已验证的发现需要捕获 PoC 证据时使用。工作流原语:本 skill 规定“Q6 requires proof of impact”;
evidence-hygiene提供该证据的捕获与脱敏协议。evidence-hygiene - ——检查 always-rejected/conditionally-valid 表格时使用。工作流原语:本 skill 的“Never Submit List”与
security-arsenal的“Always Rejected”表格保持一致;使用任一入口均可判断某个原语能否单独报告,还是只能通过链报告。security-arsenal - ——Phase 5(Validate & Report)开始时使用。工作流原语:Phase 5 的 pre-report gate 会在起草任何报告前明确调用
bb-methodology(本 skill 的 7Q gate)。/validate
Operator Notes (Claude-BugHunter)
Operator Notes(Claude-BugHunter)
Engagement-derived additions to the vendored foundation. Wisdom from real authorized engagements + Phase 2 verification across this repo's 31+ skill-area live tests. The upstream methodology covers the WHAT; this layer covers the WHEN-IT-ACTUALLY-WORKS and the FAILURE-MODES.
来自实际授权测试以及本仓库 31+ 个 skill 区域实时测试的实战补充。上游方法论讲“做什么”;本层讲“何时真正奏效”以及“失败模式”。
7-Question Gate at scale
规模化应用 7-Question Gate
The 7Q gate is the single highest-ROI artifact in this skill. Phase 2D's hardened-lab campaign verified it kills four distinct false-positive shapes:
- URL echo dressed as reflection — payload appears in the response body because the response IS the URL. Q1 (is this a real HTTP request that does something on the server) kills it.
- Word collision dressed as marker hit — the canary string matched a CSS class name, not your injection. Marker Discipline + Q1 kill it.
XSS-test - Server policy mistaken for state oracle — always returns "blocked" regardless of whether the file exists. Q6 (impact beyond technically possible) kills it: there's no oracle, just a deny-list.
download.aspx?file=foo.config - 200 OK without leak — status code differs from baseline 403; body is byte-identical. Body-Diff Rule + Q6 kill it.
Without the 7Q gate, expect 10-20% submission validity loss across an engagement. With it, retraction rates trend to single digits.
7Q gate 是本 skill 中投入产出比最高的产物。Phase 2D 的强化实验室活动验证了它能够淘汰四种不同形态的误报:
- 伪装成 reflection 的 URL echo——payload 出现在响应正文中,是因为响应本身就是 URL。Q1(这是否是会在服务器上执行操作的真实 HTTP 请求)会淘汰它。
- 伪装成 marker 命中的单词碰撞——canary 字符串 匹配到的是 CSS class name,而不是你的注入。Marker Discipline + Q1 会淘汰它。
XSS-test - 被误认为 state oracle 的服务端策略——无论文件是否存在始终返回“blocked”。Q6(实际影响,而非仅技术上可行)会淘汰它:这里没有 oracle,只有 deny-list。
download.aspx?file=foo.config - 只有 200 OK 而没有数据泄露——状态码与 403 基线不同,但正文逐字节相同。Body-Diff Rule + Q6 会淘汰它。
如果没有 7Q gate,预计整个测试活动的提交有效率会损失 10-20%。使用后,撤回率通常会降至个位数。
Pre-Severity Gate before reporting Critical
报告 Critical 前执行严重性判定门控
A authorized SharePoint engagement nearly submitted a Critical when the chain didn't actually complete end-to-end — a primitive that read auth state was conflated with a primitive that mutated it. The Pre-Severity Gate (run all 7 questions specifically against the Critical claim, not the generic "is this a bug" claim) would have caught it.
Process: write your draft Critical title. Take each of the 7 questions and answer them with the Critical claim substituted for "the bug." If Q6 (impact beyond technically possible) returns "I have a primitive that should let me do X, but I haven't demonstrated X end-to-end on a test account," downgrade. Critical means impact-demonstrated, not impact-inferable.
一次授权的 SharePoint 测试差点提交 Critical,因为完整链实际上并未端到端完成——一个读取 auth 状态的原语被错误地等同于一个修改 auth 状态的原语。Pre-Severity Gate 应针对 Critical 声明运行全部 7 个问题,而不只是笼统判断“这是否是一个漏洞”,这样才能发现该问题。
流程:先写出 Critical 标题草稿。然后逐个回答 7 个问题,并将 Critical 声明代入“这是否是一个漏洞”。如果 Q6(实际影响,而非仅技术上可行)的答案是“我确认了一个原语,它应该能让测试账户执行 X,但我还没有端到端展示 X”,则降低严重性。Critical 意味着已经展示影响,而不是仅能推断影响。
Retraction discipline
撤回纪律
If a finding stops reproducing 24h after submission — retract preemptively. Two reasons:
- Triagers retract for you with downgraded scoring. A self-retraction reads "the researcher validates their own work." A triager-retraction reads "the researcher submitted noise."
- Validation rate is platform-tracked. Self-retractions don't hit the same metric as triager-closed-as-N/A. Your reputation signal stays cleaner.
The retraction template in the RETRACTION DISCIPLINE section above is the canonical format. Don't silently delete — append a retraction appendix to the engagement report instead.
如果某个发现在提交 24 小时后不再复现——应主动撤回。原因有两个:
- 如果由你撤回,审核人员可能会给出一个被降低的评分。 自行撤回传递出的信号是“研究人员会验证自己的工作”;由审核人员撤回传递出的信号则是“研究人员提交了噪音”。
- 有效率是平台跟踪的指标。 自行撤回不会像被审核人员关闭为 N/A 那样影响同一指标。你的信誉信号会更加干净。
RETRACTION DISCIPLINE 一节中的撤回模板是标准格式。不要静默删除——应将撤回附录添加到测试活动报告中。
When the 7Q feels obstructive
当 7Q 显得妨碍流程时
The friction is the gate working. The half of findings that get killed by the 7Q are the half that would have come back as Informative or N/A. Take the friction. Your average payout per submission goes up when low-confidence findings stop diluting the funnel.
The exception: if the 7Q kills a finding but you still believe it, the answer is gather more evidence, not bypass the gate. The gate is a "do you have proof" check. Get proof, then re-run the gate.
这种阻力正是 gate 在发挥作用。被 7Q 淘汰的一半发现,本来也会被归为 Informative 或 N/A。接受这种阻力。低置信度发现不再稀释漏斗后,你每次提交的平均收益会提高。
例外情况是:如果 7Q 淘汰了某个发现,但你仍然相信它,答案是收集更多证据,而不是绕过 gate。gate 是一项“你是否拥有证据”的检查。获取证据后重新运行 gate。
Validation discipline rules cross-link
验证纪律规则交叉引用
The 7 questions are the umbrella; the discipline rules from are the implementation:
bb-methodology| 7Q Question | Discipline Rule (bb-methodology) |
|---|---|
| Q1 (real HTTP request that does something) | Reproducibility Gate |
| Q2 (impact beyond informational) | Pre-Severity Gate |
| Q3 (server-side state change or data leak) | Server-Policy-vs-State |
| Q4 (cross-tenant / cross-user demonstrated) | OOB Gate (for blind class), Marker Discipline (for reflective class) |
| Q5 (not already known / dup) | disclosed-reports/ index + HackerOne hacktivity check |
| Q6 (impact beyond technically possible) | OOB Gate + Body-Diff Rule + Statistical-Sample Rule |
| Q7 (in scope per program rules) | scope.md lookup (engagement scaffold) |
When a question is hard to answer "yes" to, the cross-linked rule tells you which artifact to produce to make the answer yes. Q6 is the one most engagements stumble on; that's why three discipline rules back it.
7 个问题是总框架, 中的纪律规则是具体实现:
bb-methodology| 7Q 问题 | 纪律规则(bb-methodology) |
|---|---|
| Q1(会执行操作的真实 HTTP 请求) | 可复现性门控(Reproducibility Gate) |
| Q2(超出信息级别的影响) | 严重性判定前置门控(Pre-Severity Gate) |
| Q3(服务端状态变更或数据泄露) | Server-Policy-vs-State |
| Q4(已证明跨租户/跨用户) | OOB Gate(适用于 blind 类)、Marker Discipline(适用于 reflective 类) |
| Q5(不属于已知问题或重复项) | disclosed-reports/ index + HackerOne hacktivity check |
| Q6(超出技术上可行的实际影响) | OOB Gate + Body-Diff Rule + Statistical-Sample Rule |
| Q7(符合项目规则的范围要求) | scope.md lookup(engagement scaffold) |
当某个问题很难回答“是”时,对应的交叉引用规则会告诉你需要生成哪个产物,才能将答案变为“是”。Q6 是大多数测试活动最容易卡住的问题,因此有三项纪律规则为它提供支撑。