Nacos权限认证绕过(CVE-2021-29441)详解
摘要:Nacos<=2.0.0-ALPHA.1版本存在未授权漏洞,攻击者通过修改User-Agent为"Nacos-Server"可绕过认证。漏洞允许未授权查看用户列表(含BCrypt加密密码)和添加任意用户,成因在于AuthFilter.java中未严格校验User-Agent,匹配"Nacos-Server"即放行请求。该问题实为开发者预留的后门逻
影响版本: Nacos <= 2.0.0-ALPHA.1
小于或等于2.0.0预发布的版本
在2.0.0正式版往后版本不存在
一.复现过程
1.未授权查看用户列表
访问主页

修改路径为/nacos/v1/auth/users?pageNo=1&pageSize=1,访问并抓包

可以看到直接访问是403(无权限),我们把User-Agent:修改为Nacos-Server

直接绕过了认证,查看到了账号以及加密密码。

密码为BCrypt单向哈希加密,可以通过此工具https://github.com/wolaile08/BCryptDecode进行穷举爆破。
2.未授权添加任意用户
访问路径/nacos/v1/auth/users,同时抓包。这里我不建议直接改修改包去访问,因为可能会少一些原本正常访问时会带上的请求头。

添加username与password参数,发送,回显200即添加账密成功。返回登录框验证。


登录成功。
二.漏洞成因
两个都是未授权,未授权意味着这里原本是有限制的,但修改了一下User-Agent头就放行了,为什么?从代码层面分析一下(本身感觉也就是代审洞):
java后端里负责捕获User-Agent头的方法名称叫做 HttpServletRequest,也就是说,我们只需要寻找哪些文件会调用此方法,又调用去干了什么。
为什么我会知道类名?因为java后端的各类接口开发声明是基于 Servlet 规范的,所以方法名基本都是一致的。
开始追溯此方法,打开源码包,直接寻找相关代码:

我在AuthFilter.java文件中发现了User-Agent捕获函数与过滤器chain.doFilter同时出现的代码,这应该就是了,我们分析一下

捕获请求包的User-Agent头,并赋值给req变量:
HttpServletRequest req = (HttpServletRequest) request;
捕获响应包的User-Agent头,并赋值给resp变量:
HttpServletResponse resp = (HttpServletResponse) response;
声明一个字符串变量,userAgrnt,他被赋值了什么呢?
String userAgent = WebUtils.getUserAgent(req);
这就需要接着追溯WebUtils这个类了,

直接就找到了,我这里删一下注释方便看的更清晰。

成功找到了此类的getUserAgent方法,这里也逐步解释一下:

声明一个静态字符串方法,getUserAgent(),里面的HttpServletRequest request是获取请求包里User-Agent内容的方法:
public static String getUserAgent(HttpServletRequest request)
声明一个字符串变量,userAgent,后面的类和方法需要进一步追溯,首先看括号里的
String userAgent = request.getHeader(HttpHeaderConsts.USER_AGENT_HEADER);

只是个传递字符串用的类,所以这个方法可以简化成,
String userAgent = request.getHeader(User-Agent);
而request.getHeader的意思是获取请求头内容,比如
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:141.0) Gecko/20100101 Firefox/141.0
那么request.getHeader(User-Agent)就是:
Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:141.0) Gecko/20100101 Firefox/141.0
综上所述,AuthFilter.java文件里的变量userAgent=当前请求包User-Agent传参内容。

接着往下看这条if语句,这是个比较if判断,如果userAgent的内容和Constants.NACOS_SERVER_HEADER方法内的内容一模一样,触发下面的chain.doFilter方法,先看看Constants.NACOS_SERVER_HEADER是什么:

看到了我们眼熟的东西,这不就是触发未授权的User-Agenr传参吗,所以上面的if语句可以简化成:
if (StringUtils.startsWith(userAgent, "Nacos-Server")) {
chain.doFilter(request, response);
return;
我们传参Nacos-Server,此时userAgent="Nacos-Server",与Constants.NACOS_SERVER_HEADER="Nacos-Server"比对,如果等于,则触发chain.doFilter过滤器,直接绕过限制,漏洞成因已解。
总结,该漏洞本质是开发者留的后门,但被代审大佬发现,故而造成严重的安全漏洞。
更多推荐


所有评论(0)