
Apache Spark 4.2.0 - Hoch - Remote - Dateischreiben - Connect-Sitzung SET copyFromLocalToFs.allowDestLocal
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · spark-connect-copy-local
Klasse: Dateischreiben (Überbleibsel von SPARK-58531; nur auf 4.3.0 statisch) Reichweite: Remote
Apache Spark 4.2.0 (32f72996) - Apache Software Foundation
spark.sql.artifact.copyFromLocalToFs.allowDestLocal ist bei diesem Pin noch buildConf (pro Sitzung setzbar). SPARK-58531 hat es in 4.3.0 zu StaticSQLConf verschoben. Eine Connect-Sitzung kann das nur für Tests gedachte Local-Dest-Gate per SET setzen, danach überschreibt copyFromLocalToFs / AddArtifacts forward_to_fs/<abs> einen treiberlokalen Pfad als Spark-UID.
Connect-Sitzung SET, dann schreibt forward_to_fs treiberlokale Dateien. Ziel muss LocalFileSystem sein. Kein RCE.
| ID | noch keine CVE (Überbleibsel von SPARK-58531) |
| Klasse | Dateischreiben (Überbleibsel von SPARK-58531; nur auf 4.3.0 statisch) |
| Reichweite | Remote (Spark Connect Config + AddArtifacts) |
| CWE | CWE-22, CWE-732 |
| CVSS | Hoch: 8.1 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:H |
| Produkt | Apache Spark (ASF) |
| Betroffen | Apache Spark 4.2.0 (32f7299601108917fb01920a54e084595b7b3bf8). 4.3.0 ist statisch. |
| Auth | Connect-Client, der ConfigRequest.SET und AddArtifacts ausführen kann. Standard-Connect hat kein PSK. |
| Lizenz | GNU Affero GPL v3.0 |
| Lab | nur 127.0.0.1:18920 |
Ein Spark-Connect-Client, der gRPC erreichen kann (Standard-Bind-Port 15002, kein PSK, sofern der Betreiber nicht spark.connect.authenticate.token gesetzt hat), kann ein nur für Tests gedachtes Gate, mit dem der Treiber gestartet wurde, ausschalten und dann einen gewählten lokalen Pfad auf dem Treiber als Spark-UID überschreiben.
| Methode | Sink | Privileg |
|---|---|---|
gRPC Config SET spark.sql.artifact.copyFromLocalToFs.allowDestLocal=true (oder SQL SET) | SparkConnectConfigHandler.handleSet -> RuntimeConfig.set -> SQLConf.setConfString | Integrität (Sitzungskonfiguration, im Lab nachgewiesen): schaltet das Local-Dest-Gate der jeweiligen Sitzung um. Schreibt für sich genommen keine Datei. Ändert keine anderen Sitzungen. Lab: SET HTTP 200, modifiable=True. |
gRPC AddArtifacts Name forward_to_fs + absolutes Ziel, CRC ok | ArtifactManager.uploadArtifactToFs -> LocalFileSystem.copyFromLocalFile(delSrc=false, overwrite=true) | Integrität (Dateiüberschreiben, im Lab nachgewiesen): Schreiben/Überschreiben eines treiberlokalen Pfads als Spark-UID, außerhalb von artifactRootDirectory/<sessionUUID>/. Lab: Ziel /oracle/SPARK-CONNECT-COPY-LOCAL-WITNESS, uid 185, Inhalt WITNESS. |
| Dasselbe AddArtifacts auf HDFS/S3/ABFS-Ziel | dokumentiertes copyFromLocalToFs | Integrität (Cluster-FS, by design): nicht dieses Überbleibsel. Ein Ziel, das nicht LocalFileSystem ist, konsultiert das Test-Flag nie. |
Im Lab nachgewiesen vs. abgeleitet: das Sitzungs-SET des buildConf-Schlüssels, dann der LocalFileSystem-Zielschreibvorgang als uid 185 außerhalb der Artefakt-Sandbox, ist im Lab nachgewiesen. Das Überschreiben eines Pfads durch die Spark-UID, den der Prozess schreiben kann (Treiber-Arbeitsverzeichnis, ein weltweit beschreibbarer Drop, ein bereits ausführbares Skript, das der Betreiber später ausführt), ist abgeleitet. Keine RIP-Kontrolle. Dateischreiben nicht zu RCE aufblähen.
Erfordert: Spark Connect lauscht. Client, der die SQL-Konfiguration der Sitzung per SET setzen und AddArtifacts ausführen kann. Ziel muss Hadoop LocalFileSystem sein. Standard-Connect hat kein PSK; wenn der Betreiber ein Token gesetzt hat, benötigt das Überbleibsel trotzdem diesen gemeinsamen Bearer. Es ist eine Umgehung der Local-Dest-Kontrolle, keine PSK-Umgehung.
| Angriffsfläche | Lab |
|---|---|
| Kopieren ohne SET | 400 _LEGACY_ERROR_TEMP_3161, Ziel fehlt |
SET des alten statischen spark.connect.copyFromLocalToFs.allowDestLocal | 400 CANNOT_MODIFY_STATIC_CONFIG |
Artefaktname .. / absolutes Staging (ArtifactUtils.concatenatePaths) | INVALID_ARTIFACT_PATH |
Nicht-forward_to_fs-Artefakte | bleiben unter artifactRootDirectory/<sessionUUID>/ |
| HDFS/Cloud-Ziel ohne das Flag | dokumentierte API, nicht dieses Überbleibsel |
Unauth SQL / Python UDF / Scala UdfPacket auf offenem Connect | Vendor-FAQ Job-Submit; DROP |
| SPARK-52122 ML DefaultParamsReader | Allowlist + safeMLClassLoader bei diesem Pin |
Keine Shell. Kein Heap-Dump. Kein Connect-PSK-Skip. Das Ziel muss trotzdem LocalFileSystem sein. Der Schreibvorgang erfolgt als Spark-UID, nicht als root.
uploadArtifactToFs verweigert ein LocalFileSystem-Ziel, sofern das Test-Flag nicht aktiv ist, mit einem expliziten Kommentar, dass andernfalls ein Benutzer eine beliebige Datei auf dem Treiber überschreibt:
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)
Der 3.5-Schlüssel ist statisch, Standard false. Der 4.0-Ersatz ist buildConf optional:
val ARTIFACT_COPY_FROM_LOCAL_TO_FS_ALLOW_DEST_LOCAL =
buildConf("spark.sql.artifact.copyFromLocalToFs.allowDestLocal")
.internal()
...
.booleanConf
.createOptional
buildConf ruft registerStaticConfigKey nicht auf. isModifiable ist containsConfigKey && !isStaticConfigKey. RuntimeConfig.set lehnt nur statische Schlüssel ab. Internal ist weiterhin setzbar. Nach dem SET gibt getConf(ARTIFACT_...) Some(true) zurück, und der getOrElse-Fallback auf die alte statische Konfiguration wird übersprungen.
SPARK-58531 / PR 57730 „Convert spark.sql.artifact.copyFromLocalToFs.allowDestLocal to a static conf" ist am 2026-08-05 gelöst, Fix Version 4.3.0. JIRA: Die Konfiguration „controls whether a caller can write to an arbitrary path on the driver's local filesystem, so it is meant to be set by whoever starts the driver." 4.2.0 ist als Affects aufgeführt. Dieser Pin hat noch die Laufzeitkonfiguration.
Bereits festgehaltene Irrwege: Connect-SQL als Finding behandeln (FAQ); SET des alten statischen Schlüssels (CANNOT_MODIFY_STATIC_CONFIG); behaupten, ein Unix-absolutes Ziel ignoriere das übergeordnete Verzeichnis (es wird unter root zusammengefügt); Dateischreiben zu RCE aufblähen; 4.3.0 RC pinnen, weil das JIRA gelöst ist.
cd lab
./run.sh