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

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

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

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

ツールディレクトリ

カテゴリ

すべてのカテゴリを見る
Loading categories
spark-history-zip-symlink — Apache Spark 4.2.0 - 高 - リモート - ファイル読み取り - History zip が仕込まれたシンボリックリンクを追跡 | Kitploit
ツール/GitHubGitHub/abraxas/spark-history-zip-symlink
脆弱性分析エクスプロイトウェブアプリケーション悪用情報収集ペネトレーションテスト論文と研究
GitHubabraxas/spark-history-zip-symlink

spark-history-zip-symlink

Apache Spark 4.2.0 - 高 - リモート - ファイル読み取り - History zip が仕込まれたシンボリックリンクを追跡

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

人気

すべて見る →

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

すべてのツールを探索

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

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

Abraxas Labs - spark-history-zip-symlink

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

spark-history-zip-symlink

クラス: ファイル読み取り 到達範囲: リモート

Apache Spark 4.2.0 (32f72996) - Apache Software Foundation

CVE-2025-54920 により History Server の Jackson はロックダウンされ、sparkEventFromJson は SparkListenerEvent のサブクラスのみを構築するようになった。しかし、ローリング zipEventLogFiles は依然としてすべての listStatus の子を FileSystem.open 経由でダンプする。LocalFileSystem は POSIX シンボリックリンクを追跡する。eventlog_v2_* に仕込まれた子は、認証不要の GET /api/v1/applications/{id}/logs にパックされる。zip メンバーの本体は SHS-UID のターゲットである。エントリ名はシンボリックリンクのベース名である。

これは Jackson RCE の再提出ではない。Jackson は閉じられたままである。これはホスト RCE ではない。完全性と可用性への影響はない。

IDCVE 未割当
クラスファイル読み取り (CVE-2025-54920 の被害者モデルにおけるローリング zip の残存物)
到達範囲リモート (History ログディレクトリへの書き込み権限保持者、および zip の認証不要 GET)
CWECWE-59, CWE-22
CVSSHigh: 7.5 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N
製品Apache Spark
影響を受けるバージョン4.2.0 タグ v4.2.0 (32f7299601108917fb01920a54e084595b7b3bf8)
認証PR:L = spark.history.fs.logDirectory への書き込み (54920 と同じ被害者)。History UI の ACL はデフォルトで無効。
ライセンスGNU Affero GPL v3.0
ラボ127.0.0.1:18980 のみ

攻撃者ができること

spark.history.fs.logDirectory (デフォルト file:/tmp/spark-events) に書き込める者は、History Server が zip 化するローリングディレクトリを仕込むことができる。ローリングライターはデフォルトで有効。History UI の ACL はデフォルトで無効。SHS プロセスの UID が confused deputy となる。

権限メソッド / シンクラボ実証済みまたは推測
機密性: SHS UID が開けるホストファイルの読み取り有効な appstatus_* と events_* JSON (SparkListenerLogStart / SparkListenerApplicationStart) を含む eventlog_v2_<id>/ を仕込み、さらにログディレクトリ外をターゲットとするシンボリックリンクの子を配置する。スキャンを待つ。認証不要の GET /api/v1/applications/{id}/logs (OneApplicationResource.getEventLogs -> FsHistoryProvider.writeEventLogs -> RollingEventLogFilesFileReader.zipEventLogFiles -> FileSystem.open)ラボ実証済み。zip メンバー eventlog_v2_app-2026-0001/planted-secret の本体は SPARK-HISTORY-ZIP-SYMLINK-WITNESS。events メンバーには witness がない。エントリ名はターゲットパスではなく、シンボリックリンクのベース名のままである。
機密性: 攻撃者が open できない (660) 兄弟テナントのイベントログ同じ zip、シンボリックリンクのターゲットは別アプリのログ推測。同じ FileSystem.open。未検証。
機密性: keytab、spark-env.sh、SHS が読める場合は /etc/passwd同じ zip推測。オラクルは専用の /secret/host-secret であり、これらのファイルではない。
SHS またはホストファイルの完全性zip は HTTP ボディに読み込まれる閉じている。ラボ実証で影響なし。
SHS またはホストファイルの可用性zip はターゲットを削除または切り詰めない閉じている。ラボ実証で影響なし。
ホスト RCE / Jackson ガジェット構築JsonProtocol.sparkEventFromJson閉じている。SparkListenerEvent が必須。このラボは無害な Event JSON のみを仕込む。
エントリ名内の ../ による zip slipPath.getName()閉じている。POSIX ファイル名に / は含められない。エントリは eventlog_v2_<id>/<basename>。
resolveLogPath のパス文字列エスケープnew Path(logDir, attempt.logPath)閉じている。Path オブジェクトは設定されたログディレクトリ配下に留まる。エスケープは inode である。
ターゲットのコンパクション書き換え / クリーナー削除spark.history.fs.eventLog.rolling.maxFilesToRetain デフォルト Integer.MAX_VALUE、クリーナーはデフォルト無効閉じている。シンボリックリンクに対するローカル fs.delete はリンクを unlink するのであり、ターゲットではない。
認証不要のジョブ投入 / ML モデルロードSECURITY.md FAQ / docs/ml-security.md閉じている。設計上、この残存物ではない。

発見の経緯

master や 4.3 RC ではなく、apache/spark v4.2.0 (32f7299601108917fb01920a54e084595b7b3bf8) に固定した。28 回の調査。Jackson History RCE はこのピールでは閉じている (JsonProtocol.scala:965-972)。History Server は依然として攻撃者が書き込めるログディレクトリを指しており、これは CVE-2025-54920 と同じ被害者モデルである。

zipEventLogFiles はイベントファイルだけでなく、すべての files を zip 化する:

override def zipEventLogFiles(zipStream: ZipOutputStream): Unit = {
  val dirEntryName = rootPath.getName + "/"
  zipStream.putNextEntry(new ZipEntry(dirEntryName))
  files.foreach { file =>
    addFileAsZipEntry(zipStream, file.getPath, dirEntryName + file.getPath.getName)
  }
}

addFileAsZipEntry は fileSystem.open してから transferTo する。LocalFileSystem は POSIX シンボリックリンクを追跡する。getLogDirInfo は「シンボリックリンクを適切に処理する」とコメントしつつ、表示名のために未解決の Path 親をたどる。

すでに記録済みの誤った道: SPARK-52381 を History の話のすべてとして扱うこと、witness を events_* に仕込むこと (ラボはこれを失敗させる)、zip エントリがターゲットパスを運ぶと期待すること、resolveLogPath のプレフィックス結合をエスケープとみなすこと、このピンで HiveConnection Event クラスを試すこと。

ラボ

python3 spark-history-zip-symlink-Abraxas-Labs.py

または

cd lab
./run.sh

EventLogFileReaders.scala のローリング zip ダンプのガジェットであり、完全な History Server でも公式の spark:4.2.0 イメージでもない。Event JSON を Jackson 経由でパースしない。ループバック 127.0.0.1:18980。Compose プロジェクト spark-history-zip-symlink。ローリングディレクトリは有効な appstatus_* + events_* (witness なし) と、planted-secret -> /secret/host-secret を保持する。

SUCCESS SPARK-HISTORY-ZIP-SYMLINK SPARK-HISTORY-ZIP-SYMLINK-WITNESS

修正

すべての listStatus 名ではなく、events_* / appstatus_* の子のみをパックすること。no-follow (O_NOFOLLOW / Hadoop の no-symlink オプション) で開き、realpath が spark.history.fs.logDirectory の外にある子を拒否すること。表示名ヘルパーは realpath チェックではない。

参考資料

  • github.com/apache/spark タグ v4.2.0 (32f7299601108917fb01920a54e084595b7b3bf8)
  • EventLogFileReaders.scala (addFileAsZipEntry ~48-56, zipEventLogFiles ~267-272)
  • FsHistoryProvider.scala (writeEventLogs ~831-856, resolveLogPath ~866-896)
  • OneApplicationResource.scala (GET .../logs ~128-165)
  • JsonProtocol.scala (sparkEventFromJson ~965-972, Jackson ロック)
  • 近傍でパッチ済み (Jackson 構築、この inode ウォークではない): CVE-2025-54920 / SPARK-52381
  • CWE-59 · CWE-22

ライセンス

GNU Affero GPL v3.0。LICENSE を参照。ループバックラボのみ。無保証。

ツールをダウンロード