
Proof-of-Concept-Lab für eine Autorisierungsschwachstelle in Apache Superset 6.1.0, bei der ein Gamma-Dashboard-Editor über einen unversionierten v0-Dashboard-Import Dataset-SQL einschleust, das beim Aktualisieren des Diagramms ausgeführt wird.
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · superset-g3-v0-import-sql-plant
Ein Kollege mit einem normalen Dashboard-Editor-Konto kann seine eigene Datenbankabfrage in einem Diagramm verstecken, dem andere bereits vertrauen. Wenn jemand dieses Diagramm das nächste Mal öffnet, wird die Abfrage gegen die Datenverbindung des Unternehmens ausgeführt. Er kann Tabellen lesen, auf die er nie Zugriff erhalten hat. Er benötigt nicht die zusätzliche Berechtigung „eigenes SQL ausführen“, die dies eigentlich absichern soll. Er kann keine neue Warehouse-Anmeldung registrieren und kann über diesen Diagramm-Pfad kein INSERT oder DELETE ausführen.
Klasse: Privilegien-Rest Reichweite: Remote
Apache Superset 6.1.0 (c83fb2bb) - Apache Software Foundation
Das Standard-Gamma hat can_write für Dashboard, daher ist POST /api/v1/dashboard/import/ in der Matrix enthalten. Nicht-ZIP-JSON hat keine metadata.yaml, daher versucht der Dispatcher zuerst v1 und fällt dann auf unversioniertes v0 zurück. decode_dashboards rekonstituiert SqlaTable. import_dataset sucht nach table_name + schema + database_id (aus params.database_name) und datasource.override(i_datasource) kopiert export_fields einschließlich sql ohne raise_for_access und ohne Dataset-Schreibzugriff. POST /api/v1/chart/data kompiliert dann dieses SQL als virtuelles FROM auf der Analytics-Verbindung des Datasets.
Gamma-SQL ohne sql_lab. Dataset REST PUT bleibt 403. v1 ZIP bleibt leer.
| ID | noch keine CVE |
| Klasse | Privilegien-Rest (Rest von CVE-2026-23982 / CVE-2024-26016) |
| Reichweite | Remote (authentifiziertes HTTP; Standard-Gamma) |
| CWE | CWE-863, CWE-284 |
| CVSS | Hoch: 7.6 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:L/A:L |
| Produkt | Apache Superset |
| Betroffen | 6.1.0 (c83fb2bb1dcfac41ac51bcebd82471f4a7180d18); GitHub Latest GA bei der Suche |
| Auth | Standard-Gamma (can_write Dashboard). Nicht unauthentifiziert. Nicht Admin (außerhalb des Geltungsbereichs). |
| Lizenz | GNU Affero GPL v3.0 |
| Lab | nur 127.0.0.1 |
Benötigt ein Gamma- (oder beliebiges Dashboard-Schreib-)Konto und ein Dataset, das er später als Diagramm darstellen kann: gleicher table_name + schema auf einer Datenbank, deren database_name im JSON params enthalten ist. Die ergänzende Berechtigung gilt für das Dataset-Objekt, nicht für jede Tabelle, die das eingeschleuste SQL nennt. Chart/data raise_for_access ist datasource-objektbezogen (datasource_access / Schema / Eigentümer). get_from_clause lehnt nur has_mutation() ab.
| Berechtigung | Methode / Sink | Recon / Integrität / Verfügbarkeit | Im Labor nachgewiesen oder abgeleitet |
|---|---|---|---|
| Überschreiben des virtuellen SQL eines namensgleichen Datasets | Gamma POST /api/v1/dashboard/import/ Nicht-ZIP-JSON; v0 import_dataset datasource.override kopiert export_fields einschließlich sql | Integrität (dataset.sql) | Im Labor nachgewiesen. Import 200; dataset.sql = SELECT 'SUPERSET-G3-V0-IMPORT-SQL-PLANT-WITNESS' AS witness |
| Ausführen dieses SQL auf der Analytics-URI des Datasets | POST /api/v1/chart/data nach dem Plant; get_from_clause verpackt gespeichertes sql als TextAsFrom | Recon (SELECT auf jede Tabelle, die der URI-Benutzer lesen kann) | Im Labor nachgewiesen. 200; kompiliert FROM (SELECT 'SUPERSET-G3-V0-IMPORT-SQL-PLANT-WITNESS' AS witness) AS virtual_table |
| Verstecken der Abfrage in einem Chart, das andere berechtigte Benutzer bereits geöffnet haben | Derselbe Plant; Eigentümer / andere datasource_access-Principals führen ihn beim Aktualisieren aus | Integrität + Recon (andere Personen führen den Plant aus) | Abgeleitet. Im Labor hatte Gamma bereits die Berechtigung, sodass es selbst ausgeführt wurde |
| Brechen von Dashboards, die das alte SQL verwendeten | Ersetzen des sql der physischen Tabelle durch ein Angreifer-SELECT | Verfügbarkeit | Abgeleitet |
| Negativ: SQL Lab execute | POST /api/v1/sqllab/execute/ | n/a | Im Labor nachgewiesen. 403 |
| Negativ: Dataset REST overwrite | PUT /api/v1/dataset/{id} mit sql | n/a | Im Labor nachgewiesen. 403; sql blieb leer (CVE-2026-23982 verwandt) |
Negativ: v1 ZIP mit metadata.yaml | derselbe Import-Endpunkt, ZIP-Bundle | n/a | Im Labor nachgewiesen. 200; sql blieb leer (CVE-2024-26016-Klasse) |
Zu diesem Überbleibsel geschlossen: unauthentifizierter Import; Registrieren einer neuen Database-URI (v0-Dataset-Import erstellt die Verbindung nicht; fehlendes params.database_name ist DatabaseNotFoundError); DML über chart/data (has_mutation()); Gamma chartet ein Dataset, das es nicht lesen kann (403); ein neu eingefügter eindeutiger table_name (PVM erstellt, nicht an Gamma angehängt). Kein RCE. Kein Admin. Die Aufteilung des Produktions-Warehouse begrenzt SELECT auf diesen URI-Benutzer. Die Analytics-URI im Labor war dieselbe Postgres wie die Metadaten, daher ist Cross-Table einschließlich ab_user abgeleitet, nicht durch ein zweites Orakel bestätigt.
Ich habe Apache Superset 6.1.0 gepinnt. Admin ist OS-äquivalent und außerhalb des Geltungsbereichs. Ich habe Überbleibsel gegen Apaches eigene Rollenmatrix gejagt: Gamma, Alpha, sql_lab, eingebetteter Gast, Public.
Die 6.0.0-Welle hatte bereits chart/data sqlExpression (CVE-2026-23980), Dataset REST SQL (CVE-2026-23982) und SQL Lab DO $$ / EXPLAIN ANALYZE (CVE-2026-23984) geschlossen. Import-Authz für versionierte ZIPs ist CVE-2024-26016. Unversioniertes v0 steht in command_versions immer noch an letzter Stelle, weil „die Dateien nicht versioniert sind“.
import_ auf Dashboard ist auf Schreiben abgebildet. Nicht-ZIP-JSON ist {filename: bytes} ohne metadata.yaml. Der Dispatcher versucht v1, fängt IncorrectVersionError ab und führt v0 aus. decode_dashboards verwandelt __SqlaTable__ in ein Live-Modell. import_dataset schlägt nach und überschreibt. export_fields enthält sql. Zur Abfragezeit wird gespeichertes SQL als vertrauenswürdig behandelt: get_from_clause nach has_mutation().
Bereits festgehaltene Irrwege: v1-ZIP als das Überbleibsel zu behandeln (sql blieb leer); Dataset REST PUT (403); SQL Lab als Gamma (403); Aufblähen zu einem beliebigen Database-Objekt (v0 registriert keine URI); eine Reverse Shell. Theater. Der Zeuge ist das virtuelle FROM.
python3 superset-g3-v0-import-sql-plant-Abraxas-Labs.py
oder:
cd lab
./run.sh