导语:GraphQL 三部曲前两篇把内省、DoS、IDOR、错误泄漏打透了,这篇是收官。讲那些藏在字段权限、订阅长连接、限流逻辑里的”进阶玩法”,再把 19 份 HackerOne 实战报告和 6 个深度资源按攻击类型重新归类,红队下次遇到 GraphQL 端点时直接照表打。
一、三部曲一句话回顾
第一讲拆的是”端点长什么样”:单端点架构、内省三件套(schema / type / __typename)、批处理别名绕过。第二讲拆的是”如何打挂和打穿”:深度递归 DoS、字段 IDOR、错误消息泄漏 ORM 内部 SQL。
第三讲不重复基础,直接进入权限边界模糊地带——这些点防守方经常写一半就放过,攻击者拿分却最稳。

二、四个最容易拿分的进阶手法
2.1 内省被关后的字段枚举
团队把生产环境内省关掉就以为安全了,其实关内省只是关了一扇门,攻击者照样能进。
- 错误消息字段名泄漏:发一个故意缺字段名的 query,服务端在
Cannot query field "xxx"里主动建议正确字段名(Did you mean user / users / me?) - GET 参数污染:很多端点同时支持 GET query string,POST 关了内省 GET 开着
- Apollo Federation 多 schema 合并:联邦模式下查询
_service { sdl }直接拿全部子图 SDL - 客户端 JS 源码:前端打包文件里往往能挖到完整 schema.graphql 一并传
Bishop Fox 专门写过一篇文章《Design Considerations for Secure GraphQL APIs》,把”内省关掉就安全”列为一等误区,文章里给出完整的 schema 探测清单。
2.2 订阅(Subscription)长连接滥用
Query 和 Mutation 在 HTTP 短连接里跑,Subscription(基于 WebSocket)是个完全独立的长连接通道。很多团队的安全策略只覆盖了 HTTP 端点,WebSocket 这条暗道没人管。
实战中最常被忽视的三类:
- 订阅里的权限校验缺失:用户 A 订阅了用户 B 的事件流,过滤逻辑只在前端加,服务端没复检
- 订阅事件注入:mutation 触发的字段没消毒,直接推给所有订阅者,等于把 XSS 投到所有在线客户端
- 心跳与断线检测:没设心跳的订阅会被反向用来占满 WebSocket 槽位,DoS 成本比 query 端低一个数量级
第一讲里讲过 WebSocket 八大致命风险,订阅把这八条全继承了一遍。418883 这份 H1 报告就是订阅端权限绕过拿到后台数据流的案例。
2.3 别名击穿限流器
419883、614355、633001 三份报告里有同一个共同点:限流器按 HTTP 请求数计,而不是按 GraphQL 操作数计。
攻击者把 200 个查询塞进一条 HTTP 请求(每个查询起一个别名),限流器算 1 个请求,resolver 跑了 200 次。结果:登录爆破、优惠码枚举、批量 IDOR 全部畅通无阻。
query {
a:login(user: "admin", pwd: "p1") { token }
b:login(user: "admin", pwd: "p2") { token }
c:login(user: "admin", pwd: "p3") { token }
# ...197 more
}
PortSwigger Academy 在 GraphQL 安全章节里专门写了别名绕过限流的检测手法,burp 插件inQL可以直接批量生成。
2.4 GraphQL CSRF
很多人以为”非简单请求要预检就安全”,实际上 GraphQL 端点接收 application/json 时确实会触发 CORS 预检,但服务端接受 application/x-www-form-urlencoded 时,预检就跳过了。攻击者写一段 form 自动提交,浏览器不带 cookie 也要带 cookie——只要用户的 session cookie 没设 SameSite=Lax/Strict,照样被打。
417170 这份报告里就有一段经典 PoC: 把整段 query 塞进 input value,CSRF 一次投递完成。
三、19 份 HackerOne 报告按攻击类型速查
| 攻击类型 | 代表报告 |
|---|---|
| 内省泄漏 | 885539 645299 707433 924914 978143 715192 |
| 字段/对象 IDOR | 489146 608656 800231 898528 924914 |
| 限流击穿(别名/批处理) | 419883 614355 633001 |
| 错误消息泄漏 | 423388 707433 924914 |
| 订阅/实时流越权 | 419883 633001 |
| CSRF / 跨域滥用 | 417170 608656 |
| 嵌套查询 DoS | 885539 978143 |
| 注入(SQLi/SSRF/SSTI) | 645299 489146 898528 |
这 15 个 ID 是原文 day22 给的清单,剩下 800231 898528 924914 978143 715192 五个按上下文归到多个类别,说明它们往往是组合拳。原始报告全部需要登录 HackerOne 才能看完整 PoC,但每个标题都标注了漏洞类型,照着去找就行。
四、6 份深度资源速读
- Security-Simplified《GraphQL Penetration Testing》:印度安全研究员写的实战 blog,覆盖从端点发现到利用的完整流程,适合入门第一篇
- YouTube
Wb0BO8J7024:用动画演示 batch + alias + introspection 怎么组合打,红队培训常用 - Pen Test Partners《Pwning WordPress GraphQL》:WPGraphQL 0.2.3 多 CVE 实战(CVE-2019-9879/9880/9881),演示一个未鉴权 mutation 如何创建管理员账号、再用主题编辑拿 shell
- ThreatNinja《GraphQL Injection Tutorial》:把 SQLi / NoSQLi / SSRF / SSTI 套到 GraphQL 字段上做演示的工具集
- Bishop Fox《Design Considerations for Secure GraphQL APIs》:从架构层面讲 SDL 切片、Resolver 隔离、Persisted Query,可作为企业部署参考
- PayloadsAllTheThings/GraphQL Injection:GitHub 仓库,渗透测试 cheat sheet 的标配,复制即用
五、红队收官 Checklist
照下面这张表走,10 分钟内出第一个 lead:
- [ ]
/graphql端点发现(OPTIONS、错误页路径扫、JS 提取) - [ ] 内省是否开着(
{__schema{types{name}}}一发命中) - [ ] 内省关了用错误消息字段建议挖 schema
- [ ] 批处理 + 别名跑限流击穿
- [ ] 深度递归 fragment 测 DoS 阈值
- [ ] mutation 字段遍历做 IDOR 测试
- [ ] subscription 走 WebSocket 单独测越权
- [ ] content-type 切
text/plain/application/x-www-form-urlencoded测 CSRF - [ ] 错误响应里看 ORM 内部 SQL(信息泄漏)
- [ ] 拿到第一个 lead 后跑
inQL/graphqlmap/clairvoyance做深度
工具栈:inQL(Burp 插件)+ graphqlmap(自动注入)+ clairvoyance(schema 恢复)+ graphql-playground(手动调试)。三个加起来 30 分钟出报告。
六、写在最后
GraphQL 不是”新东西”,但它把”后端的事”搬到客户端来做的设计让权限、深度、错误处理这些传统安全控制变得格外脆弱。learn365 day20-22 三篇合起来是一张完整的攻击地图:第一篇定位、第二篇打穿、第三篇收口。
下回开新坑,比如 OAuth 那一档的 day23 Password Reset Token。














暂无评论内容