关于 hunt-schema-enumeration
面向 API 安全测试人员的黑盒架构枚举技能,利用结构化错误信息和查询响应发现表名、字段名及接口路径。内容涵盖 PostgREST、验证错误与 GraphQL,并说明验证结果及其局限。
主要功能
- 01利用 PostgREST 提示发现表名
- 02从验证错误提取字段信息
- 03执行 GraphQL 内省查询
- 04通过词表模糊测试表名
- 05提供结果确认与误报辨别
适用场景
- 01绘制 PostgREST API 的数据表结构
- 02检查接口错误是否泄露字段要求
- 03在 GraphQL 内省受限时查找类型线索
- 04为后续授权写操作测试定位接口
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ uphiago/ recon-skills --skill hunt-schema-enumeration安装后在 Claude Code 中输入/hunt-schema-enumeration确认已加载。
详细介绍
适用场景
目标 API 会返回结构化错误消息(JSON),提示有效的表名、字段名或端点路径。这是针对 REST/GraphQL API 最有效的黑盒侦察方法——一次模糊测试请求就能揭示整个数据库架构。
最常见于:PostgREST(Supabase)、FastAPI(.NET)、Zod(Next.js/Node)、tRPC、GraphQL,以及任何在生产环境中启用了验证错误详情的框架。
阶段 1 — PostgREST 错误提示枚举
PostgREST 是 Supabase/PostgreSQL 的 REST API 层。查询不存在的表时,它会返回一条提示,其中包含真实表名。
SUPABASE_URL="https://PROJECT.supabase.co"
ANON_KEY="eyJ..."
# Fuzz with common table names — read the hints
for table in users profiles posts products orders data config settings; do
echo "=== $table ==="
curl --max-time 30 --connect-timeout 10 -sk "${SUPABASE_URL}/rest/v1/${table}?select=*&limit=1" \
-H "apikey: ${ANON_KEY}" \
-H "Authorization: Bearer ${ANON_KEY}" 2>/dev/null | python3 -c "
import sys,json
d=json.load(sys.stdin)
hint=d.get('hint','')
if hint: print(f' -> {hint}')
"
done
# The response pattern:
# {"hint":"Perhaps you meant the table 'public.real_table_name'"}
# {"hint":"Perhaps you meant the table 'public.user_sessions'"}
构建用于定向模糊测试的词表:
# Common patterns found in field:
# - Game apps: hands, scores, sessions, players, items, inventory
# - SaaS: subscriptions, subscribers, billing, invoices, teams, api_keys
# - Health: patients, appointments, assessments, prescriptions
# - Gov: citizens, certificates, documents, protocols
# - Finance: transactions, accounts, wallets, withdrawals, deposits
阶段 2 — 挖掘 Zod/FastAPI 验证错误
现代框架会返回详细的验证错误,暴露所有预期字段。
FastAPI(.NET/Go)
# POST with empty body or wrong fields
curl --max-time 30 --connect-timeout 10 -sk -X POST "https://api.target.com/endpoint" \
-H "Content-Type: application/json" -d '{}' 2>/dev/null
# Response reveals ALL required fields:
# {"errors":{"usuario":["required"],"senha":["required"]}}
Zod(Next.js/Node)
curl --max-time 30 --connect-timeout 10 -sk -X POST "https://target.com/api/workspaces" \
-H "Content-Type: application/json" -d '{}' 2>/dev/null
# Response: {"error":{"name":"ZodError","message":"[\n {\"expected\":\"string\",\"path\":[\"name\"]}\n]"}}
阶段 3 — GraphQL 内省
# Standard introspection query
curl --max-time 30 --connect-timeout 10 -sk -X POST "https://target.com/graphql" \
-H "Content-Type: application/json" \
-d '{"query":"{__schema{types{name fields{name type{name}}}}}"}' 2>/dev/null
# Even if introspection is disabled, error messages reveal type names:
# "Cannot query field 'x' on type 'User'. Did you mean 'users'?"
阶段 4 — 积极进行表名模糊测试
生成一个综合词表,其中包含:
# 1. From JS bundle analysis
grep -Eo 'from\(["\x60][a-zA-Z_]+["\x60]\)' /tmp/target.js | sort -u
# 2. From common patterns
# Singular/plural: user/users, post/posts, product/products
# Snake/camel: user_sessions, userSessions, UserSessions
# Domain-specific: appointments, patients, assessments, certificates
# 3. Systematic fuzz
for table in $(cat /tmp/wordlist.txt); do
curl --max-time 30 --connect-timeout 10 -sk -w "%{http_code}" "${BASE}/rest/v1/${table}?select=count" \
-H "apikey: ${KEY}" 2>/dev/null | tee -a /tmp/fuzz_results.txt
done
验证
- 确认命中 PostgREST:响应为
[](空数组 = 表存在,但 RLS 阻止读取)或返回了数据 - 确认命中 Zod:错误列出了预期的确切字段名和类型
- 确认命中 FastAPI:返回 422,且
detail数组列出了缺失字段 - 误报:通用的 404 HTML 页面(不是 JSON 错误)
下一步
- 如果 PostgREST 提示揭示了表 → 继续使用
hunt-write-gap(测试 PATCH/POST/DELETE) - 如果 Zod 错误揭示了字段 → 测试
hunt-business-logic(批量赋值、篡改价格) - 如果 FastAPI 揭示了身份验证架构 → 测试
jwt-attack或api-noauth-hunt - 架构枚举总会引向下一步攻击,不会是最终步骤
验证
运行此自测,确认已准备好进行架构枚举搜寻:
-
技能完整性 — 确认技能文件可读且格式正确:
grep -q "name: hunt-schema-enumeration" SKILL.md && echo "PASS: skill frontmatter present" || echo "FAIL" grep -q "revision_date:" SKILL.md && echo "PASS: revision date present" || echo "FAIL" -
类别检查 — 确认技能包含类别:
grep -q "category:" SKILL.md && echo "PASS: category present" || echo "FAIL" -
陷阱部分 — 确认已记录陷阱:
grep -q "^## Pitfalls" SKILL.md && echo "PASS: pitfalls section present" || echo "FAIL"
这 3 项测试可验证技能结构正确且已准备好使用。
陷阱
- 枚举架构但未发现敏感字段 — 了解 API 架构属于侦察。需要证明存在可利用的字段/变更操作。
- 通过内省获取 GraphQL 架构 — 内省是功能,不是漏洞(除非生产环境明确禁用了它)。
- 通过错误消息获取数据库架构 — SQL 错误泄露表名属于信息泄露,而不是特定于架构的问题。应根据泄露内容评估。
- OpenAPI 规范可公开访问 —
/swagger.json或/openapi.json是为 API 使用者提供的公开资源。应根据暴露的管理/内部端点评估。
评论
支持 Markdown