
Proof-of-concept di laboratorio per una vulnerabilità di autorizzazione in Apache Superset 6.1.0, in cui un editor di dashboard con ruolo Gamma inserisce SQL nel dataset tramite l'importazione di dashboard v0 non versionata, eseguito all'aggiornamento del grafico.
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · superset-g3-v0-import-sql-plant
Un collega con un normale account di editor di dashboard può nascondere la propria query al database all'interno di un grafico di cui altri si fidano già. La prossima volta che qualcuno apre quel grafico, la query viene eseguita sulla connessione ai dati aziendale. Può leggere tabelle a cui non gli è mai stato concesso l'accesso. Non ha bisogno del permesso aggiuntivo "esegui il mio SQL" che dovrebbe proteggere questa operazione. Non può registrare un nuovo login al warehouse e non può eseguire INSERT o DELETE tramite questo percorso del grafico.
Classe: Privilegio residuo Portata: Remota
Apache Superset 6.1.0 (c83fb2bb) - Apache Software Foundation
Il Gamma predefinito ha can_write su Dashboard, quindi POST /api/v1/dashboard/import/ è nella matrice. Il JSON non-ZIP non ha metadata.yaml, quindi il dispatcher prova la v1, poi ricade sulla v0 senza versione. decode_dashboards ricostituisce SqlaTable. import_dataset cerca per table_name + schema + database_id (da params.database_name) e datasource.override(i_datasource) copia export_fields incluso sql senza raise_for_access e senza scrittura su Dataset. POST /api/v1/chart/data compila poi quel SQL come FROM virtuale sulla connessione analitica del dataset.
SQL Gamma senza sql_lab. Il PUT REST del Dataset resta 403. La ZIP v1 resta vuota.
| ID | nessuna CVE al momento |
| Classe | Privilegio residuo (residuo di CVE-2026-23982 / CVE-2024-26016) |
| Portata | Remota (HTTP autenticato; Gamma predefinito) |
| CWE | CWE-863, CWE-284 |
| CVSS | Alto: 7.6 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:L/A:L |
| Prodotto | Apache Superset |
| Affetto | 6.1.0 (c83fb2bb1dcfac41ac51bcebd82471f4a7180d18); GitHub Latest GA al momento della ricerca |
| Auth | Gamma predefinito (can_write su Dashboard). Non non autenticato. Non Admin (fuori ambito). |
| Licenza | GNU Affero GPL v3.0 |
| Lab | solo 127.0.0.1 |
Serve un account Gamma (o qualsiasi account con scrittura su Dashboard) e un dataset che possa successivamente rappresentare in un grafico: stesso table_name + schema su un Database il cui database_name è nel JSON params. La concessione complementare è sull'oggetto dataset, non su ogni tabella nominata dal SQL impiantato. raise_for_access di chart/data è sull'oggetto datasource (datasource_access / schema / owner). get_from_clause rifiuta solo has_mutation().
| Privilegio | Metodo / sink | Recon / integrità / disponibilità | Provato in laboratorio o dedotto |
|---|---|---|---|
| Sovrascrivere l'SQL virtuale di un dataset con nome corrispondente | Gamma POST /api/v1/dashboard/import/ JSON non-ZIP; v0 import_dataset datasource.override copia export_fields incluso sql | Integrità (dataset.sql) | Provato in laboratorio. Import 200; dataset.sql = SELECT 'SUPERSET-G3-V0-IMPORT-SQL-PLANT-WITNESS' AS witness |
| Eseguire quell'SQL sull'URI analytics del dataset | POST /api/v1/chart/data dopo il plant; get_from_clause avvolge l'sql memorizzato come TextAsFrom | Recon (SELECT su qualsiasi tabella che l'utente dell'URI può leggere) | Provato in laboratorio. 200; compilato FROM (SELECT 'SUPERSET-G3-V0-IMPORT-SQL-PLANT-WITNESS' AS witness) AS virtual_table |
| Nascondere la query in un grafico che altri utenti autorizzati hanno già aperto | Stesso plant; i proprietari / altri principal con datasource_access eseguono al refresh | Integrità + recon (altre persone eseguono il plant) | Dedotto. Il laboratorio Gamma aveva già la concessione, quindi auto-eseguito |
| Rompere le dashboard che usavano il vecchio SQL | Sostituire l'sql della tabella fisica con un SELECT dell'attaccante | Disponibilità | Dedotto |
| Negativo: esecuzione SQL Lab | POST /api/v1/sqllab/execute/ | n/a | Provato in laboratorio. 403 |
| Negativo: sovrascrittura REST del Dataset | PUT /api/v1/dataset/{id} con sql | n/a | Provato in laboratorio. 403; sql rimasto vuoto (simile a CVE-2026-23982) |
Negativo: ZIP v1 con metadata.yaml | stesso endpoint di import, bundle ZIP | n/a | Provato in laboratorio. 200; sql rimasto vuoto (classe CVE-2024-26016) |
Chiuso su questo residuo: import non autenticato; registrazione di un nuovo URI Database (l'import dataset v0 non crea la connessione; la mancanza di params.database_name è DatabaseNotFoundError); DML tramite chart/data (has_mutation()); Gamma che crea un grafico su un dataset che non può leggere (403); un table_name univoco appena inserito (PVM creato, non collegato a Gamma). Non è RCE. Non è Admin. La separazione del warehouse di produzione limita il SELECT all'utente di quell'URI. L'URI analytics del laboratorio era lo stesso Postgres dei metadati, quindi l'accesso cross-table incluso ab_user è dedotto, non verificato con un secondo oracolo.
Ho fissato Apache Superset 6.1.0. Admin è equivalente a livello di OS ed è fuori scope. Ho cercato residui confrontandoli con la matrice dei ruoli di Apache: Gamma, Alpha, sql_lab, guest embedded, Public.
L'ondata 6.0.0 aveva già chiuso sqlExpression di chart/data (CVE-2026-23980), l'SQL REST del Dataset (CVE-2026-23982) e DO $$ / EXPLAIN ANALYZE di SQL Lab (CVE-2026-23984). L'autorizzazione all'import per lo ZIP versionato è CVE-2024-26016. Il v0 non versionato è ancora ultimo in command_versions perché "i file non sono versionati".
import_ su Dashboard corrisponde a write. Il JSON non-ZIP è {filename: bytes} senza metadata.yaml. Il dispatcher prova v1, intercetta IncorrectVersionError, esegue v0. decode_dashboards trasforma __SqlaTable__ in un modello live. import_dataset cerca e sovrascrive. export_fields include sql. Al momento della query l'SQL memorizzato è considerato attendibile: get_from_clause dopo has_mutation().
Vicoli ciechi già registrati: trattare lo ZIP v1 come residuo (sql rimasto vuoto); PUT REST del Dataset (403); SQL Lab come Gamma (403); gonfiare fino a un oggetto Database qualsiasi (v0 non registra un URI); una reverse shell. Teatro. Il testimone è il FROM virtuale.
python3 superset-g3-v0-import-sql-plant-Abraxas-Labs.py
o:
cd lab
./run.sh