
Apache Spark 4.2.0 - 高 - リモート - 権限の残存 - proxy-user defaultExtraClassPath
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · spark-proxyuser-classpath
クラス: 権限の残存 (CVE-2023-22946 / SPARK-41958 の残存) 到達性: リモート
Apache Spark 4.2.0 (32f72996) - Apache Software Foundation
CVE-2023-22946 / SPARK-41958 は依然として spark.submit.proxyUser.allowCustomClasspathInClusterMode をデフォルトで false にしており、--proxy-user クラスタサブミット時に childClasspath.clear() を実行し続けている。これは公開されている YARN の --jars パスである。その後 Spark 4.0 で spark.driver.defaultExtraClassPath が追加された。ランチャーは常にこのキーを spark-submit JVM の -cp の先頭に付加し、クラスタモードでも同様である。SPARK-41958 はこれを一切検知しない。
Livy スタイルのテナントは、ゲートウェイの spark-submit JVM 内でステージングされた jar を依然としてロードできる。Hadoop の UserGroupInformation.doAs はその Unix UID を変更しない。
| ID | CVE 未採番 |
| クラス | 権限の残存 (CVE-2023-22946 / SPARK-41958 の残存) |
| 到達性 | リモート (ゲートウェイ経由の Livy スタイル --proxy-user ジョブサブミット) |
| CWE | CWE-269, CWE-427 |
| CVSS | High: 8.8 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H |
| 製品 | Apache Spark |
| 影響を受けるバージョン | Apache Spark 4.2.0 (32f7299601108917fb01920a54e084595b7b3bf8) |
| 認証 | --conf とステージングされた --jars を spark-submit --proxy-user ... --deploy-mode cluster に転送する Livy / Kyuubi / Oozie スタイルのゲートウェイの認証済みテナント |
| ライセンス | GNU Affero GPL v3.0 |
| ラボ | 127.0.0.1:18950 のみ。Witness ファイル。引用されたランチャー / サブミットの walk のガジェット。 |
スーパーユーザー UID として spark-submit --proxy-user <tenant> --deploy-mode cluster を実行するマルチテナント Spark ゲートウェイ (Livy、Kyuubi、Oozie など) 上でテナントアカウントを保持する。ゲートウェイ JVM が開ける jar をステージングする。--conf spark.driver.defaultExtraClassPath=<staged jar> を送信する。SPARK-41958 のゲートは false のままでよい。構築された spark-submit -cp は依然としてその jar で始まる。その中のクラスはゲートウェイの Unix UID としてロードされる。
--conf spark.submit.proxyUser.allowCustomClasspathInClusterMode=true は第 2 の walk である: .internal() はドキュメント専用であり、--conf は依然としてキーを書き込み、YARN クラスタは --jars を childClasspath に保持する。公開 CVE-2023-22946 は、clear() が既にカバーしている YARN デフォルトの --jars パスのままである。この残存はゲートされていない defaultExtraClassPath である。
クリーンなサブミット後の Hadoop なりすましは、YARN AM / k8s ドライバにとって依然としてプロキシユーザーである。この残存はゲートウェイ JVM のみである。
| 手法 | シンク | 偵察 | 完全性 | 可用性 | 来歴 |
|---|---|---|---|---|---|
Livy スタイルのサブミット --proxy-user + yarn/k8s/standalone クラスタ + --conf spark.driver.defaultExtraClassPath=<staged local jar>、SPARK-41958 フラグは false のまま | SparkSubmitCommandBuilder.buildSparkSubmitCommand SparkSubmitCommandBuilder.java:317-327 -cp の先頭エントリ | ゲートウェイ UID が読めるファイルの一覧/読み取り (keytab ディレクトリ、spark-defaults、ローカルステージング)。以降の RPC の Hadoop アイデンティティは依然としてプロキシユーザー。 | spark-submit JVM 内でテナントクラスをロードする。Unix UID はゲートウェイ (Hadoop プロキシスーパーユーザー) のまま。ラボ: defaultExtraClassPath-on-cp=yes childClasspath-cleared=yes lab.WitnessMain が SPARK-PROXYUSER-CLASSPATH-WITNESS を書き込んだ。公開 CVE クラスからの推測: その UID としての Hadoop Configuration リソースオーバーレイ / FileSystem 実装ルックアップ。 | オーバーレイが例外を投げた場合、サブミット JVM がクラッシュする。クラスではない。 | 構築された -cp としてのラボ実証済みロード + witness 書き込み。Hadoop オーバーレイは推測。Livy/Kyuubi の --conf パススルーは推測 (それらのツリーはこのピンではない)。 |
同じサブミットで --conf spark.submit.proxyUser.allowCustomClasspathInClusterMode=true と --jars / プライマリリソースを併用 | SparkSubmit.prepareSubmitEnvironment SparkSubmit.scala:333-336,738-743,917-924 その後 runMain :980-987 | walk A と同じ偵察、システムローダーではなく子 URLClassLoader 上で。 | addJarToClasspath が実行されるように --jars を childClasspath に保持する。ラボ: conf-flag-keeps-jars=yes。 | 同じ。 | ラボ実証済みの childClasspath 保持。フラグが false のままのときに clear() がカバーする公開 YARN --jars パスの再申請ではない。 |
ラボ実証済み vs 推測: 構築された -cp はクラスタモードで defaultExtraClassPath を含む; childClasspath.clear() はデフォルトフラグで依然として実行される; spark.driver.extraClassPath はクラスタで省略される; フラグ false の --jars はクリアされる; その -cp 上の witness クラスがオラクルを書き込む。Hadoop 設定クラスの実行は公開 CVE-2023-22946 のメカニズムであり、ここでは再実行していない。Livy/Kyuubi が --conf を転送することは、それらのプロジェクトが文書化しているアーキテクチャである。
| 手法 | シンク | クローズのまま |
|---|---|---|
クラスタモードでの --driver-class-path / spark.driver.extraClassPath | SparkSubmitCommandBuilder.java:318-319 | spark-submit の -cp には追加されない。ラボ: extraClassPath-omitted=yes。YARN/K8s がプロキシユーザーとして起動するクラスタドライバに渡る。 |
デフォルトクラスタ + --proxy-user + --jars でフラグを反転せず defaultExtraClassPath もなし | SparkSubmit.scala:917-918 childClasspath.clear() | YARN/standalone/k8s クラスタの子クラスパスが空にされる。ラボ: コントロール walk で childClasspath-cleared=yes。公開 CVE-2023-22946 はこのパスのまま。 |
ゲートウェイ上の --proxy-user クライアントモードドライバ | docs/security.md Proxy User セクション | 文書化済み: クライアントモードドライバ JVM はスーパーユーザー。ベンダーは CVE ではないとしている。Livy/Kyuubi はクラスタモードを強制するよう指示されている。 |
K8s クラスタモードドライバコンテナ (spark.kubernetes.submitInDriver=true) がクラスパスに . を追加 | SparkSubmit.scala:420-431 SPARK-43540 | ドライバポッド内の 2 番目の spark-submit であり、Livy ホストではない。ポッド UID はコンテナユーザー。 |
クラスタモードでの spark.driver.extraJavaOptions | SparkSubmitCommandBuilder.java:341-357 | spark-submit JVM には適用されない。SPARK_SUBMIT_OPTS はゲートウェイ環境であり、テナントの --conf ではない。 |
| サブミットされたアプリの YARN AM / k8s ドライバ | クリーンなサブミット後の Hadoop なりすまし | クラスタ起動では依然としてプロキシユーザー。この残存はゲートウェイ JVM のみ。 |
| 未認証ジョブサブミット / Connect SQL / ML モデルロード | SECURITY.md FAQ / docs/ml-security.md | 設計による。この残存ではない。 |
Spark 4.2.0 (32f7299601108917fb01920a54e084595b7b3bf8) をピン留めし、SparkSubmit.submit / prepareSubmitEnvironment / runMain、SPARK-41958 フラグ、ランチャーの -cp ビルダーを walk した。公開 Medium は依然として --jars パスで成立する: デフォルトの allowCustomClasspathInClusterMode は false (package.scala:2849-2854) であり、クラスタ + proxy-user は依然として childClasspath をクリアする。--conf は依然としてその内部キーを書き込む (SparkSubmitArguments.scala:474-476)。別途、Spark 4.0.0 の spark.driver.defaultExtraClassPath はクラスタモードを含め常に spark-submit の -cp 上にある:
boolean isClientMode = isClientMode(config);
String extraClassPath = isClientMode ? config.get(SparkLauncher.DRIVER_EXTRA_CLASSPATH) : null;
String defaultExtraClassPath = config.get(SparkLauncher.DRIVER_DEFAULT_EXTRA_CLASS_PATH);
if (extraClassPath == null || extraClassPath.trim().isEmpty()) {
extraClassPath = defaultExtraClassPath;
} else {
extraClassPath += File.pathSeparator + defaultExtraClassPath;
}
List<String> cmd = buildJavaCommand(extraClassPath);
4.0.0 のキーは .internal() である (package.scala:80-85)。--conf は依然としてそれを書き込む (SparkSubmitCommandBuilder.java:572-576)。SPARK-41958 はこのパスを一切ゲートしなかった: jar は SparkSubmit が起動する前にシステムクラスローダー上にある。
既に記録済みの誤った道: 公開 CVE-2023-22946 の再申請 (clear() がカバーする YARN --jars walk); クライアントモードのドライバ・アズ・スーパーユーザーを CVE として扱うこと (security.md はそうではないとしている); Ivy spark.jars.ivySettings (別のガジェット); SPARK_DIST_CLASSPATH / SPARK_SUBMIT_OPTS (ゲートウェイ環境であり、テナントの --conf ではない); clear() 後のログ行 (既に空のバッファをログする)。劇場: リバースシェル。オラクルは、構築された -cp が lab.WitnessMain をロードしたときに書き込まれる witness 文字列である。