
Proof-of-Concept, das gespeichertes XSS im Appsmith Table Widget demonstriert, was zu vertikaler Privilegieneskalation und vollständiger Admin-Übernahme über einen XSS-zu-CSRF-Angriff führt.
Proof-of-Concept für Privilege Escalation in Appsmith über Stored XSS
Offenlegung: Ursprünglich von mir gemeldet über GHSA-5hw4-whxv-6794
⚠️ Nur für autorisierte Penetrationstests/Forschung.
| Feld | Wert |
|---|---|
| CVE-ID | CVE-2026-30862 |
| Schweregrad | 🔴 Kritisch |
| CVSS-Score | 9.1 |
| CVSS-Vektor | [CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:H/I:H/A:H] |
| CWE | CWE-79, CWE-269, CWE-352 |
| Betroffenes Produkt | Appsmith ≤ 1.95 |
| Gepatchte Version | 1.96 |
| Advisory | GHSA-5hw4-whxv-6794 |
Eine kritische Stored-XSS-Schwachstelle besteht im Table Widget (TableWidgetV2). Die Ursache liegt in fehlender HTML-Bereinigung in der React-Komponenten-Rendering-Pipeline, wodurch bösartige Attribute in das DOM interpoliert werden können. Durch die Nutzung der Funktion „Benutzer einladen“ kann ein Angreifer mit einem regulären Benutzerkonto ([email protected]) einen Systemadministrator dazu zwingen, einen API-Aufruf mit hohen Rechten (/api/v1/admin/env) auszuführen, was zu einer vollständigen Übernahme des Administratorkontos führt.
1. Ursache: Fehlende Ausgabe-Bereinigung (Sink) Die Schwachstelle liegt in der Rendering-Engine des Table Widgets
Datei: app/client/src/widgets/TableWidgetV2/component/cellComponents/BasicCell.tsx
Die BasicCell-Komponente bereinigt Daten nicht, wenn columnType auf URL oder Plain Text gesetzt ist. Sie gibt rohe, vom Benutzer bereitgestellte Werte zurück, die direkt als React-Children gerendert werden und vom Browser als ausführbares HTML interpretiert werden.
Verwundbarer Code-Ausschnitt (Zeilen 132–143 & 172–173):
const contentToRender = useMemo(() => {
switch (columnType) {
case ColumnTypes.URL:
// Direkte Interpolation von 'url' in href ohne Bereinigung
return <a href={url} target="_blank">{value}</a>;
default:
return value; // Zeile 141: Rohwert zurückgegeben
}
}, [columnType, url, value]);
// Zeile 173: Finaler Sink, in dem unbereinigter Inhalt in das DOM injiziert wird
<Content ref={contentRef}>{contentToRender}</Content>
2. Angriffsvektor: XSS-zu-CSRF über Social Engineering (Einladungsfunktion) Obwohl das SESSION-Cookie durch HttpOnly geschützt ist, ist das XSRF-TOKEN über document.cookie zugänglich. Da Appsmith jedem Benutzer erlaubt, andere zu ihrer App „einzuladen“, kann ein Angreifer dies als Verteilmechanismus nutzen, um eine Cross-Privilege Request Forgery (CPRF) innerhalb der aktiven Sitzung des Administrators auszuführen.
Schritt 1: Verifizierung der XSS-Schwachstelle
Melden Sie sich mit einem regulären Benutzerkonto an: [email protected].
Erstellen Sie eine neue Anwendung und fügen Sie ein Table Widget hinzu.
Injizieren Sie in die Eigenschaft Table Data Folgendes:
[{ "id": 1, "payload": "" }]
-- Schritt 2: Waffeneinsatz (vollständige Admin-Übernahme)
[email protected] die Table Data mit dem folgenden Payload, der darauf ausgelegt ist, die administrative Umgebung zu modifizieren:[
{
"id": 1,
"Status": "System Update Required",
"payload": "alert('Admin Privileges Granted to [email protected]'));\">"
}
]
Nutzen Sie die Funktion „Teilen“, um den Systemadministrator ([email protected]) zur App einzuladen. Dadurch wird der Administrator gezwungen, die bösartige Tabelle beim Öffnen der Einladung anzusehen.
Sobald der Administrator die App startet, wird das Skript im Hintergrund ausgeführt. Es liest das XSRF-TOKEN des Administrators und sendet eine PUT-Anfrage, um [email protected] zur administrativen Whitelist hinzuzufügen.
Ergebnis: Melden Sie sich erneut als [email protected] an. Sie haben nun vollen Zugriff auf die Admin-Einstellungen und alle Instanzkonfigurationen.
Schwachstellentyp: Stored XSS / Vertikale Privilege Escalation.
Schweregrad: 9.1 (Kritisch) | CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:H/I:H/A:H
Risiko: Vollständige Kompromittierung der Appsmith-Instanz. Angreifer erhalten Zugriff auf sensible Umgebungsvariablen, Datenbank-Anmeldedaten und die Möglichkeit, jede Anwendung innerhalb der Instanz zu modifizieren.
Sinks bereinigen: Alle dynamischen Ausgaben in BasicCell.tsx und verwandten Komponenten mit DOMPurify.sanitize() umschließen.
Härtung der CSP: Implementieren Sie eine strikte connect-src-Richtlinie, um unbefugte API-Aufrufe an administrative Endpunkte durch XSS-Payloads zu verhindern.
https://github.com/user-attachments/assets/206a10e4-1619-4887-a552-99761baa0a29