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

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

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

피드문의개인정보© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
spark-python-ds-static — Apache Spark 4.2.0 - 높음 - 원격 - 권한 잔여 - 프로세스 전역 Python 데이터 소스 맵 | Kitploit
도구/GitHubGitHub/abraxas/spark-python-ds-static
Privilege EscalationVulnerability AnalysisExploitationPost-ExploitationPapers & ResearchRed TeamingPayload DevelopmentLabs & Practice
GitHubabraxas/spark-python-ds-static

spark-python-ds-static

Apache Spark 4.2.0 - 높음 - 원격 - 권한 잔여 - 프로세스 전역 Python 데이터 소스 맵

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

인기

모두 보기 →

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

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

Abraxas Labs - spark-python-ds-static

abraxaslabs.tech  ·  github.com/abraxas  ·  @abraxas_null  ·  [email protected]  ·  spark-python-ds-static

spark-python-ds-static

분류: 권한 잔여물 도달 범위: 원격

Apache Spark 4.2.0 (32f72996) - Apache Software Foundation

DataSourceManager.dataSourceBuilders는 JVM 전역의 선착순(first-wins) 맵이다. SPARK-45917은 조회 워커의 sys.path에서 pyspark_* Python 데이터 소스를 자동 등록한다. Connect 세션 격리는 아티팩트를 SparkFiles/<sessionUUID>/ 아래에 유지하며, 세션별 registerPython은 runtimeDataSourceBuilders에 남는다. 그러나 첫 조회는 여전히 트리거한 세션의 SparkFiles 디렉터리를 sys.path에 올리고, 모든 DefaultSource를 피클링하며, 그 클래스들을 컴패니언 객체에 캐시한다. 이후 Connect SQL(또는 Hive Thrift SQL)의 read.format(name) / USING name은 Python proto를 전송하지 않고 그 클래스를 Spark UID로 실행한다.

심는 쪽(planter)은 이미 Python이 허용된 Connect Python 테넌트다. 피해자는 동일한 Connect 드라이버에 있는 SQL 전용 테넌트다. Java 별칭(parquet, csv, json, orc, jdbc)은 Java ServiceLoader 경로에 남는다. 맵이 채워진 후의 이후 심기는 갱신되지 않는다. AC:H는 첫 조회에 더해 Java 별칭이 아닌 이름이라는 조건이다.

ID아직 CVE 없음
분류권한 잔여물 (Spark UID로서의 교차 세션 Python 데이터 소스, 인증 없는 작업 제출이 아님)
도달 범위원격 (공유 Spark Connect 드라이버)
CWECWE-269, CWE-502
CVSSHigh: 8.8 CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:C/C:H/I:H/A:H
제품Apache Spark
영향받는 버전4.2.0 (32f7299601108917fb01920a54e084595b7b3bf8) Python 데이터 소스 정적 레지스트리
인증Connect Python 테넌트(심는 쪽) 및 이후의 SQL 전용 Connect / Hive Thrift SQL 사용자(피해자)
라이선스GNU Affero GPL v3.0
랩127.0.0.1:18970 전용. 증거 파일. 컴패니언 맵의 가젯.

공격자가 할 수 있는 일

공유 드라이버에서 Spark Connect Python 세션을 유지한다. DefaultSource.name()이 존재하지 않는 커넥터 단축 이름(delta, iceberg, hudi, ...)인 pyfiles/pyspark_<name>.py를 심는다. 해당 세션에서 첫 Python 데이터 소스 조회를 트리거한다. 같은 JVM의 이후 모든 세션이 read.format(name) 또는 SQL USING name을 실행하면, 피클링된 클래스를 드라이버 플래너 워커와 익스큐터에서 Spark UID로 인스턴스화한다.

이것이 전체 권한 집합이다. 심는 쪽은 이미 Python을 실행한다. 잔여물이란 REGISTER_DATA_SOURCE / Python UDF proto를 전혀 전송한 적 없는 SQL 전용 테넌트가 여전히 그 클래스를 실행한다는 점이다.

무결성 (랩에서 입증됨)

방법싱크권한
심는 쪽: AddArtifacts 이름 pyfiles/pyspark_<name>.py 후 첫 format(name) / 조회컴패니언 DataSourceManager.dataSourceBuilders (DataSourceManager.scala 객체) 및 lookup_data_sources.py의 pyspark_* iter_modules트리거한 세션의 피클링된 DefaultSource를 JVM 전역으로 캐시. 랩: layer='static' trigger='attacker' first-wins=yes.
피해자: 심은 적 없는 세션에서 SQL USING <name> / spark.read.format(name)PythonDataSourceV2 createDataSourceInPython그 클래스를 Spark UID로 실행. 랩: planted_by='attacker' witness_written=True static-cross-session=yes. 오라클 파일에 SPARK-PYTHON-DS-STATIC-WITNESS가 담긴다.

이번 검증에서 닫힌 것 (랩에서 입증됨)

방법싱크결과
맵이 채워진 후 두 번째 이름을 이후에 심기동일한 정적 맵닫힘. 선착순. 랩: later-lookup found=False, 컴패니언에는 여전히 delta만 존재.
세션별 registerPython("alpha")runtimeDataSourceBuilders격리됨. 클론은 런타임만 복사. 랩: runtime-isolated=yes. 피해자의 alpha 읽기는 found=False.
Java 별칭 parquetJava DataSourceRegister ServiceLoader닫힘. 랩: java-alias-closed=yes layer='java'. csv/json/orc/jdbc도 동일.

추론됨 (동일한 싱크, 오라클은 아님)

방법싱크권한
심은 후 피해자의 USING드라이버 + 익스큐터 Python 워커Spark UID로서의 클러스터 전역 코드. 랩은 페이로드 대신 증거 파일을 기록한다.
동일 경로워커 크래시 / 스핀Spark UID로서의 가용성. High는 아님. High는 코드 실행이다.
공유 SparkSession에서의 Hive Thrift SQL USING동일한 정적 맵Thrift와 Connect가 드라이버 JVM을 공유하면 동일한 잔여물. 검증되지 않음.

이 잔여물이 부여하지 않는 것

  • 개방된 클러스터에서의 인증 없는 작업 제출. SECURITY.md FAQ. 설계상.
  • Java parquet / csv / json / orc / jdbc 하이재킹. ServiceLoader가 우선한다.
  • 아티팩트 경로 이탈 (concatenatePaths는 ..와 절대 이름을 거부한다).
  • 클라이언트 제공 pythonExec. Connect 플래너는 서버의 PYSPARK_PYTHON / python3을 사용한다.
  • registerPython의 교차 세션 유출. 런타임 맵은 DataSourceManager 인스턴스별이다.
  • 단일 세션의 단일 사용자 로컬 pyspark. 다른 테넌트가 없다.
  • 빈 맵을 채우는 미스 우선 조회. 이후 심기는 갱신되지 않는다 (AC:H).

발견 방법

apache/spark v4.2.0 (32f7299601108917fb01920a54e084595b7b3bf8)을 고정했다. 스물여덟 번의 소스 탐색. 사용자 코드를 실행하는 작업 제출은 설계상이다. History Jackson, UI 셸, PySpark 로컬 임퍼소네이션, 그리고 독립 실행형 RPC 수신 경로는 이번 검증에서 닫혀 있다. Connect 아티팩트는 pyfiles를 세션 UUID 아래에 격리한다. 런타임 registerPython은 세션별이다. 컴패니언 객체는 그렇지 않다.

SPARK-45917은 PYTHONPATH에서 pyspark_* 패키지를 자동 등록한다. 이는 운영자가 설치한 커넥터를 위한 의도된 동작이다. 잔여물이란 조회 워커가 트리거한 세션의 SparkFiles 디렉터리도 sys.path.insert하고(worker_util.setup_spark_files), 그런 다음 발견한 pyspark_* DefaultSource를 절대 갱신되지 않는 프로세스 전역 맵에 피클링한다는 점이다.

잘못된 방향: registerPython 격리를 전체 테넌트 장벽으로 간주한 것. 런타임은 격리된다. 정적은 그렇지 않다.

랩

cd lab
./run.sh

루프백 127.0.0.1:18970. Compose 프로젝트 spark-python-ds-static. 증거 SPARK-PYTHON-DS-STATIC-WITNESS. object DataSourceManager의 Python 가젯 및 세션별 런타임 맵. pyspark_delta.py를 공격자 SparkFiles에만 심는다. 공격자 조회가 컴패니언을 채운다. 이후 iceberg 심기는 갱신되지 않는다. 피해자의 delta 읽기가 오라클을 기록한다. registerPython("alpha")는 유출되지 않는다. Java parquet은 Java로 남는다.

마지막 줄:

SUCCESS SPARK-PYTHON-DS-STATIC static-cross-session=yes runtime-isolated=yes first-wins=yes java-alias-closed=yes SPARK-PYTHON-DS-STATIC-WITNESS

수정 방법

정적 맵을 채울 때 조회 워커 sys.path에 세션 SparkFiles를 올리지 말 것. 운영자 PYTHONPATH 패키지만 로드하라(설계된 대로의 SPARK-45917). 또는 아티팩트가 이미 그러하듯 정적 맵을 세션 / JobArtifactSet UUID로 키잉하라. 선착순 빈 채우기는 드라이버의 수명 동안 다른 테넌트의 클래스를 고정해서는 안 된다.

그때까지는, 드라이버 Python을 이미 신뢰하지 않는 한 Python 테넌트와 SQL 전용 테넌트 사이에 Connect 드라이버를 공유하지 말 것.

참고 자료

  • github.com/apache/spark 태그 v4.2.0 (32f7299601108917fb01920a54e084595b7b3bf8)
  • DataSourceManager.scala 컴패니언 dataSourceBuilders / initialStaticDataSourceBuilders
  • lookup_data_sources.py pyspark_* DefaultSource
  • worker_util.py setup_spark_files
  • PythonDataSourceV2.scala
  • SPARK-45917 자동 등록 (운영자 PYTHONPATH용으로 의도됨)

연락처

Abraxas Labs - abraxaslabs.tech - github.com/abraxas - @abraxas_null - [email protected]

도구 다운로드