GraphQL 漏洞 Part-2:深度嵌套 DoS、IDOR 越权与错误消息泄漏实战

导语:GraphQL 把数据查询权交给客户端,看似收敛了攻击面,实际上把权限校验、深度限制、错误处理这些活全压到了服务端。本文是 learn365 day21 翻译与拓展,从红队视角讲三种最容易在渗透测试中拿分的攻击路径。


一、错误消息信息泄漏

和所有接口一样,GraphQL 也会泄漏调试信息。给端点喂畸形或不合预期的输入,verbose error message 会把后端栈、对象结构、字段名、甚至内部文件路径一股脑回吐出来。

实战中最常见的三类触发:

  • 类型不匹配:把字符串塞进 Int 字段,看响应是不是抛 Expected type Int! 之类的栈跟踪
  • 未知字段:直接查 typename、schema,很多关掉内省的端点其实没关错误细节
  • 嵌套死循环:在看似无关联的两个对象上互相套娃,触发 N+1 错误时经常连 ORM 内部 SQL 一并显示

OWASP-SKF 在 KBID-285 里专门把这一类单独列出,因为多数团队只想着关内省,忘了错误返回也是信息泄漏入口。

三大攻击面示意图

二、GraphQL 拒绝服务

服务端没限制查询深度,攻击者就能写出无限嵌套的递归查询,把 CPU、内存、连接池全打爆。KBID-285 GraphQL DOS 实验就一句话:向 GraphQL 端点发送任意深度的嵌套查询,观察后端是否异常。

DVGA(Damn-Vulnerable-GraphQL-Application)整理了 5 种 DoS 路径:

攻击类型原理杀伤力
批处理查询单 HTTP 请求里塞几十上百个 query服务端并发 worker 耗尽
深度递归自关联字段无限嵌套CPU 占满,堆内存爆掉
资源密集查询多对象关联回同一张大表数据库被 N+1 拖垮
字段复制同字段重复几百遍JSON 序列化器跑满
别名爆炸一个 query 里起几百个别名调同一 resolver短时间把内部 API 配额耗光

最容易打出效果的是深度递归。一条典型 PoC(fragment 自关联 100 层):

fragment NestedUser on User {
  id
  name
  friends {
    ...NestedUser
  }
}
query Attack { me { ...NestedUser } }

没有深度限制的服务端秒级堆爆。修复就一条:在 query AST 上做深度限制 + 别名数量限制 + 复杂度评分 三件套,单点都拦不住,全部上才有冗余。

三、字段 IDOR 越权

和普通 API 的 IDOR 没本质区别。GraphQL 字段就相当于 RESTful 的端点,权限校验没跟上,一查一个准。

KBID-285 IDOR 的 writeup 给了一段教科书例子——DVGA 里查询用户设置页的 query:

{
  singleUser(user: 1) {
    apiKey
    name
    surname
    dateOfBirth
  }
}

把 user: 1 改成 user: 2、user: 3,加递增枚举或从其他渠道拿到的 UUID,无授权校验时直接返回他人资料。HTTP IDOR 检查表那套完全通用——query 只是从 URL 变成了花括号,字段改为嵌套。

更深一层:批处理 + IDOR 组合,单请求里写几十个别名批量越权,同时打垮授权层:

query MassIDOR {
  u1: singleUser(user: 1) { apiKey }
  u2: singleUser(user: 2) { apiKey }
  u3: singleUser(user: 3) { apiKey }
}

四、Burp 扩展值得装

跑 GraphQL 测试别裸奔,Burp Suite 上两个扩展能省一半时间:

  • InQL:自动生成 introspection 查询,对端点做 schema 树形展示,一眼看到所有 query/mutation/field
  • GraphQL Raider:内置常见 payload 库,跑批处理、深度递归、字段复制三连击

目标域名丢进 InQL scope,它就开始自动枚举,配合 Repeater 改字段值比手工拼 query 快三倍。

五、动手练手

DVGA 一站式搞定,五大类攻击明明白白摆在那:

git clone https://github.com/dolevf/Damn-Vulnerable-GraphQL-Application
cd Damn-Vulnerable-GraphQL-Application
docker-compose up -d   # 浏览器开 http://localhost:5000

Beginner / Expert 两档难度,Postman 还提供现成解题集合可以导入。

六、防御五要点

实战里真正能防住 80% 攻击的:

  1. 生产关 introspection(schema/type/__typename),错误页打码,不漏堆栈
  2. 强制 query 白名单(persisted queries),不让客户端写任意 query
  3. 加深度和复杂度限制:单 query 嵌套不超过 8-10 层、aliases 不超 100
  4. 字段级授权:每个 resolver 都要 ctx.user 校验,不能靠前端传 user id
  5. 批处理 rate limit:陌生人请求数卡到 5 个 query 一个 HTTP

做到这五条,Bug Bounty 上不会因为 GraphQL 基础姿势被拿。

七、思考题

  1. introspection 关掉的端点,还有哪些姿势能反推 schema?(提示:field suggestions / GraphiQL UI / 错误消息三重路子)
  2. 嵌套递归 DoS 之外,batch query + IDOR 组合有没有更隐蔽的玩法?
  3. 字段级授权在 GraphQL 实现层是不是每个 resolver 都要写一遍?有没有框架级一刀切的方案?

八、素材出处

© 版权声明
THE END
喜欢就支持一下吧
点赞15 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容