
Apache Spark 4.2.0 - 高 - リモート - ファイル書き込み - Connect セッション SET copyFromLocalToFs.allowDestLocal
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · spark-connect-copy-local
解説記事: https://abraxaslabs.tech/research/spark-connect-copy-local
分類: ファイル書き込み (SPARK-58531 の残存; 4.3.0 のみで static) 到達性: リモート
Apache Spark 4.2.0 (32f72996) - Apache Software Foundation
spark.sql.artifact.copyFromLocalToFs.allowDestLocal は、このピンでは依然として buildConf (セッションで設定可能) です。SPARK-58531 により、4.3.0 で StaticSQLConf に移動されました。Connect セッションはテスト専用のローカル宛先ゲートを SET でき、その後 copyFromLocalToFs / AddArtifacts の forward_to_fs/<abs> が Spark UID としてドライバーローカルのパスを上書きします。
Connect セッションで SET した後、forward_to_fs がドライバーローカルのファイルを書き込みます。宛先は LocalFileSystem である必要があります。RCE ではありません。
| ID | CVE 未割当 (SPARK-58531 の残存) |
| 分類 | ファイル書き込み (SPARK-58531 の残存; 4.3.0 のみで static) |
| 到達性 | リモート (Spark Connect Config + AddArtifacts) |
| CWE | CWE-22, CWE-732 |
| CVSS | High: 8.1 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:H |
| 製品 | Apache Spark (ASF) |
| 影響範囲 | Apache Spark 4.2.0 (32f7299601108917fb01920a54e084595b7b3bf8)。4.3.0 は static。 |
| 認証 | ConfigRequest.SET と AddArtifacts を実行できる Connect クライアント。デフォルトの Connect には PSK がありません。 |
| ライセンス | GNU Affero GPL v3.0 |
| ラボ | 127.0.0.1:18920 のみ |
gRPC に到達できる Spark Connect クライアント (デフォルトのバインドポートは 15002、オペレーターが spark.connect.authenticate.token を設定していない限り PSK なし) は、ドライバーが起動時に有効にしていたテスト専用ゲートをオフにし、その後 Spark UID としてドライバー上の任意のローカルパスを上書きできます。
| 手法 | シンク | 権限 |
|---|---|---|
gRPC Config SET spark.sql.artifact.copyFromLocalToFs.allowDestLocal=true (または SQL SET) | SparkConnectConfigHandler.handleSet -> RuntimeConfig.set -> SQLConf.setConfString | 整合性 (セッション設定、ラボで実証): セッションごとのローカル宛先ゲートを反転させます。それ自体ではファイルを書き込みません。他のセッションには影響しません。ラボ: SET HTTP 200、modifiable=True。 |
gRPC AddArtifacts の名前 forward_to_fs + 絶対宛先、CRC 正常 | ArtifactManager.uploadArtifactToFs -> LocalFileSystem.copyFromLocalFile(delSrc=false, overwrite=true) | 整合性 (ファイル上書き、ラボで実証): artifactRootDirectory/<sessionUUID>/ の外にあるドライバーローカルのパスを Spark UID として書き込み/上書きします。ラボ: 宛先 /oracle/SPARK-CONNECT-COPY-LOCAL-WITNESS、uid 185、内容 WITNESS。 |
| 同じ AddArtifacts を HDFS/S3/ABFS の宛先に対して実行 | ドキュメント化された copyFromLocalToFs | 整合性 (クラスタ FS、設計通り): この残存ではありません。LocalFileSystem でない宛先はテストフラグを参照しません。 |
ラボで実証済み vs 推測: buildConf キーのセッション SET、続いてアーティファクトサンドボックス外への uid 185 としての LocalFileSystem 宛先書き込みはラボで実証済みです。プロセスが書き込み可能なパス (ドライバーの作業ディレクトリ、全員書き込み可能なドロップ先、オペレーターが後で実行する既存の実行可能スクリプト) の Spark UID による上書きは推測です。RIP 制御はありません。ファイル書き込みを RCE に誇張しないでください。
必要条件: Spark Connect がリッスンしていること。セッション SQL conf を SET でき、AddArtifacts が可能なクライアント。dest は Hadoop の LocalFileSystem でなければならない。デフォルトの Connect には PSK がない。オペレーターがトークンを設定した場合、この残存経路でもその共有 Bearer が必要となる。これはローカル dest 制御のバイパスであり、PSK のバイパスではない。
| サーフェス | ラボ |
|---|---|
| SET なしのコピー | 400 _LEGACY_ERROR_TEMP_3161、dest は存在しない |
旧静的設定 spark.connect.copyFromLocalToFs.allowDestLocal の SET | 400 CANNOT_MODIFY_STATIC_CONFIG |
アーティファクト名 .. / 絶対ステージング (ArtifactUtils.concatenatePaths) | INVALID_ARTIFACT_PATH |
forward_to_fs 以外のアーティファクト | artifactRootDirectory/<sessionUUID>/ 配下に留まる |
| フラグなしの HDFS/クラウド dest | 文書化された API であり、この残存経路ではない |
オープンな Connect 上の未認証 SQL / Python UDF / Scala UdfPacket | ベンダー FAQ のジョブ投入、DROP |
| SPARK-52122 ML DefaultParamsReader | このピンでは allowlist + safeMLClassLoader |
シェルなし。ヒープダンプなし。Connect PSK のスキップなし。dest は依然として LocalFileSystem でなければならない。書き込みは root ではなく Spark UID として行われる。
uploadArtifactToFs は、テスト用フラグが有効でない限り LocalFileSystem の dest を拒否し、そうでなければユーザーがドライバー上の任意のファイルを上書きしてしまうという明示的なコメントを添えている:
if (fs.isInstanceOf[LocalFileSystem]) {
val allowDestLocalConf =
session.sessionState.conf.getConf(SQLConf.ARTIFACT_COPY_FROM_LOCAL_TO_FS_ALLOW_DEST_LOCAL)
.getOrElse(
session.conf.get("spark.connect.copyFromLocalToFs.allowDestLocal").contains("true"))
if (!allowDestLocalConf) {
throw new SparkUnsupportedOperationException("_LEGACY_ERROR_TEMP_3161")
}
}
fs.copyFromLocalFile(false, true, new FSPath(localPath.toString), destFSPath)
3.5 のキーは静的で、デフォルトは false です。4.0 での置き換えはオプションの buildConf です:
val ARTIFACT_COPY_FROM_LOCAL_TO_FS_ALLOW_DEST_LOCAL =
buildConf("spark.sql.artifact.copyFromLocalToFs.allowDestLocal")
.internal()
...
.booleanConf
.createOptional
buildConf は registerStaticConfigKey を呼び出しません。isModifiable は containsConfigKey && !isStaticConfigKey です。RuntimeConfig.set は静的キーのみを拒否します。内部設定は依然として設定可能です。SET の後、getConf(ARTIFACT_...) は Some(true) を返し、静的で古い conf への getOrElse フォールバックはスキップされます。
SPARK-58531 / PR 57730「spark.sql.artifact.copyFromLocalToFs.allowDestLocal を静的 conf に変換する」は 2026-08-05 に解決済み、Fix Version 4.3.0。JIRA: この conf は「呼び出し元がドライバのローカルファイルシステム上の任意のパスに書き込めるかどうかを制御するため、ドライバを起動する側が設定することを意図している」。4.2.0 が Affects に記載されています。このピンには依然としてランタイム conf が含まれています。
既に記録済みの誤った道筋: Connect SQL を所見として扱うこと(FAQ); 古い静的キーの SET(CANNOT_MODIFY_STATIC_CONFIG); Unix の絶対パス dest が親を無視すると主張すること(実際は root 配下に結合される); File 書き込みを RCE に誇張すること; JIRA が解決済みであることを理由に 4.3.0 RC をピン留めすること。
cd lab
./run.sh
ループバック 127.0.0.1:18920。session-conf ゲートのガジェットと LocalFileSystem 宛先コピー(pin v4.2.0 32f72996)。サーバー UID 185。SET なしの制御: 400 _LEGACY_ERROR_TEMP_3161、宛先は存在しない。静的旧キーの SET 制御: CANNOT_MODIFY_STATIC_CONFIG。buildConf キーのセッション SET 後にコピー: 宛先 /oracle/SPARK-CONNECT-COPY-LOCAL-WITNESS は /opt/spark/work/artifacts/<sessionUUID>/ の外、uid 185、内容 WITNESS。
health pin=v4.2.0 commit=32f7299601108917fb01920a54e084595b7b3bf8
server uid=185 artifact_root=/opt/spark/work/artifacts/<sessionUUID>
control-no-set status=400 condition=_LEGACY_ERROR_TEMP_3161
control-no-set dest-absent=yes
control-static-set status=400 error_class=CANNOT_MODIFY_STATIC_CONFIG
session-set status=200 modifiable=True
copy-after-set status=200 dest=/oracle/SPARK-CONNECT-COPY-LOCAL-WITNESS
oracle dest=/oracle/SPARK-CONNECT-COPY-LOCAL-WITNESS uid=185 outside-sandbox=yes content=SPARK-CONNECT-COPY-LOCAL-WITNESS
SUCCESS SPARK-CONNECT-COPY-LOCAL SPARK-CONNECT-COPY-LOCAL-WITNESS
spark.sql.artifact.copyFromLocalToFs.allowDestLocal を StaticSQLConf に移動し、セッションから SET できないようにします。これが 4.3.0 における SPARK-58531 / PR 57730 です。運用者が 4.3.0 を実行できるようになるまでは、トークンとネットワーク ACL なしで Connect を公開せず、ドライバがこのフラグを未設定で起動されたという理由だけでテスト用フラグがオフになっていると見なさないでください。