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

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

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

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

ツールディレクトリ

カテゴリ

すべてのカテゴリを見る
Loading categories
spark-rpc-stream-unauth — Apache Spark 4.2.0 - 高 - リモート - ファイル読み取り - 認証不要のRPC StreamRequestファイル結合 | Kitploit
ツール/GitHubGitHub/abraxas/spark-rpc-stream-unauth
脆弱性分析エクスプロイトウェブアプリケーション悪用情報収集ネットワークセキュリティペネトレーションテスト論文と研究ラボと実践
GitHubabraxas/spark-rpc-stream-unauth

spark-rpc-stream-unauth

Apache Spark 4.2.0 - 高 - リモート - ファイル読み取り - 認証不要のRPC StreamRequestファイル結合

リポジトリを見る
82日前未レビュー

人気

すべて見る →

コミュニティで最も使われているツールを見つけましょう。

すべてのツールを探索

ツールコレクションを閲覧

すべてのツールを見る →
共有

Abraxas Labs - spark-rpc-stream-unauth

abraxaslabs.tech  ·  github.com/abraxas  ·  @abraxas_null  ·  [email protected]  ·  spark-rpc-stream-unauth

spark-rpc-stream-unauth

クラス: 権限の取り残し / ファイル読み取り 到達範囲: リモート

Apache Spark 4.2.0 (32f72996) - Apache Software Foundation

CVE-2020-9480 は、RPC コントロールプレーン上の未認証の RequestSubmitDriver / RegisterApplication を塞いだ。AbstractAuthRpcHandler は receive() と receiveStream() をゲートする。しかし getStreamManager() はゲートしない。TransportRequestHandler は依然として SASL の前に StreamRequest をそのマネージャへディスパッチする。NettyStreamManager.openStream はルート配下に留まるチェックなしで new File(dir, fname) を実行する。

未認証の StreamRequest classes/../../path が Spark-UID のファイルを読み取る。 Unix の絶対パスの子は登録ディレクトリ配下に留まる(ラボでは 404)。files/ はマップ取得(404)。receive() / receiveStream() は 401 のまま。これは 9480 の RCE ではない。

IDCVE 未割当
クラス権限の取り残し / ファイル読み取り(CVE-2020-9480 のゲートされていない RPC データプレーンの取り残し)
到達範囲リモート(spark.authenticate=true のドライバ RpcEnv / ESS / BlockManager への未認証 TCP)
CWECWE-862, CWE-22
CVSSHigh: 7.5 CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
製品Apache Spark
影響を受けるバージョン4.2.0 (32f7299601108917fb01920a54e084595b7b3bf8)。オペレータが spark.authenticate=true を有効化していること。ホストファイル読み取りには登録ディレクトリ(spark.repl.class.outputDir の /classes および/または Connect の artifacts)が必要。
認証StreamRequest / getStreamManager() には不要
ライセンスGNU Affero GPL v3.0
ラボ127.0.0.1 のみ

攻撃者ができること

spark.authenticate=true と登録ディレクトリを持つ Spark RPC ポートへの TCP。共有シークレットは不要。spark.network.crypto.enabled も不要。トランスポートの StreamRequest(メッセージタイプ 6)を streamId classes/../../<path> で送信する。TransportRequestHandler.processStreamRequest は RpcHandler.receive を決して呼び出さない。代わりに getStreamManager().openStream を呼び出す。9480 のラッパーは本物のマネージャを返す。new File(dir, "../../oracle/secret") は REPL/アーティファクトルートの外へ正規化され、FileSegmentManagedBuffer として返ってくる。

これは Spark UID としてのホストファイル読み取りである。ジョブ投入ではない。RequestSubmitDriver ではない。シェルでもない。

機密性(ラボで実証済み)

手法シンク権限
未認証 StreamRequest classes/../../<path>NettyStreamManager.openStream の new File(dir, fname) の後 FileSegmentManagedBufferドライバが開ける Spark-UID ファイルを読み取る。ラボで実証済み: opened /opt/repl-classes/../../oracle/secret、正規化後 /oracle/secret、本文 SPARK-RPC-STREAM-UNAUTH-WITNESS、x-auth-gated=false、x-authenticated=false。
未認証 StreamRequest classes/hello.txt(ディレクトリ内コントロール)同じ結合、登録ディレクトリ配下に留まる実際に /classes 配下にあるファイルを読み取る。ラボで実証済み 200 IN-DIR-OK、witness なし。含まれる名前であっても SASL なしでファイルサーバが機能することを確認。

機密性(推測)

手法シンク権限
稼働中の ESS streamId に対する未認証 ChunkFetchRequest / StreamRequestOneForOneStreamManager.getChunk / openStream。client.getClientId() == null のとき checkAuthorization がスキップされる別アプリの進行中の shuffle / ディスク RDD バイトを読み取る。可用性: ドレインが curChunk を進める。稼働中の streamId が必要(ランダム開始、その後 +1)。ガジェットは稼働中の ESS と通信しなかった。
未認証 MergedBlockMetaRequestAbstractAuthRpcHandler.getMergedBlockMetaReqHandler() もゲートされていないESS がマージド shuffle を持つとき、選択した appId のマージド shuffle チャンクビットマップを読み取る。同じ null clientId スキップ。検証はしていない。

この取り残しで塞がれているもの(ラボで実証済み)

手法シンク塞がれたまま
未認証 StreamRequest classes//oracle/secret(Unix 絶対パスの子)new File(dir, "/oracle/secret")404。開かれるパスは /opt/repl-classes/oracle/secret。Unix の File は連結する。親を無視しない。絶対パスの子がルートを捨てるというハントの主張は Unix では誤り。
未認証 StreamRequest files//oracle/secretfiles マップ取得404。files/ と jars/ はベース名のルックアップであり、結合ではない。
未認証 receive() / OneWayMessageAbstractAuthRpcHandler.receive401 Unauthenticated call to receive(). x-auth-gated=true。
未認証 receiveStream() / UploadStreamAbstractAuthRpcHandler.receiveStream401 Unauthenticated call to receiveStream().
ラボのシークレットによる認証済み receiveStream()doAuthChallenge 後の同じゲート200 receiveStream-ok。シークレットが依然として 9480 パスを開くことのコントロール。

ラボで実証済み vs 推測: 未認証 .. ファイル読み取り、Unix 絶対パス 404、files/ 404、ゲートされた receive / receiveStream はラボ。ESS shuffle ドレインは推測。

隣接する塞がれたもの(誇張しないこと):

  • CVE-2020-9480 RCE の道: OneWayMessage / UploadStream / RpcRequest 経由の未認証 RequestSubmitDriver / RegisterApplication。依然として共有シークレットが必要。
  • デフォルト spark.authenticate=false での未認証 shuffle とジョブ投入(SECURITY.md FAQ、信頼ネットワークのデフォルトとして文書化)。この取り残しではない。
  • 認証済みアプリ A がアプリ B を取得(AppIsolationSuite / SPARK-57889 の非 null clientId)。
  • CVE-2021-38296 ハンドシェイク鍵回復。
  • CVE-2025-55039 Moderate CTR デフォルト。
  • スタンドアロン master RpcEnv は通常 /classes や artifacts を登録していないため、このホストファイル探索はドライバ / REPL / Connect であり、master:7077 ではない。
  • ファイルを実行しない。書き込まない。spark.authenticate.secret をダンプしない。

発見の経緯

私は apache/spark v4.2.0 (32f7299601108917fb01920a54e084595b7b3bf8) をピン留めした。master でも 4.3 RC でもない。28 回のソースハント。オープンクラスタでのジョブ投入は設計通り。ML モデルロードは実行可能コード。公開されている Jackson History RCE、UI id -Gn シェル、PySpark ローカルなりすまし、9480 の receive パスはこの剥離では塞がれている。

RPC 認証のハントは 9480 の再ファイルチェックのはずだった。AuthServerBootstrap は依然としてハンドラをラップしている。未認証 receive は依然として例外を投げる。そこで私は getStreamManager() を読んだ。3 行。デリゲートを返す。TransportRequestHandler.handle は StreamRequest を receive を迂回してルーティングする。デフォルトの StreamManager.checkAuthorization は no-op。SPARK-57889 は StreamRequest に文字列 ID チェックを追加し、ESS が「認証オフ」に使う null clientId スキップを残した。それは「この接続は一度も認証していない」でもある。

SparkContext は spark.repl.class.outputDir が設定されているとき /classes を登録する。Connect の ArtifactManager は artifacts を登録する。NettyStreamManager.openStream は ftype/fname を分割する。files/jars 以外のタイプは正規化プレフィックスチェックなしで new File(dir, fname) を実行する。

記録に残す誤った道。ハントの自信を一日無駄にしたからだ。JavaDoc は絶対パスの子が親を無視すると述べている。Unix では UnixFileSystem.resolve は連結する。new File("/opt/repl-classes", "/oracle/secret") は /opt/repl-classes/oracle/secret になる。ラボでは 404。High の道は classes/../../oracle/secret である。

茶番: これを 9480 RCE だと主張すること。コントロールプレーンは依然としてゲートされている。オラクルは Spark UID がすでに読めるファイル内の witness 文字列にすぎない。

ラボ

ピン留めソースのガジェット(AbstractAuthRpcHandler.java:52-87、NettyStreamManager.scala:54-70)。HTTP は TransportRequestHandler の代用: /stream?id= は StreamRequest、POST /rpc/receive は OneWayMessage、POST /rpc/receive-stream は UploadStream。公式の spark:4.2.0 は不要。ループバックのみ。

python3 spark-rpc-stream-unauth-Abraxas-Labs.py

または:

cd lab
./run.sh

ループバック 127.0.0.1:18910。Compose プロジェクト spark-rpc-stream-unauth。witness SPARK-RPC-STREAM-UNAUTH-WITNESS は /oracle/secret 内。登録ディレクトリ /opt/repl-classes に hello.txt = IN-DIR-OK。最終行:

SUCCESS SPARK-RPC-STREAM-UNAUTH SPARK-RPC-STREAM-UNAUTH-WITNESS

修正

isAuthenticated まで getStreamManager()(および getMergedBlockMetaReqHandler())をゲートするか、拒否するマネージャを返す。NettyStreamManager.openStream では、getCanonicalFile 後に登録ディレクトリを離れる fname を拒否する。ESS では、spark.authenticate がオンのとき null clientId を未認証として扱う。SPARK-57889 はすでに StreamRequest で checkAuthorization を呼び出している。スキップが取り残しである。

それまでは、Spark UID のファイルをすでに信頼していない誰からでも TCP ポートに到達できる RpcEnv に /classes や artifacts を登録しないこと。spark.authenticate=true はこのデータプレーンを塞がない。

参考文献

ツールをダウンロード