
Apache Spark 4.2.0 - 高 - リモート - 権限の残存 - スタンドアロンRESTがspark.authenticateを無視する
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · spark-rest-auth-bypass
クラス: 権限の取り残し 到達性: リモート
Apache Spark 4.2.0 (32f72996) - Apache Software Foundation
スタンドアロン Master REST はデフォルトで有効なポート 6066 で待ち受け、spark.authenticate を一切参照しない。CVE-2018-11770 は REST をデフォルトで無効にし、REST が有効な状態で RPC シークレットが設定されていればフェイルクローズドにすることを約束していた。このピンではその両方が覆されている。MASTER_REST_SERVER_ENABLED は createWithDefault(true) である。フィルタは MASTER_REST_SERVER_FILTERS のみで、デフォルトは Nil。認証されていない POST /v1/submissions/create が、攻撃者の main を Worker UID として実行する。Worker は _SPARK_AUTH_SECRET を注入するため、2018 年の「executor なしの driver」という制限は成立しない。
これは 11770 の取り残しであり、新たな CVE-2020-9480 RCE ではない。RPC 7077 は依然として AuthServerBootstrap をインストールする。spark.authenticate=false のクラスタでのジョブ投入は文書化されたデフォルトであり、このバグではない。
| ID | CVE 未採番 |
| クラス | 権限の取り残し (CVE-2018-11770 の取り残し) |
| 到達性 | リモート (スタンドアロン Master 6066 への未認証 HTTP) |
| CWE | CWE-306, CWE-287 |
| CVSS | High: 8.8 CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H |
| 製品 | Apache Spark |
| 影響範囲 | 4.2.0 (32f7299601108917fb01920a54e084595b7b3bf8) スタンドアロン Master REST |
| 認証 | REST にはなし。運用者は spark.authenticate=true を設定。REST はデフォルトのまま。 |
| ライセンス | GNU Affero GPL v3.0 |
| ラボ | 127.0.0.1:18900 のみ。公式 spark:4.2.0 イメージ。 |
私はタグ v4.2.0 をピン留めし、32f7299601108917fb01920a54e084595b7b3bf8 (2026-07-11, v4.2.0-rc6) を特定した。master ではない。4.3 RC でもない。
6066 のスタンドアロン Master REST に到達する。Authorization ヘッダはなし。spark.authenticate は有効。spark.master.rest.filters は未設定。少なくとも 1 つの Worker が稼働している。
| メソッド | シンク | 権限 |
|---|---|---|
未認証 POST /v1/submissions/create | RequestSubmitDriver (Master.scala:402-420) その後 Worker DriverWrapper の classForName(mainClass).main | 完全性 (ラボ実証済み): 攻撃者の mainClass を Worker UID として実行。ラボ: driver RUNNING、witness ファイル。 |
同じ create; Worker CommandUtils.buildLocalCommand | driver 環境変数 _SPARK_AUTH_SECRET | 完全性 (ラボ実証済み): driver が認証済み RPC クラスタに SASL 参加できる。ラボ: injected=yes。 |
未認証 GET /v1/submissions/status/{id} | RequestDriverStatus (Master.scala:489-503) | 偵察 (作成した id についてラボ実証済み): driver の状態 / worker ホスト。 |
未認証 GET /v1/submissions/readyz | RequestReadyz | 偵察 (ラボ実証済み): Master が STANDBY でない。 |
未認証 POST /v1/submissions/kill/{id} | RequestKillDriver (Master.scala:422-453) | 完全性 + 可用性 (推測): 別テナントのスタンドアロン driver を停止。同じ未認証サーブレット配線。未検証。 |
未認証 POST /v1/submissions/killall | RequestKillAllDrivers (Master.scala:455-478) | 可用性 (推測): 待機中/実行中のすべてのスタンドアロン driver を終了。未検証。 |
未認証 POST /v1/submissions/clear | RequestClearCompletedDriversAndApps | 完全性 (推測): 完了した driver/app の記録を削除。未検証。 |
ラボ実証済み vs 推測: create、シークレット注入、自身の id の status、readyz はラボ。kill / killall / clear は同じ未認証サーブレットマップからの推測。
必要条件: スタンドアロン Master (YARN/K8s ではない)。運用者が spark.authenticate=true を設定。REST はデフォルトのまま (spark.master.rest.enabled が true、spark.master.rest.filters 未設定)。Master 6066 へのネットワーク経路。少なくとも 1 つの Worker。文書化されたオープンクラスタ (spark.authenticate=false) ではない。
| 面 | 理由 |
|---|---|
spark.authenticate=true での RPC 7077 | AuthServerBootstrap が依然として必要。CVE-2020-9480 の受信パスは閉じたまま。新たな 9480 RCE ではない。 |
| 設定時の JWSFilter | spark.master.rest.filters=org.apache.spark.ui.JWSFilter と secretKey。JWT なしではテストは 403。オプトイン。デフォルトは Nil。 |
UI doAs | 依然として admin が必要。REST は UI フィルタを継承しない。 |
| CVE-2022-33891 UI シェル | id -Gn argv の取り残しはこのピンでは閉じている。 |
| YARN / Kubernetes 投入 | この REST サーバはスタンドアロン Master 専用。 |
デフォルト spark.authenticate=false のジョブ投入 | FAQ: 設計によるもの。この取り残しではない。 |
| Mesos REST | Spark 4.0 で削除。 |
CLI spark-submit のデフォルト | 依然として RPC 7077 を使用 (useRest は文字列デフォルトで false)。spark:// での --kill / --status は常に REST を使用。取り残しはサーバリスナの方。 |
CVE-2018-11770 のコード修正 (SPARK-25088) は、REST をデフォルトで無効にし、REST が有効な状態で spark.authenticate.secret が設定されていれば Master をフェイルクローズドにする require だった。このピンでは:
package.scala:2045-2048。ドキュメント: 「Spark 4.1 以降、Spark Master デーモンはデフォルトで REST API を提供する。」Master.scala から欠落。テスト SPARK-57451: Allows REST server and spark.authenticate.secret to be enabled together (MasterSuite.scala:253-261) は起動が成功しなければならないと主張している。NETWORK_AUTH_ENABLED / AUTH_SECRET を参照しない。addFilters は spark.master.rest.filters のみを適用し、デフォルトは Nil。CVE-2018-17190 / FAQ (「spark.authenticate を有効にせよ」) に従った運用者でも、6066 での未認証 HTTP ジョブ投入が残っている。
誤った道: オープンクラスタでの未認証ジョブ投入を CVE として扱うこと。これが RPC 7077 上の 9480 を再開させるという主張。JWSFilter のデフォルトオフを、spark.authenticate が REST にマッピングされないことではなく取り残しとして扱うこと。4.3 RC をピン留めすること。
茶番: リバースシェル。オラクルは witness 文字列と injected=yes。
python3 spark-rest-auth-bypass-Abraxas-Labs.py
または
cd lab
./run.sh
ループバック 127.0.0.1:18900 をコンテナの 6066 に公開。Compose プロジェクト spark-rest-auth-bypass。公式 spark:4.2.0 イメージ。Master と Worker の両方が spark.authenticate=true と spark.authenticate.secret を設定。REST フィルタは未設定。Witness SPARK-REST-AUTH-BYPASS-WITNESS。最終行:
SUCCESS SPARK-REST-AUTH-BYPASS create-http=200 success=true submissionId=driver-20261012231831-0000 injected=yes state=RUNNING SPARK-REST-AUTH-BYPASS-WITNESS