Apache Spark 4.2.0 - Alto - Remoto - Scrittura di file - Connect session SET copyFromLocalToFs.allowDestLocal
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · spark-connect-copy-local
Classe: Scrittura di file (residuo di SPARK-58531; statico solo su 4.3.0) Portata: Remota
Apache Spark 4.2.0 (32f72996) - Apache Software Foundation
spark.sql.artifact.copyFromLocalToFs.allowDestLocal è ancora buildConf (impostabile per sessione) su questo pin. SPARK-58531 l'ha spostata in StaticSQLConf nella 4.3.0. Una sessione Connect può impostare il gate local-dest riservato ai test, poi copyFromLocalToFs / AddArtifacts forward_to_fs/<abs> sovrascrive un percorso locale al driver con l'UID di Spark.
La sessione Connect imposta, poi forward_to_fs scrive file locali al driver. La destinazione deve essere LocalFileSystem. Non è RCE.
| ID | nessuna CVE al momento (residuo di SPARK-58531) |
| Classe | Scrittura di file (residuo di SPARK-58531; statico solo su 4.3.0) |
| Portata | Remota (Spark Connect Config + AddArtifacts) |
| CWE | CWE-22, CWE-732 |
| CVSS | Alto: 8.1 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:H |
| Prodotto | Apache Spark (ASF) |
| Affetto | Apache Spark 4.2.0 (32f7299601108917fb01920a54e084595b7b3bf8). La 4.3.0 è statica. |
| Auth | Client Connect in grado di eseguire ConfigRequest.SET e AddArtifacts. Connect predefinito non ha PSK. |
| Licenza | GNU Affero GPL v3.0 |
| Lab | solo 127.0.0.1:18920 |
Un client Spark Connect che riesce a raggiungere gRPC (porta di bind predefinita 15002, nessuna PSK a meno che l'operatore non abbia impostato spark.connect.authenticate.token) può disattivare un gate riservato ai test con cui il driver era stato avviato, e poi sovrascrivere un percorso locale scelto sul driver con l'UID di Spark.
| Metodo | Sink | Privilegio |
|---|---|---|
gRPC Config SET spark.sql.artifact.copyFromLocalToFs.allowDestLocal=true (o SQL SET) | SparkConnectConfigHandler.handleSet -> RuntimeConfig.set -> SQLConf.setConfString | Integrità (conf di sessione, dimostrato in lab): disattiva il gate local-dest per sessione. Non scrive un file da solo. Non modifica altre sessioni. Lab: SET HTTP 200, modifiable=True. |
gRPC AddArtifacts nome forward_to_fs + dest assoluta, CRC ok | ArtifactManager.uploadArtifactToFs -> LocalFileSystem.copyFromLocalFile(delSrc=false, overwrite=true) | Integrità (sovrascrittura di file, dimostrato in lab): scrive/sovrascrive un percorso locale al driver con l'UID di Spark, al di fuori di artifactRootDirectory/<sessionUUID>/. Lab: dest /oracle/SPARK-CONNECT-COPY-LOCAL-WITNESS, uid 185, contenuto WITNESS. |
| Stesso AddArtifacts verso dest HDFS/S3/ABFS | copyFromLocalToFs documentato | Integrità (FS di cluster, by design): non è questo residuo. Una destinazione che non è LocalFileSystem non consulta mai il flag di test. |
Dimostrato in lab vs dedotto: il SET di sessione della chiave buildConf, seguito dalla scrittura su destinazione LocalFileSystem come uid 185 al di fuori della sandbox degli artefatti, è dimostrato in lab. La sovrascrittura con l'UID di Spark di un percorso scrivibile dal processo (work dir del driver, una drop directory scrivibile da tutti, uno script già eseguibile che l'operatore esegue in seguito) è dedotta. Nessun controllo RIP. Non gonfiare la scrittura di file a RCE.
Richiede: Spark Connect in ascolto. Client in grado di impostare la conf SQL di sessione e AddArtifacts. La destinazione deve essere Hadoop LocalFileSystem. Connect predefinito non ha PSK; se l'operatore ha impostato un token, il residuo necessita comunque di quel Bearer condiviso. È un bypass del controllo local-dest, non un bypass della PSK.
| Superficie | Lab |
|---|---|
| Copia senza SET | 400 _LEGACY_ERROR_TEMP_3161, destinazione assente |
SET della vecchia chiave statica spark.connect.copyFromLocalToFs.allowDestLocal | 400 CANNOT_MODIFY_STATIC_CONFIG |
Nome artefatto .. / staging assoluto (ArtifactUtils.concatenatePaths) | INVALID_ARTIFACT_PATH |
Artefatti non-forward_to_fs | restano sotto artifactRootDirectory/<sessionUUID>/ |
| Dest HDFS/cloud senza il flag | API documentata, non questo residuo |
SQL non autenticato / Python UDF / Scala UdfPacket su Connect aperto | invio job da FAQ del vendor; DROP |
| SPARK-52122 ML DefaultParamsReader | allowlist + safeMLClassLoader su questo pin |
Nessuna shell. Nessun heap dump. Nessun salto della PSK di Connect. La destinazione deve comunque essere LocalFileSystem. La scrittura avviene con l'UID di Spark, non come root.
uploadArtifactToFs rifiuta una destinazione LocalFileSystem a meno che il flag di test sia attivo, con un commento esplicito che altrimenti un utente sovrascrive un file arbitrario sul driver:
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)
La chiave della 3.5 è statica, predefinita false. Il sostituto della 4.0 è buildConf opzionale:
val ARTIFACT_COPY_FROM_LOCAL_TO_FS_ALLOW_DEST_LOCAL =
buildConf("spark.sql.artifact.copyFromLocalToFs.allowDestLocal")
.internal()
...
.booleanConf
.createOptional
buildConf non chiama registerStaticConfigKey. isModifiable è containsConfigKey && !isStaticConfigKey. RuntimeConfig.set rifiuta solo le chiavi statiche. Internal è comunque impostabile. Dopo il SET, getConf(ARTIFACT_...) restituisce Some(true) e il fallback getOrElse alla vecchia conf statica viene saltato.
SPARK-58531 / PR 57730 "Convert spark.sql.artifact.copyFromLocalToFs.allowDestLocal to a static conf" è risolto il 2026-08-05, Fix Version 4.3.0. JIRA: la conf "controlla se un chiamante può scrivere su un percorso arbitrario sul filesystem locale del driver, quindi è pensata per essere impostata da chi avvia il driver." La 4.2.0 è elencata come Affected. Questo pin ha ancora la conf runtime.
Vicoli ciechi già registrati: trattare Connect SQL come un finding (FAQ); SET della vecchia chiave statica (CANNOT_MODIFY_STATIC_CONFIG); sostenere che una destinazione assoluta Unix ignori il parent (si unisce sotto la root); gonfiare la scrittura di file a RCE; fissare la 4.3.0 RC perché la JIRA è risolta.
cd lab
./run.sh