关于 triage-validation
面向安全研究人员的漏洞赏金验证技能,在提交前检查发现的问题。它通过有序的证据、范围、影响和查重关卡筛除误报并提升报告质量。
主要功能
- 01七问发现项验证关卡
- 02四项提交前检查
- 03认证层顺序复测指南
- 04无效及需组合利用的漏洞清单
- 05CVSS 3.1 严重性参考
- 06快速排除规则
适用场景
- 01提交前验证疑似漏洞
- 02复测疑似认证绕过
- 03检查范围、影响和重复报告
- 04准备可复现证据并评定严重性
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ elementalsouls/ claude-bughunter --skill triage-validation安装后在 Claude Code 中输入/triage-validation确认已加载。
详细介绍
分流与验证
一个错误答案 = 立即停止处理此发现。终止此发现。继续进行下一个测试类别。
本技能中“停止”的范围: 本技能的关卡会终止未通过验证的单个发现。它们并不授权你停止整个测试任务。通过 7 问关卡终止某个发现,只意味着不会提交该发现——任务中的其他测试类别仍待处理。有关覆盖范围轴规则,请参阅
redteam-mindset中的“DO NOT STOP primary directive”。
“N/A 会拉低你的有效性比率。提供信息的结果不影响比率。只提交通过全部 7 个问题的内容。”
7 问关卡
按顺序提问。一个错误答案 = 立即停止。
Q1:攻击者现在能否逐步利用此漏洞?
填写此模板:
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]
如果你无法将步骤 2 写成真实的 HTTP 请求 → 终止此发现。
Q2:此漏洞的影响是否属于该计划接受的影响范围?
前往计划页面。查找“Vulnerability Types”或“Out of Scope”。
常见级别:
- 严重:无需交互即可接管任意用户账号、RCE、可导出数据的 SQLi、管理员身份验证绕过
- 高:大规模导出 PII、权限提升、可获取数据的内网 SSRF、影响所有用户的存储型 XSS
- 中:针对特定用户非关键数据的 IDOR、需点击才能触发的敏感页面 XSS
- 低:非敏感信息泄露、附带 PoC 的点击劫持
如果你的漏洞对应某项列出的排除项 → 终止此发现。
Q3:根本原因是否位于范围内的资产中?
确认:
- 易受攻击的域名在范围内列表中(而非
*.internal.target.com) - 这是生产资产(不是 staging/dev,除非明确列入范围)
- 这不是公司使用的第三方服务(不是 Stripe、Salesforce、Google Auth)
如果超出范围 → 终止此发现。
Q4:是否需要攻击者无法现实获取的特权访问权限?
- “管理员可以执行 X” = 集中化风险 = 终止此发现(适用于 99% 的计划)
- “非管理员可以执行只有管理员才能执行的 X” = 有效
- “需要物理访问权限 / MFA 设备” = 通常无效
- “必须先攻陷受害者账号才能奏效” = 存疑,至多为低严重性
Q5:这是否是已知行为或已被接受的行为?
搜索:
- 计划公开的 HackerOne/Bugcrowd 报告:按 Ctrl+F 搜索端点名称 + 漏洞类别
- 目标仓库的 GitHub 问题:
is:issue label:security ENDPOINT_NAME - 更新日志/CHANGELOG.md — 是否提到了此行为?
- API 文档 / 设计文档 — 是否将其记录为预期行为?
如果已确认 / 属于设计决策 → 终止此发现。
Q6:你能否证明实际影响,而不只是“技术上可行”?
- XSS → 展示实际的 Cookie 窃取或会话劫持,而不只是
alert(1)或alert(document.domain) - SSRF → 访问一个会返回数据的内部端点,而不只是 DNS ping
- SQLi → 展示从真实表中实际导出的数据,而不只是错误消息
- IDOR → 展示响应中实际包含其他用户的数据,而不只是 200 状态码
如果你只能证明“技术上可行” → 降低严重性评级,不要终止此发现。
Q7:这是否属于已知无效的漏洞类别?
查看下方的“绝不提交”列表。如果漏洞在列表中且没有攻击链 → 终止此发现。
层级顺序陷阱——声称存在任何认证绕过前,请先阅读
验证错误并不能证明你已通过认证。
这是认证绕过类问题中置信度最高的误报,因为证据看起来很具体。以下推理是错误的:
“我发送了一个未经认证的请求,收到
400 — field X is required。 验证错误意味着请求通过了认证并到达业务逻辑。 因此认证缺失。”
只有在认证先于输入处理运行时,这个推断才成立。许多技术栈会在认证中间件之前放置**全局输入清理器、请求体解析器或架构过滤器。**此时,格式错误的请求体会在认证逻辑运行前被拒绝,其响应与“认证已通过,验证失败”无法区分。
测试:使用格式正确的最小请求体重新发送。
# malformed body — trips the sanitiser, which runs FIRST
curl -s -X POST https://target/api/v1/resource -d '{'
# 400 {"code":"ERR-INPUT-0001","message":"Invalid text. Only permitted
# characters are allowed"} <- looks like auth bypass
# 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 '{}'
# 401 {"code":"ERR-AUTH-0001","message":"Not authenticated. Please log in."}
只有第二个响应才能告诉你认证层位于何处。
**来自一次经授权测试的经验。**在一个生产 API 上,测试的大多数端点对格式错误的请求体都返回了类似验证错误的 400。如果将其解读为认证绕过,就会针对生产基础设施提交一个涵盖金融和管理操作的严重(Critical)问题。实际情况是,认证运行前,清理器就对 { 字符作出了反应——这些端点在收到格式正确的 {} 时,全部返回了 401。只有因为有人重新测试,才避免了这个误报的严重问题。
规则:
- 无法通过单个响应观察层级顺序。切勿推断。
- 使用解析器能够接受的最简单的有效请求体测试认证,不要使用格式错误的请求体。
- 如果错误文本涉及输入结构或字符类别,那么你接触到的是解析器或清理器,而非业务逻辑。
- 如果错误文本提到了领域字段(
accountId is required),并且格式正确的请求体仍会触发该错误,这才是真正的信号——继续执行 Q6。 - 同样适用于 WAF 和 CDN 层:边缘节点拦截不代表源站响应。
4 个提交前检查关卡
按顺序执行。4 个关卡必须全部通过。
关卡 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
关卡 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
关卡 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"
关卡 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"
绝不提交的清单
提交这些内容会拉低你的有效率。
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)
有条件成立——需要利用链
先构建利用链,证明其端到端有效,然后再报告。
| 单独发现的问题 | 所需利用链 | 有效结果 |
|---|---|---|
| 开放重定向 | + OAuth redirect_uri → 窃取授权码 | ATO(严重) |
| 点击劫持 | + 敏感操作 + 可用的 PoC | 中危 |
| CORS 通配符 | + 携带凭据的请求外泄用户 PII | 高危 |
| CSRF | + 敏感操作(转账、更改邮箱、删除账户) | 高危 |
| 绕过速率限制 | + 成功暴力破解 OTP/重置令牌 | 中危/高危 |
| 仅 DNS 的 SSRF | + 访问内部服务 + 返回数据 | 中危 |
| Host 标头注入 | + 密码重置邮件使用被注入的主机名 | 高危 |
| 提示词注入 | + 读取其他用户的数据(IDOR) | 高危 |
| S3 存储桶列表 | + JS 包含 API 密钥或 OAuth 密钥 | 中危/高危 |
| Self-XSS | + 通过 CSRF 在受害者不知情的情况下触发 | 中危 |
| 子域接管 | + OAuth redirect_uri 注册在该子域 | 严重 |
| GraphQL 内省 | + 认证绕过变更操作或 node() 上的 IDOR | 高危 |
CVSS 3.1 速查
常见分数示例
| 发现 | 分数 | 严重性 | 向量 |
|---|---|---|---|
| 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 |
| 绕过身份验证 → 管理面板 | 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 → 云元数据 | 9.1 | 严重 | AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:N |
| 竞态条件 → 重复消费 | 7.5 | 高 | AV:N/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:N |
| GraphQL 身份验证绕过 | 8.1 | 高 | AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N |
| JWT none 算法 | 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,请说明选择理由,或在将分数填入报告前重新评分。
指标速查指南
| 已知情况 | 指标 | 值 |
|---|---|---|
| 可通过互联网利用 | AV | 网络(N) |
| 无特殊时序要求或竞态条件 | AC | 低(L) |
| 需要免费账户 | PR | 低(L) |
| 无需登录 | PR | 无(N) |
| 需要管理员权限 | PR | 高(H) |
| 无需受害者操作 | UI | 无(N) |
| 受害者必须点击 | UI | 必需(R) |
| 读取所有数据 | C | 高(H) |
| 读取部分数据 | C | 低(L) |
| 修改所有数据 | I | 高(H) |
| 导致服务崩溃 | A | 高(H) |
| 仅影响应用 | S | 不变(U) |
| 影响浏览器/操作系统/云 | S | 已改变(C) |
快速排除规则
目标是快速排除无效线索,以便寻找真正的漏洞:
- 5 分钟规则:如果 5 分钟内无法填写 Q1 的模板 → 继续寻找
- 前置条件数量:同时需要超过 2 个前置条件 → 排除
- 影响测试:“攻击者能得到什么?”——如果没有任何实际收获 → 排除
- 管理员绕过:“管理员可以执行 X”绝不是漏洞 → 立即排除
- 设计文档测试:如果这是文档中描述的行为 → 立即排除
- 陷入死胡同的信号:在 Q6 上花费 30 分钟以上,仍没有可复现的 PoC → 排除
严重性评定门槛
在笔记或报告中的任何地方将发现标为严重或高危之前,先用一句话分别写出以下问题的答案。如果无法给出具体答案,说明严重性评级有误。
- 我是否验证了攻击者可实际达成影响的完整链路,还是只验证了其中一个基础环节? — “已确认第 N 层存在基础环节”≠可利用。多阶段链路必须在所有阶段都经过验证后,严重性才能达到链路的最高级别。
- 用一句具体的话说明,攻击者最终能获得什么? — “在 SP 前端 Web 服务器上实现 RCE”是具体的。“可能导致 RCE”则不具体——这种情况最高只能评为高危,通常应为中危。
- 我是否亲自至少两次端到端复现了完整链路? — 两次 = 发现期间一次,报告截图/PoC 一次。不能只是“我确信它能成功”。
- 链路是否仍受继承门槛、签名检查、受众检查或其他验证步骤限制? — 如果是,则该链路不属于严重级别。在门槛被绕过之前,应按较低严重性记录为“存在基础环节”。
- 该计划是否曾拒绝过此严重性类别? — 许多计划会将“无具体影响的信息披露”最高定为低危/信息级,无论数据类型如何。请阅读计划范围。
来自一次授权测试的教训: JWT alg:none 最初因在受众验证层确认了签名绕过这一基础环节,而被评为严重。后续测试发现,签发者信任检查仍会拒绝未签名令牌——完整的 ATO 链路并未成功。如果最初撰写报告时执行了严重性评定门槛,问题 1 就会在提交前否决严重级别。
导致损失的反模式
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
撤回规范
先前报告的发现若无法复现,**切勿悄悄删除。**请在报告附录中记录撤回情况。这能向分诊人员证明你会验证自己的工作,也能避免他们追查你已经证伪的问题。
撤回条目模板:
### Retracted: <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>
来自一次授权测试的具体撤回案例——模式参考:
- X-Forwarded-Proto 反射——看起来像是 4 个页面都存在请求头反射;实际内容是 SP 帮助链接 href 中的字面字符串
javascript。原因:标记不唯一。 - Host 请求头
:80@evil绕过——通常返回 403 的路径返回了 200 OK;但响应正文与基线逐字节相同(8341 字节)。原因:仅凭状态码就过度确信;ELB 的 Host 规范化处理移除了@evil部分。 download.aspx文件存在性预言机——看起来不同路径类型之间存在文件是否存在的差异;实际上是 SP 的文件扩展名黑名单(无论文件是否存在,.ashx/.asmx/.svc/.config均始终会被拦截)。原因:混淆了服务器端策略与文件状态。Administrator计时泄露——Authentication.asmx Login 上单次测得 1527 ms,而对照约为 700 ms;交错进行 n=80 次复现后,各组结果均收敛至 685-716 ms。原因:基于单次样本做出统计性结论。
**重要性:**在附录中列出撤回的发现,体现了方法上的诚实。悄悄删除会让人觉得你在挑选有利结果。一份附有撤回附录、共 11 项发现的报告,比一份有 2 项在分诊时被推翻、共 13 项发现的报告更值得信任。
相关技能与链路
report-writing— 当全部 7 个问题均通过且严重性预审关卡无异常时使用。工作流原语:此技能是运行在report-writing之前的关卡;只有通过全部 7Q 和 4 项提交前关卡的发现,才会移交给报告模板。bugcrowd-reporting— 当已接受的发现需要映射到 Bugcrowd VRT 时使用。工作流原语:此技能验证发现后,由bugcrowd-reporting确定 VRT 类别和严重性请求段落。evidence-hygiene— 当需要为已验证的发现采集 PoC 证据时使用。工作流原语:此技能指出“Q6 要求证明影响”;evidence-hygiene提供该证据的采集与脱敏流程。security-arsenal— 检查始终被拒绝/有条件有效的表格时使用。工作流原语:此技能的“绝不提交清单”和security-arsenal的“始终被拒绝”表格相互对应;无论从哪个入口查询,都能判断某个原语单独是否可报告,还是必须与链路结合。bb-methodology— Phase 5(验证与报告)开始时使用。工作流原语:Phase 5 的报告前关卡明确要求在起草任何报告之前调用/validate(即此技能的 7Q 关卡)。
操作人员须知(Claude-BugHunter)
基于实战补充到供应商版本基础内容中的经验。源自真实的授权测试,以及本仓库 31+ 个技能领域的实时测试所开展的 Phase 2 验证。上游方法论涵盖 WHAT;本层涵盖实际奏效的时机和失败模式。
大规模应用 7Q 关卡
7Q 关卡是此技能中投资回报率最高的单项成果。Phase 2D 的强化实验室测试验证了它可以排除四种不同的误报类型:
- 伪装成反射的 URL 回显 — 负载出现在响应正文中,是因为响应本身就是 URL。Q1(这是否是一个会在服务器上执行操作的真实 HTTP 请求)可以排除这种情况。
- 伪装成标记命中的词语碰撞 — 金丝雀字符串
XSS-test匹配到的是 CSS 类名,而不是你的注入内容。标记纪律 + Q1 可以排除这种情况。 - 将服务器策略误认为状态判定器 — 无论文件是否存在,
download.aspx?file=foo.config都始终返回“已阻止”。Q6(影响是否超出理论上的可能性)可以排除这种情况:这里没有判定器,只有拒绝名单。 - 返回 200 OK,但没有泄露 — 状态码不同于基线 403;正文逐字节完全相同。正文差异规则 + Q6 可以排除这种情况。
如果没有 7Q 关卡,一次测试期间预计会有 10-20% 的提交失效。采用该关卡后,撤回率会降至个位数。
报告 Critical 前的严重性预审关卡
一次获得授权的 SharePoint 测试差点提交了 Critical 报告,但攻击链并未真正端到端完成——一个读取认证状态的原语被误认为是一个修改认证状态的原语。如果对 Critical 声明(而不是笼统的“这是不是一个漏洞”声明)逐项运行全部 7 个问题,严重性预审关卡就能发现这个问题。
流程:先写下 Critical 草稿标题。逐一回答 7 个问题,并将“漏洞”替换为 Critical 声明。如果 Q6(影响是否超出理论上的可能性)的回答是“我有一个应该能让我执行 X 的原语,但尚未在测试账户上端到端演示 X”,就应降低严重性。Critical 意味着影响已经得到演示,而非仅能推断出影响。
撤回纪律
如果某项发现提交 24h 后无法再复现,应主动撤回。原因有二:
- 分诊人员会以降低评分的方式替你撤回。 自行撤回传达的是“研究人员会自行验证自己的工作”;分诊人员撤回传达的则是“研究人员提交了噪声”。
- 平台会跟踪验证率。 自行撤回不会计入与分诊人员以 N/A 关闭相同的指标,因此你的声誉信号会更干净。
上方“撤回纪律”章节中的撤回模板是标准格式。不要直接悄悄删除;应在测试报告中附加撤回附录。
当 7Q 让人觉得碍事时
阻力正说明这道关卡发挥了作用。被 7Q 淘汰的发现中,有一半最终会被判定为 Informative 或 N/A。接受这份阻力。停止让低置信度的发现稀释整个流程后,你的平均单次提交收益会提高。
例外情况:如果 7Q 淘汰了某项发现,但你仍然相信它成立,正确做法是收集更多证据,而不是绕过关卡。这道关卡检查的是“你有证据吗”。拿到证据后,再重新过关。
验证规范规则交叉引用
这 7 个问题是总纲;bb-methodology 中的规范规则则是具体实施方式:
| 7Q 问题 | 规范规则(bb-methodology) |
|---|---|
| Q1(执行了有实际作用的真实 HTTP 请求) | 可复现性关卡 |
| Q2(影响超出信息提示级别) | 严重性预判关卡 |
| Q3(服务器端状态发生变化或数据泄露) | 服务器策略与状态 |
| Q4(已证明跨租户/跨用户) | 带外关卡(适用于盲测类别),标记纪律(适用于反射类别) |
| Q5(尚未被披露/不是重复报告) | 检查 disclosed-reports/ 索引和 HackerOne hacktivity |
| Q6(影响并非仅在技术上可行) | 带外关卡 + 响应体差异规则 + 统计抽样规则 |
| Q7(符合计划规则中的范围) | 查阅 scope.md(项目脚手架) |
如果某个问题很难回答“是”,交叉引用的规则会告诉你要制作哪项证据材料,才能让答案变成“是”。Q6 是大多数项目最容易卡住的一项,因此有三条规范规则为它提供支撑。