Skip to content
KitploitKITPLOIT
ツールエクスプロイトブログ
Log in
提出
ツールエクスプロイトブログ
提出

ハッキング、侵入テスト、サイバーセキュリティツールをあなたのセキュリティアーセナルに!

Kitploitはハッキング、サイバーセキュリティ、ペネトレーションテストのツールディレクトリです。最新のプロジェクトアップデートを見つけて、脆弱性の発見、システム分析、テストの自動化、セキュリティの強化を行いましょう。

フィードお問い合わせプライバシー© 2026 Kitploit

ツールディレクトリ

カテゴリ

すべてのカテゴリを見る
Loading categories
ツール/GitHubGitHub/abraxas/spark-python-ds-static
特権昇格脆弱性分析エクスプロイトポストエクスプロイト論文と研究レッドチーミングペイロード開発ラボと実践
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 グローバルな先勝ちマップである。SPARK-45917 はルックアップワーカーの sys.path から pyspark_* Python データソースを自動登録する。Connect のセッション分離によりアーティファクトは SparkFiles/<sessionUUID>/ 配下に保たれ、セッションごとの registerPython は runtimeDataSourceBuilders に留まる。しかし最初のルックアップは依然としてトリガーしたセッションの SparkFiles ディレクトリを sys.path に追加し、すべての DefaultSource を pickle 化し、それらのクラスをコンパニオンオブジェクトにキャッシュする。その後の Connect SQL(または Hive Thrift SQL)の read.format(name) / USING name は、Python proto を送ることなくそのクラスを Spark UID として実行する。

仕掛け人は、すでに Python を許可されている Connect Python テナントである。被害者は、同じ Connect ドライバー上の SQL 専用テナントである。Java エイリアス(parquet、csv、json、orc、jdbc)は Java の ServiceLoader パスに留まる。マップが埋まった後の後からの仕掛けはリフレッシュされない。AC:H は最初のルックアップと、Java エイリアスではない名前による。

IDCVE はまだなし
クラス特権の残留(クロスセッションの Python データソースを Spark UID として。未認証のジョブ投入ではない)
到達範囲リモート(共有 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 を行うと、pickle 化されたクラスをドライバープランナーワーカー上およびエグゼキュータ上で 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トリガーしたセッションの pickle 化された 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 を保持する。

この検証で塞がれているもの(ラボで実証済み)

手法シンク結果
マップが埋まった後に2つ目の名前を後から仕掛ける同じ静的マップ塞がれている。先勝ち。ラボ: 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) をピン留めした。28回のソース探索。ユーザーコードを実行するジョブ投入は設計によるもの。History Jackson、UI シェル、PySpark ローカルなりすまし、スタンドアロン RPC 受信パスはこの剥離では塞がれている。Connect アーティファクトは pyfiles をセッション UUID 配下に分離する。ランタイムの registerPython はセッションごとである。コンパニオンオブジェクトはそうではない。

SPARK-45917 は PYTHONPATH から pyspark_* パッケージを自動登録する。これはオペレーターがインストールしたコネクタ向けに意図されたものである。残留とは、ルックアップワーカーがトリガーしたセッションの SparkFiles ディレクトリも sys.path.insert し(worker_util.setup_spark_files)、その後見つけた pyspark_* DefaultSource を、決してリフレッシュされないプロセスグローバルマップに pickle 化することである。

誤った方向: 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 の read がオラクルを書き込む。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

修正

静的マップを埋めるときに、セッションの SparkFiles をルックアップワーカーの sys.path に置かないこと。オペレーターの 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]

ツールをダウンロード