mcpField
C
conducting-api-security-testing

conducting-api-security-testing

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

关于 conducting-api-security-testing

面向授权安全测试人员的 API 安全评估技能,提供从接口发现到漏洞分析和报告的分步流程,涵盖 REST 与 GraphQL API。

主要功能

  1. 01接口攻击面发现与认证梳理
  2. 02JWT、OAuth 和 API 密钥测试
  3. 03BOLA、BFLA 与批量赋值检查
  4. 04注入、速率限制与数据暴露测试
  5. 05按阶段整理评估发现

适用场景

  1. 01评估微服务 API 的授权控制
  2. 02检查 API 网关的认证与限流措施
  3. 03测试 GraphQL 模式和访问控制

安装

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

$npx skills add https://github.com/mukul975/anthropic-cybersecurity-skills --skill conducting-api-security-testing

安装后在 Claude Code 中输入/conducting-api-security-testing确认已加载。

包含的文件

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

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

详细介绍

开展 API 安全测试

适用场景

  • 测试 API 端点是否存在授权缺陷、注入漏洞和业务逻辑绕过
  • 评估以 API 为主要通信方式的微服务架构的安全性
  • 验证 API 网关防护措施(速率限制、身份验证、输入验证)是否正确实施
  • 测试第三方 API 集成是否存在数据泄露和不安全配置
  • 评估 GraphQL API 是否存在内省信息泄露、查询复杂度攻击和授权绕过问题

请勿在未获得书面授权的情况下对 API 使用,除非明确纳入范围,否则不得用于负载测试或拒绝服务测试,也不得在缺乏保护措施的情况下用于测试处理真实金融交易的生产 API。

前置条件

  • API 文档(OpenAPI/Swagger、GraphQL schema、Postman collection)或应用程序访问权限,以便对 API 进行逆向工程
  • 配置好 Burp Suite Professional,以拦截 API 流量并处理 JSON/XML 内容类型
  • Postman 或 Insomnia,用于在不同身份验证上下文中组织和重放 API 请求
  • 多个权限级别的有效 API 令牌或凭据(未认证、标准用户、管理员)
  • 目标 API 基础 URL 和版本信息

工作流

第 1 步:API 发现与文档梳理

绘制完整的 API 攻击面:

  • 导入 API 文档:将 OpenAPI/Swagger 规范加载到 Postman 或 Burp Suite 中,编目所有端点、方法、参数和身份验证要求
  • 对未公开的 API 进行逆向工程:通过 Burp Suite 代理移动应用或 Web 前端,操作所有功能以捕获 API 调用。将 Burp sitemap 导出为基线端点清单。
  • GraphQL 内省:发送内省查询以发现完整 schema:
    {"query": "{__schema{types{name,fields{name,args{name,type{name}}}}}}"}
    
  • 端点枚举:模糊测试隐藏的 API 版本(/api/v1/、/api/v2/、/api/internal/)、调试端点(/api/debug、/api/health、/api/metrics)和管理端点
  • 记录身份验证机制:确定 API 使用的是 API key、OAuth 2.0 Bearer token、JWT、会话 cookie 还是双向 TLS
第 2 步:身份验证与令牌测试

测试身份验证机制是否存在弱点:

  • JWT 分析:解码 JWT 并检查声明(sub、exp、iss、aud、role)。测试:
    • 算法混淆:将 alg 改为 none 并移除签名
    • 密钥混淆:将 alg 从 RS256 改为 HS256,并使用公钥签名
    • 弱密钥:使用 hashcat -m 16500 jwt.txt wordlist.txt 暴力破解 HMAC 密钥
    • 令牌过期:验证令牌会过期,且过期后无法使用
    • 声明篡改:修改 role、userId 或权限声明并重新签名
  • OAuth 2.0 测试:检查 redirect_uri 操纵、授权码重用、Referer 头中的令牌泄露以及缺少 state 参数(CSRF)
  • API key 安全:测试 API key 是否按端点进行验证、已撤销的 key 是否立即被拒绝,以及查询字符串中的 key 是否会出现在访问日志或分析数据中
步骤 3:授权测试(BOLA/BFLA)

测试失效的对象级授权(BOLA)和失效的功能级授权(BFLA):

  • BOLA(IDOR)测试:对于每个返回用户特定数据的端点,将对象标识符替换为另一个用户的标识符:
    • GET /api/users/123/orders -> GET /api/users/456/orders
    • 使用数字 ID、UUID、用户名和电子邮件地址进行测试
    • 使用 Burp Autorize 扩展自动化:配置两个会话(攻击者和受害者)并重放所有请求
  • BFLA 测试:使用低权限令牌,尝试访问管理端点:
    • DELETE /api/users/456(仅限管理员的删除)
    • PUT /api/users/456/role(角色修改)
    • GET /api/admin/dashboard(管理面板数据)
  • 批量赋值:发送文档中未显示的额外 JSON 属性:
    PUT /api/users/123
    {"name": "Test", "role": "admin", "isVerified": true, "balance": 99999}
    
  • HTTP 方法测试:如果 GET 在某个端点上有效,请尝试 PUT、PATCH、DELETE 和 OPTIONS 以发现未受保护的方法
步骤 4:输入验证和注入测试

测试 API 输入的注入和验证缺陷:

  • API 参数中的 SQL 注入:使用 SQL 注入负载测试所有参数(路径、查询、正文、标头)。JSON API 常被忽视:{"username": "admin' OR 1=1--", "password": "test"}
  • NoSQL 注入:对于 MongoDB 后端,使用运算符注入进行测试:{"username": {"$gt": ""}, "password": {"$gt": ""}}
  • 通过 API 的 SSRF:使用内部地址和云元数据端点测试任何接受 URL 的参数(webhook URL、头像 URL、导入端点)
  • GraphQL 特定注入:测试查询深度攻击、基于别名的批量暴力破解和字段建议枚举
  • XML API 中的 XXE:向接受 XML 的 API 端点提交带有外部实体声明的 XML 内容
  • 速率限制验证:向身份验证端点、密码重置和 OTP 验证发送 100+ 个快速请求,以测试暴力破解保护
步骤 5:数据暴露和响应分析

检查 API 响应中的过度数据暴露:

  • 详细响应:将 API 响应中返回的数据与 UI 显示的内容进行比较。API 通常返回比所需更多的字段(内部 ID、创建时间戳、其他用户的电子邮件地址、角色信息)。
  • 错误消息分析:通过发送格式错误的输入、无效令牌和不存在的资源来触发错误。检查错误消息是否泄露堆栈跟踪、数据库查询、内部路径或技术细节。
  • 分页和枚举:通过遍历分页响应(/api/users?page=1、page=2 等)测试是否可以枚举以提取所有记录
  • GraphQL 数据暴露:查询当前用户角色不应访问的字段。测试遍历关系以访问未授权数据的嵌套查询。
  • 调试端点:检查 /api/debug、/api/status、/metrics、/health、/.env、/api/swagger.json 以查找暴露的内部信息

关键概念

术语定义
BOLA失效的对象级授权(OWASP API #1);未能验证请求用户是否有权访问特定对象,从而导致 IDOR 攻击
BFLA失效的功能级授权(OWASP API #5);未能限制低权限用户访问管理或特权 API 功能
批量赋值一种漏洞,API 将客户端提供的数据绑定到内部对象属性时未进行过滤,允许攻击者修改他们本不应有权访问的字段
GraphQL 自省GraphQL 的内置功能,会暴露完整的 API schema,包括所有类型、字段和关系;应在生产环境中禁用
JWTJSON Web Token;一种自包含的令牌格式,用于 API 身份验证,包含使用密钥或密钥对签名的声明
速率限制用于限制客户端在时间窗口内可发起的 API 请求数量的控制措施,可防止暴力破解、枚举和滥用

工具与系统

  • Burp Suite Professional:用于拦截、修改和重放 API 请求的 HTTP 代理,可配合 Autorize 等扩展进行自动化授权测试
  • Postman:API 开发平台,用于组织端点集合、编写测试脚本,以及比较不同身份验证上下文中的响应
  • GraphQL Voyager:用于探索通过自省查询获得的 GraphQL schema 的可视化工具
  • jwt.io / jwt_tool:用于解码、分析和篡改 JWT 令牌以测试身份验证绕过的工具
  • Nuclei:基于模板的扫描器,带有针对 API 的模板,用于检测常见错误配置和已知漏洞

常见场景

场景:金融科技移动应用的 API 安全评估

背景:一家金融科技初创公司拥有一个移动银行应用,其后端为 REST API。该 API 处理账户管理、资金转账、账单支付和交易历史。测试人员拥有 Swagger 文档以及用户和管理员级别的账户。

方法:

  1. 将 Swagger 规范导入 Postman,在 12 个控制器中生成 87 个端点集合
  2. 在 /api/v1/accounts/{accountId}/transactions 上发现 BOLA,允许任何已认证用户查看任何账户的交易历史
  3. 在用户更新端点上发现批量赋值,添加 "dailyTransferLimit": 999999 可绕过配置的转账限额
  4. 确认资金转账端点缺乏速率限制,允许无限制的转账尝试且没有节流
  5. 发现 JWT 令牌的有效期为 30 天且没有刷新令牌轮换,从而导致长期会话劫持
  6. 发现管理员端点 /api/v1/admin/users 可使用标准用户令牌访问(BFLA)
  7. 报告所有发现,并附上 CVSS 评分和具体的 API 代码级修复指导

陷阱:

  • 仅测试 Swagger 中记录在案的端点,而遗漏未记录或已弃用的 API 版本
  • 未使用每个权限级别的令牌测试同一个端点,以检测授权绕过
  • 当 UI 仅显示返回字段的一部分时,忽略对响应正文的分析,从而遗漏过度数据暴露
  • 仅发送文档中显示的字段,未能测试批量赋值

输出格式

## Finding: Broken Object Level Authorization in Transaction History API

**ID**: API-001
**Severity**: Critical (CVSS 9.1)
**Affected Endpoint**: GET /api/v1/accounts/{accountId}/transactions
**OWASP API Category**: API1:2023 - Broken Object Level Authorization

**Description**:
The transaction history endpoint returns all transactions for the specified
account without verifying that the authenticated user owns the account. Any
authenticated user can view the complete transaction history of any account
by substituting the accountId path parameter.

**Proof of Concept**:
1. Authenticate as User A (account ID: ACC-10045)
2. Request: GET /api/v1/accounts/ACC-10046/transactions
   Authorization: Bearer <User_A_token>
3. Response: 200 OK with User B's full transaction history

**Impact**:
Any authenticated user can view the complete financial transaction history of
all 45,000 customer accounts, including amounts, dates, recipients, and
transaction descriptions.

**Remediation**:
Implement server-side authorization check that verifies the authenticated user
owns the requested account before returning data:
  const account = await Account.findById(accountId);
  if (account.userId !== req.user.id) return res.status(403).json({error: "Forbidden"});

评论

支持 Markdown