2. API基础与攻击面分析

API安全测试的第一步不是直接上扫描器,而是先弄清楚“被测对象到底是什么”。同样是HTTP接口,REST、GraphQL、gRPC、WebSocket在协议、数据格式、调用方式和信任模型上差异很大,攻击面也完全不同。如果测试人员把GraphQL当成REST来测,很可能只覆盖了少量查询入口,却漏掉了内省、批量查询、字段级越权等关键风险。

四类主流API的协议特征与攻击面差异

REST以资源为中心,使用HTTP方法(GET/POST/PUT/PATCH/DELETE)表达操作语义,通常以JSON传输数据,通过URL路径和查询参数定位资源。它的攻击面集中在:越权访问(IDOR)、批量赋值、HTTP方法覆盖、参数污染、版本回退(如/v1/仍可访问)、以及错误信息泄露。测试时应重点关注资源ID的可枚举性和方法级权限校验是否一致。

GraphQL只有一个入口端点(通常是/graphql),由客户端提交查询文档,服务端按字段解析。它的攻击面与REST截然不同:内省查询(__schema)可能暴露完整数据模型;嵌套查询和别名可以构造高复杂度请求造成资源耗尽;字段级授权若只在查询根节点校验,深层字段可能被越权读取;批量操作(如多个mutation)可能绕过单次请求限制。测试重点是查询深度、复杂度限制、字段级权限和内省是否在生产环境关闭。

gRPC基于HTTP/2和Protocol Buffers,使用.proto定义服务契约,支持四种调用模式:一元、服务端流、客户端流、双向流。它的攻击面包括:反射服务(Server Reflection)暴露接口定义、消息字段的默认值与可选性导致校验遗漏、流式调用中的资源控制、以及HTTP/2特有的多路复用和头部压缩带来的请求走私风险。测试时需要关注proto文件是否可获取、流式接口是否有速率和大小限制。

WebSocket通过一次HTTP升级握手建立全双工长连接,之后的消息不再遵循请求-响应模式。它的攻击面在于:握手阶段的认证是否可靠、连接建立后是否有消息级授权、跨站WebSocket劫持(CSWSH)、消息频率和大小限制、以及连接生命周期管理。测试重点是握手时的Origin校验、消息级权限、以及断线重连是否会导致会话状态异常。

四类API的协议特征与攻击面聚焦 REST 协议:HTTP/1.1 · JSON 入口:多URL路径 操作:GET/POST/PUT/DELETE 攻击面: IDOR · 批量赋值 · 方法覆盖 版本回退 · 错误信息泄露 GraphQL 协议:HTTP · 查询文档 入口:单一端点 /graphql 操作:Query / Mutation 攻击面: 内省泄露 · 嵌套复杂度 · 字段越权 批量mutation · 别名滥用 gRPC 协议:HTTP/2 · Protobuf 入口:.proto定义的服务方法 模式:一元/流式(4种) 攻击面: 反射服务 · 字段默认值 · 流控 HTTP/2走私 · 头部压缩 WebSocket 协议:HTTP升级 · 全双工 入口:ws:// 或 wss:// 端点 模式:长连接 · 消息帧 攻击面: CSWSH · 消息级授权 · 频率限制 握手认证 · 重连状态 攻击面识别方法:从资产清点到风险映射 ① 资产清点 端点/协议/版本/文档 Swagger/Proto/内省 → ② 认证与授权 Token/Session/API Key 角色/权限/字段级 → ③ 输入与解析 参数/类型/边界 注入/反序列化 → ④ 业务逻辑 流程绕过/竞态 状态机/重放 → ⑤ 风险映射 OWASP API Top 10 对照 资产清点 → 认证授权 → 输入解析 → 业务逻辑 → 风险映射,形成可复用的攻击面清单 每个环节输出:端点清单、权限矩阵、参数边界表、业务流程图、风险登记表 示例:某电商API清点出 47 个端点,其中 6 个未鉴权、3 个存在IDOR、2 个GraphQL字段越权

API生命周期与攻击面迁移

API不是静态存在的,它经历设计、开发、测试、发布、运行、迭代、下线七个阶段。攻击面会随生命周期迁移:设计阶段若未定义权限模型,开发阶段就可能把鉴权逻辑散落在各接口中;测试阶段若只测功能不测安全,发布后就会暴露未授权访问;运行阶段若缺少版本管理和废弃策略,旧版本接口可能成为绕过新安全控制的“后门”。

实际工作中,建议建立一张API资产台账,至少记录:端点路径、协议类型、认证方式、数据敏感级别、负责人、当前版本、是否对外网开放、最近一次安全测试时间。这张台账是攻击面识别的起点,也是后续风险治理的依据。

常见API架构与信任边界

API架构决定了信任边界在哪里。常见的三种模式:

  • 直连模式:客户端直接调用后端服务。信任边界在客户端与API网关之间,网关负责认证、限流、日志。测试重点是网关规则是否可绕过(如直接访问后端IP)。
  • BFF模式:为不同前端(Web/App/小程序)提供专属后端。信任边界在BFF层,BFF可能聚合多个下游服务。测试重点是BFF是否对下游服务做了权限透传,还是简单转发导致越权。
  • 微服务网关模式:API网关统一入口,内部服务通过服务网格通信。信任边界在网关和网格边车(Sidecar)之间。测试重点是服务间认证(mTLS)、网格策略是否覆盖所有服务、以及内部服务是否意外暴露。

攻击面识别实操:从文档到验证

以某电商平台的REST API为例,演示攻击面识别的关键动作:

# 1. 获取API文档(示例)
curl -s https://api.example.com/swagger.json | jq '.paths | keys[]'
# 输出示例:
# /api/v1/users/{id}
# /api/v1/orders
# /api/v1/orders/{id}/cancel
# /api/v1/admin/users

# 2. 检查未鉴权端点(示例)
curl -s -o /dev/null -w "%{http_code}" https://api.example.com/api/v1/users/1001
# 若返回 200 且包含用户数据,说明存在未授权访问

# 3. 检查方法覆盖(示例)
curl -s -X PUT https://api.example.com/api/v1/users/1001 -d '{"role":"admin"}'
# 若返回 200,说明存在批量赋值或方法级权限缺失

# 4. GraphQL内省检查(示例)
curl -s -X POST https://api.example.com/graphql \
  -H "Content-Type: application/json" \
  -d '{"query":"{__schema{types{name}}}"}'
# 若返回完整类型列表,说明内省未关闭

上述命令中的域名、路径和返回码均为教学示例,实际测试需替换为目标环境并确保获得授权。判断依据是:未鉴权端点返回敏感数据、方法覆盖成功修改了不应修改的字段、内省返回了完整数据模型,这三类结果都意味着攻击面已经暴露。

合规提醒:所有攻击面识别动作必须在书面授权范围内进行。未授权扫描、越权测试、数据读取都可能违反法律法规。测试前应确认授权范围、时间窗口、允许的测试方法和禁止的操作。

攻击面清单模板

完成识别后,建议输出一份可执行的攻击面清单,字段如下:

字段 说明 示例
端点 完整路径与方法 GET /api/v1/users/{id}
协议 REST/GraphQL/gRPC/WebSocket REST
认证方式 JWT/Session/API Key/无 JWT
权限要求 角色或权限标识 user:read
数据敏感级 公开/内部/机密 机密
已识别风险 风险类型与验证结果 IDOR(已验证)
风险等级 高/中/低 高
修复建议 具体可执行措施 增加资源归属校验

这张清单不是一次性文档,而应随API迭代持续更新。每次新增端点、修改权限、升级版本时,都应在清单中同步记录,并在发布前完成对应的安全验证。攻击面识别不是“测一次就结束”的任务,而是贯穿API生命周期的持续活动。