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

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

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

피드문의개인정보© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
spark-history-store-path — Apache Spark 4.2.0 - 높음 - 원격 - 파일 쓰기 - History appStorePath의 App ID 미검증 | Kitploit
도구/GitHubGitHub/abraxas/spark-history-store-path
Static AnalysisVulnerability AnalysisCode AnalysisExploitationWeb Application ExploitationPenetration TestingLabs & Practice
GitHubabraxas/spark-history-store-path

spark-history-store-path

Apache Spark 4.2.0 - 높음 - 원격 - 파일 쓰기 - History appStorePath의 App ID 미검증

저장소 보기
1610일 전아직 검토되지 않음

인기

모두 보기 →

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

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

Abraxas Labs - spark-history-store-path

abraxaslabs.tech  ·  github.com/abraxas  ·  @abraxas_null  ·  [email protected]  ·  spark-history-store-path

분석 문서: https://abraxaslabs.tech/research/spark-history-store-path

spark-history-store-path

분류: 파일 쓰기 (설정에 의해 제한됨) 도달 범위: 원격

Apache Spark 4.2.0 (32f72996) - Apache Software Foundation

HistoryServerDiskManager.appStorePath는 정제 없이 new File(appStoreDir, appId + extension)을 수행합니다. Utils.sanitizeDirName은 이벤트 로그 파일 이름에만 사용됩니다. JSON App ID는 asText()입니다. 목록 조회는 event.appId.orNull을 저장합니다. Lease.commit은 그 문자열을 사용합니다. App ID ../는 spark.history.store.path 외부에 .rdb를 씁니다. 기본적으로 설정되지 않은 store.path는 인메모리입니다(쓰기 없음). 내용은 저장소 파일이며 RCE는 아닙니다.

ID아직 CVE 없음
분류파일 쓰기 (설정에 의해 제한되는 History 디스크 저장소)
도달 범위원격 (이벤트 로그 작성자와 spark.history.store.path가 설정된 History; UI ACL은 기본적으로 꺼짐)
CWECWE-22
CVSS높음: 7.5 CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N (spark.history.store.path가 설정된 경우)
제품Apache Spark History Server
영향 받는 버전4.2.0 (32f7299601108917fb01920a54e084595b7b3bf8)
인증spark.history.fs.logDirectory(기본값 file:/tmp/spark-events)의 작성자; History에 spark.history.store.path가 설정되어 있어야 함
라이선스GNU Affero GPL v3.0
실습 환경127.0.0.1:18990 전용. 인용된 조인의 가젯. store.path 외부의 .rdb 증거.

공격자가 할 수 있는 일

CVE-2025-54920과 동일한 피해자 모델입니다: History Server가 공격자가 쓸 수 있는 로그 디렉터리를 가리키도록 설정된 경우입니다. Jackson은 더 이상 HiveConnection 클래스 가젯을 생성하지 않습니다. 디스크 저장소 경로는 여전히 이벤트 JSON의 App ID를 신뢰합니다.

방법싱크권한실험실 vs 추론
JSON App ID가 ../<name>(또는 ../../oracle/...)인 이벤트 로그를 심는다. 스캔을 기다린다. 앱 UI를 로드하는 GET / getAppUI / loadDiskStore / createDiskStoreHistoryServerDiskManager.appStorePath 이후 Lease.commit renameTo무결성: History UID로서 {store.path}/apps 외부에 .rdb(기본 RocksDB) 또는 .ldb(LevelDB) 경로를 생성한다. 가젯에서 실험실 입증: escaped=yes, 파일 /work/oracle/SPARK-HISTORY-STORE-PATH-WITNESS.rdb에 위트니스가 포함됨. 내용은 스토어 파일이며, 공격자가 선택한 호스트 바이트코드도, 셸도 아니다.실험실 입증(탈출 경로에 위트니스 바이트를 쓰는 가젯). RocksDB 디렉터리의 전체 History renameTo도 동일한 조인이다.
탈출한 목적지가 이미 디렉터리인 경우 동일한 App IDLease.commit if (dst.isDirectory()) deleteStore(dst) 이후 Utils.deleteRecursively가용성: 이름이 이미 백엔드 접미사로 끝나는 기존 디렉터리를 삭제한 뒤, 임대된 스토어로 교체한다.추론(HistoryServerDiskManager.scala 커밋 고정). 가젯은 파일을 썼으며 deleteRecursively를 호출하지 않았다.
기본값으로 설정되지 않은 spark.history.store.pathLOCAL_STORE_DIR createOptional; diskManager = storePath.map닫힘. 인메모리 목록. HistoryServerDiskManager 없음. 실험실 입증 gated=yes written=no.실험실 입증
App ID에 먼저 Utils.sanitizeDirName 적용이벤트 로그 파일명 헬퍼apps/ 내부에 머문다. /와 :는 -가 된다. 실험실 입증 부정.실험실 입증
store.path가 설정된 상태에서 App ID local-control 제어동일한 조인{store.path}/apps/local-control.rdb에 쓴다. apps/ 내부에 머문다.실험실 입증

인접한 닫힌 항목: 기본 미설정 스토어(인메모리). Jackson sparkEventFromJson은 여전히 SparkListenerEvent를 요구한다(CVE-2025-54920). URL getAppUI 폴백 eventlog_v2_ + nameForAppAndAttempt는 정제된다. 목록 KV 키는 파일시스템 경로가 아니다. HybridStore / kvstore 매퍼에는 Id.CLASS가 없다. History HTTP는 업로드 경로를 받지 않는다. 컴팩션 기본 꺼짐. 클리너 기본 꺼짐. 열린 클러스터에서의 작업 제출(SECURITY.md FAQ). ML 모델 로드(docs/ml-security.md). 이 잔여물은 호스트 RCE가 아니다.

발견 경위

나는 Spark 4.2.0을 고정했다. master도, 4.3 RC도 아니다. 스물여덟 번의 추적. 공개된 History Jackson RCE는 이 껍질에서는 닫혀 있다. 이벤트 로그 작성자는 이미 Utils.sanitizeDirName을 호출하므로 로그 파일에는 /가 포함될 수 없다. 디스크 캐시 파일 이름은 원시 App ID를 사용한다.

private[history] def appStorePath(appId: String, attemptId: Option[String]): File = {
  val fileName = appId + attemptId.map("_" + _).getOrElse("") + extension
  new File(appStoreDir, fileName)
}

appStoreDir는 {spark.history.store.path}/apps입니다. Unix에서 new File(parent, "../../oracle/name.rdb")는 상위 디렉터리 밖으로 해석됩니다. JsonProtocol.applicationStartFromJson은 json.get("App ID").asText()를 사용합니다. AppListingListener.onApplicationStart는 event.appId.orNull을 저장합니다. lease.commit(appId, attempt.info.attemptId)가 해당 문자열을 appStorePath로 전달합니다.

이미 기록된 잘못된 판단: 기본값으로 설정되지 않은 store.path를 쓰기로 간주한 것(실제로는 인메모리임); Unix의 new File(dir, "/abs")가 상위 디렉터리를 무시할 것이라고 기대한 것(그렇지 않음; 남는 것은 ..임); 접미사가 .rdb라는 이유로 RCE를 주장한 것; 조인이 oracle인데도 전체 History Server를 부팅한 것; sanitizeDirName이 이 경로를 커버한다고 간주한 것.

Lab

python3 spark-history-store-path-Abraxas-Labs.py

또는

cd lab
./run.sh

127.0.0.1:18990에서 HistoryServerDiskManager.appStorePath의 Gadget. 발췌 내용은 lab/pin/ 아래에 고정한다. 전체 History Server는 부팅되지 않는다. 루프백에 바인딩한다.

SUCCESS SPARK-HISTORY-STORE-PATH how=gadget escaped=yes gated=yes outside=/work/oracle/SPARK-HISTORY-STORE-PATH-WITNESS.rdb SPARK-HISTORY-STORE-PATH-WITNESS

수정 방법

new File 이전에 appStorePath 내부의 appId와 attemptId에 대해 Utils.sanitizeDirName을 실행하거나(또는 .. / / / NUL을 거부) 처리해야 합니다. 경로를 결합한 후에는 dst.getCanonicalFile()이 appStoreDir.getCanonicalFile() 아래에 유지되는지 확인해야 합니다. spark.history.store.path를 설정하지 않은 상태가 안전한 기본값으로 유지됩니다.

참고 자료

  • github.com/apache/spark 태그 v4.2.0 (32f7299601108917fb01920a54e084595b7b3bf8)
  • HistoryServerDiskManager.scala appStorePath / Lease.commit
  • FsHistoryProvider.scala diskManager / loadDiskStore / onApplicationStart
  • JsonProtocol.scala applicationStartFromJson
  • Utils.scala sanitizeDirName
  • History.scala LOCAL_STORE_DIR (선택 사항)
  • 종료된 Jackson 경로 탐색: CVE-2025-54920 / SPARK-52381
  • CWE-22

라이선스

GNU Affero GPL v3.0. LICENSE를 참조하세요. 루프백 실험 환경 전용입니다. 보증은 제공되지 않습니다.

도구 다운로드