![在这里插入图片描述](https://img-blog.csdnimg.cn/c24b0a3856d44ebda67d551d85c7597b.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBASEJvaGFu,size_20,color_FFFFFF,t_70,g_se,x_16)
背景
Nacos 致力于帮助您发现、配置和管理微服务。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据及流量管理。
Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。 Nacos 是构建以“服务”为中心的现代应用架构 (例如微服务范式、云原生范式) 的服务基础设施。
Nacos是阿里巴巴于2018年开源的项目,目前在Github中已获得 19.8kSt,由此可见其的使用广泛程度。
未授权访问漏洞
threedr3am师傅在去年十二月份的时候在Github上给Nacos项目提交了Bypass 认证的Issue,详情可移步https://github.com/alibaba/nacos/issues/4593。在该Issue中提及了漏洞详情,Nacos的认证过滤器中会判断客户端的User-Agent如果是以Constants.NACOS_SERVER_HEADER(Nacos-Server)开头的话,则直接return返回。 ![在这里插入图片描述](https://img-blog.csdnimg.cn/188ae28afc614c3abf7f687f217c1194.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBASEJvaGFu,size_20,color_FFFFFF,t_70,g_se,x_16) 对于上述的认证绕过漏洞争议很大,Nacos官方起初并不认为这是一个安全漏洞的问题,不过还是在1.4.1版本中发布了漏洞修复补丁。在1.4.1版本中需要在 application.properties添加nacos.core.auth.enable.userAgentAuthWhite的属性值为false,即可避免使用User-Agent绕过鉴权的问题,但这也引发了新的Bypass,具体的漏洞详情可移步至https://github.com/alibaba/nacos/issues/4701,不再赘述。
客户端Yaml反序列化
在Nacos的releases记录中搜索 yaml 关键字不难发现其在1.4.2版本中有个PR更新了Yaml的安全解析: ![在这里插入图片描述](https://img-blog.csdnimg.cn/d53ac58902274659929efe8212c0275e.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBASEJvaGFu,size_20,color_FFFFFF,t_70,g_se,x_16) 而根据PR的描述内容可知实际上该漏洞只影响单独使用 nacos-client SDK的用户,原因在于spring cloud、springboot、dubbo等框架中并非使用的 AbstractConfigChangeListener 监听配置,所以该漏洞只影响了使用AbstractConfigChangeListener监听配置的客户端。 ![在这里插入图片描述](https://img-blog.csdnimg.cn/7ba15996ee4f455c8399b15c8f2b35a8.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBASEJvaGFu,size_20,color_FFFFFF,t_70,g_se,x_16)
漏洞分析
首先在Nacos服务端中添加一个用于测试监听的配置:
![在这里插入图片描述](https://img-blog.csdnimg.cn/9b1bc11215374a1590e0de28ca4c5857.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBASEJvaGFu,size_20,color_FFFFFF,t_70,g_se,x_16)
使用Maven引入nacos-client依赖:
<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-client</artifactId>
<version>1.4.1</version>
</dependency>
以官方的监听配置请求示例复现,需要修改serverAddr、dataId、group、Listener,如果配置了登陆还需要添加username和password。
import com.alibaba.nacos.api.NacosFactory;
import com.alibaba.nacos.api.config.ConfigChangeEvent;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.client.config.listener.impl.AbstractConfigChangeListener;
import java.util.Properties;
public class Client {
public static void main(String[] args) throws Exception {
String serverAddr = "{serverAddr}";
String dataId = "{dataId}";
String group = "{group}";
Properties properties = new Properties();
properties.put("serverAddr", serverAddr);
properties.put("username", "nacos");
properties.put("password", "nacos");
ConfigService configService = NacosFactory.createConfigService(properties);
String content = configService.getConfig(dataId, group, 5000);
System.out.println(content);
configService.addListener(dataId, group, new AbstractConfigChangeListener() {
@Override
public void receiveConfigChange(ConfigChangeEvent configChangeEvent) {
System.out.println(configChangeEvent);
}
});
while (true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
然后在com.alibaba.nacos.client.config.impl.YmlChangeParser#doParse方法中打下断点: ![在这里插入图片描述](https://img-blog.csdnimg.cn/0d27742a9f05485081c0bf732105edf9.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBASEJvaGFu,size_20,color_FFFFFF,t_70,g_se,x_16) 开启Debug并在服务端中修改上述用于测试的配置内容为yaml反序列化的payload,该payload会加载远程的jar包并运行主类的代码。 ![在这里插入图片描述](https://img-blog.csdnimg.cn/b6c91126b7b6428bacdc9a9605af1966.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBASEJvaGFu,size_20,color_FFFFFF,t_70,g_se,x_16) 点击发布后即可命中断点 ![在这里插入图片描述](https://img-blog.csdnimg.cn/4e698381d9ab4d53aed95b0d6b026806.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBASEJvaGFu,size_20,color_FFFFFF,t_70,g_se,x_16) 再根据堆栈信息进行回溯的调试,首先在ConfigFactory#createConfigService方法中通过反射获取com.alibaba.nacos.client.config.NacosConfigService类的实例对象并返回该对象。 ![在这里插入图片描述](https://img-blog.csdnimg.cn/ad2aea1cc4014fe585fc0a261522706b.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBASEJvaGFu,size_20,color_FFFFFF,t_70,g_se,x_16) 在NacosConfigService的构造器中实例化ClientWorker对象 ![在这里插入图片描述](https://img-blog.csdnimg.cn/d3a74a462b624bc09e2fd5b41ff960d7.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBASEJvaGFu,size_20,color_FFFFFF,t_70,g_se,x_16) 跟进ClientWorker的checkConfigInfo方法 ![在这里插入图片描述](https://img-blog.csdnimg.cn/3f7e6042e693473ebdc6072b04748fc2.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBASEJvaGFu,size_20,color_FFFFFF,t_70,g_se,x_16) 传入的对象为ClientWorker的内部类LongPollingRunnable对象,会调用其run方法。 ![在这里插入图片描述](https://img-blog.csdnimg.cn/68cd6f4bdc644fc594de1301b1dbb761.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBASEJvaGFu,size_20,color_FFFFFF,t_70,g_se,x_16) 而run方法就是nacos客户端的长轮询监听,run方法中会循环调用cacheDatax.checkListenerMd5方法,而CacheData对象是从ClientWorker对象的cacheMap属性中获取的。
Iterator var3 = ClientWorker.this.cacheMap.values().iterator();
![在这里插入图片描述](https://img-blog.csdnimg.cn/7d884d49ccea42f0838806da2dc6ce5a.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBASEJvaGFu,size_20,color_FFFFFF,t_70,g_se,x_16) 而cacheMap中缓存的CacheData对象是在客户端添加监听的时候写入的 ![在这里插入图片描述](https://img-blog.csdnimg.cn/3590b4ac20a94ef797a629568582294f.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBASEJvaGFu,size_20,color_FFFFFF,t_70,g_se,x_16) 再回到ClientWorker.LongPollingRunnable#run方法中,前面说到其会调用checkListenerMd5方法,该方法中会调用safeNotifyListener方法,并传入监听配置的dataId、group、content(修改的新内容)、type、md5及CacheData.ManagerListenerWrap对象。 ![在这里插入图片描述](https://img-blog.csdnimg.cn/16cbacaedb4547178b2078c41c4d0242.png) 在safeNotifyListener方法中调用了ConfigChangeHandler#parseChangeData方法解析数据,传入的参数listenerWrap.lastContent为修改前的内容,content为修改后的内容,type为数据类型(TEXT/JSON/XML/YAML/HTML/Properties)。 ![在这里插入图片描述](https://img-blog.csdnimg.cn/da5ee2a3ba9047aeb0575cc705ef259e.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBASEJvaGFu,size_20,color_FFFFFF,t_70,g_se,x_16) 其会调用YmlChangeParser#doParse方法 ![在这里插入图片描述](https://img-blog.csdnimg.cn/68042683ce014b6f967ab848516c9ad4.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBASEJvaGFu,size_20,color_FFFFFF,t_70,g_se,x_16) YmlChangeParser#doParser方法中触发Yaml反序列化漏洞,请求远程的Jar包并执行。 ![在这里插入图片描述](https://img-blog.csdnimg.cn/7d67df2db62045978628ab1e50441c7d.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBASEJvaGFu,size_20,color_FFFFFF,t_70,g_se,x_16) ![在这里插入图片描述](https://img-blog.csdnimg.cn/26eb72b02e884e7fa3daf5e74e8eedb1.png) 再次声明,该漏洞只影响使用AbstractConfigChangeListener监听器的客户端,原因如下: ![在这里插入图片描述](https://img-blog.csdnimg.cn/a3a1a4165d86485fa4199c0eaf8c0d5b.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBASEJvaGFu,size_20,color_FFFFFF,t_70,g_se,x_16)
漏洞修复
在1.4.2版本中已修复了该漏洞,修复方法为使用SnakeYaml提供的SafeConstructor解析Yaml配置。 ![在这里插入图片描述](https://img-blog.csdnimg.cn/176a7d7f3c7a4a778c4077af2ed00904.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBASEJvaGFu,size_20,color_FFFFFF,t_70,g_se,x_16)
实战应用
在实际的渗透测试中如果获取了Nacos Server控制台权限的话,不妨可以尝试修改已有的配置为Yaml Payload进行盲打客户端的攻击。但通常情况下的Springboot或SpringCloud都可以集成使用Nacos,所以这种场景下一般不会出现存在漏洞的情况。
最后
关注私我获取2021最新【网络安全学习资料·攻略】 ![在这里插入图片描述](https://img-blog.csdnimg.cn/d3781e2a85574b20a287c12b8f095d57.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBASEJvaGFu,size_13,color_FFFFFF,t_70,g_se,x_16)
|