Skip to content
KitploitKITPLOIT
工具漏洞利用博客
Log in
提交
工具漏洞利用博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

··订阅源·联系·隐私·© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
CVE-2025-8088 — CVE-2025-8088 | Kitploit
工具/GitHubGitHub/nhattanhh/cve-2025-8088
持久化机制漏洞分析漏洞利用二进制分析学习与教育Payload 开发
GitHubnhattanhh/cve-2025-8088

CVE-2025-8088

CVE-2025-8088

查看仓库
231年前尚未审核

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享

技术深度解析:CVE-2025-8088 - 坚忍不拔的路径遍历漏洞

免责声明:本文内容仅供教育和研究目的。请勿将本信息用于任何恶意活动。

今天,我们将深入探讨一个引人入胜的路径遍历漏洞,编号为 CVE-2025-8088。该漏洞允许攻击者在受害者解压特制的 RAR 压缩包时,将任意文件写入受害者系统上的任何位置。这一特定漏洞利用之所以有趣,在于它采用了“霰弹枪”式的策略,确保无论用户在何处解压压缩包,都能成功投递载荷。

本文将详细解析所提供的 Python 概念验证代码(PoC)中用于构造恶意 .rar 文件的技术细节。


目标:实现持久化

该 PoC 的最终目标经典且有效:持久化。通过利用路径遍历漏洞,该漏洞利用程序试图将载荷(payload.bat)投递到 Windows 启动文件夹(AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup)中。放置在此处的任何可执行文件或脚本都将在用户下次登录时自动运行,从而为攻击者提供持久化访问权限。


漏洞利用策略:逐步分解

该 Python 脚本自动化了一个多步骤过程,以构建最终的 exploit.rar。让我们逐步分析其逻辑。

第一步:准备工作 —— 诱饵文件、载荷和占位符

脚本首先准备以下组件:

  1. 载荷: 创建了一个名为 payload.bat 的简单批处理文件。这就是我们想要投递到受害者机器上的恶意文件。
PAYLOAD = "@echo off\necho Payload executed!\npause\n"
  1. 诱饵文件: 脚本生成了几个看起来无害的文本文件(例如 file1.txt、file2.txt 等)。这些文件有两个目的:使压缩包看起来合法;更重要的是,它们作为隐藏载荷的载体。
def create_files() -> Tuple[List[Path], Path]:
    # ...
    for i in range(NUM_DEPTHS):
        decoy = Path(f"{DECOY_FILE_PREFIX}{i+1}.txt")
  1. 占位符: 定义了一个由重复字符组成的长字符串("X" * 200)。这个占位符将被嵌入到压缩包的元数据中,稍后会被替换为恶意路径。

第二步:隐藏武器 —— 备用数据流(ADS)

这是该技术的关键部分。脚本没有直接使用遍历路径来命名文件,而是利用了 NTFS 文件系统的一个特性:备用数据流(Alternate Data Streams,ADS)。ADS 允许你在现有文件中“隐藏”数据。

脚本将 payload.bat 作为 ADS 附加到每个诱饵文件上。这个流的名称就是使用占位符的地方。实际上,它创建的文件路径在文件系统中看起来像这样: file1.txt:XXXXXXXXXXXXXXXXXXXX...

payload.bat 的内容现在被秘密地存储在 file1.txt 内部。

def attach_ads(decoy: Path, placeholder: str):
    """Attach payload to decoy as Alternate Data Stream"""
    ads_path = f"{decoy}:{placeholder}"
    with open(ads_path, "wb") as f:
        f.write(Path("payload.bat").read_bytes())

第三步:基础建设 —— 一个“干净”的 RAR 压缩包

接下来,脚本在系统中找到命令行工具 Rar.exe,并使用它创建一个合法的基准压缩包(base.rar)。该压缩包包含所有诱饵文件,这些文件现在已经在备用数据流中秘密携带了载荷。

此时,base.rar 是一个完全有效且无恶意的压缩包。WinRAR 可以毫无问题地解压它,并会创建带有其长且奇怪的 ADS 名称的诱饵文件。

def create_base_rar(rar_exe: str, decoys: List[Path]) -> Path:
    # ...
    subprocess.run(
        f'"{rar_exe}" a -ep -os "{base_rar}" {files}',
        # ...
    )

第四步:“霰弹枪”式方法 —— 生成多个遍历路径

这就是漏洞利用变得巧妙且坚韧的地方。攻击者不知道受害者会将压缩包解压到何处。是 C:\Users\victim\Downloads?C:\?D:\Temp?

为了克服这种不确定性,脚本生成了一组不同的路径遍历字符串,每个字符串具有不同的深度:

  • ..\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\payload.bat
  • ..\..\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\payload.bat
  • ..\..\..\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\payload.bat
  • ......以此类推。

其思路是,通过提供多个深度,至少有一个能够成功地从解压目录导航回文件系统的根目录(例如 C:\),然后进入目标启动文件夹。

def build_relative_paths() -> List[str]:
    """Generate paths with different traversal depths"""
    paths = []
    for depth in range(1, NUM_DEPTHS + 1):
        paths.append(("..\\" * depth) + RELATIVE_DROP_PATH)
    return paths

第五步:魔法时刻 —— 二进制修补 RAR 头部

这是漏洞利用的核心。脚本以二进制模式打开 base.rar 并对其进行手术式修改。

它遍历压缩包的内部结构,查找每个文件(file1.txt、file2.txt 等)的头部。在每个头部内部,它找到占位符 ADS 名称(:XXXXXXXXXXXXXXXXXXXX...),并将其替换为上一步生成的一个恶意遍历路径。

  • file1.txt 的头部得到带有 ..\ 的路径。
  • file2.txt 的头部得到带有 ..\..\ 的路径。
  • 以此类推。
def patch_rar(base_rar: Path, placeholder: str, relative_paths: List[str]) -> Path:
    # ...
    while pos + 4 <= len(data) and current_file_index < len(target_paths_utf8):
        # ...
        # Find the placeholder and replace it with the target path
        c = patch_placeholder_in_header(hdr, placeholder_utf8, target_utf8)
        # ...

第六步:掩盖痕迹 —— 重新计算 CRC

仅仅修改头部数据会导致压缩包损坏。WinRAR 使用 CRC32 校验和来验证每个头部块的完整性。如果校验和与头部内容不匹配,它会报错。

PoC 考虑了这一点。在将恶意路径修补到头部后,它会重新计算整个修改后头部块的正确 CRC32 校验和,并将新的校验和写回文件中。这使得被篡改的压缩包在 WinRAR 看来仍然是完全有效的。

def rebuild_all_header_crc(buf: bytearray) -> int:
    """Recalculate CRC checksums for all headers"""
    # ...
    while pos + 4 <= len(buf):
        # ...
        # Calculate CRC for the header region
        region = buf[block_start + 4:header_end]
        crc = zlib.crc32(region) & 0xFFFFFFFF
        # Write the new CRC back into the buffer
        struct.pack_into("<I", buf, block_start, crc)
        # ...
下载工具