
Preuve de concept démontrant une XSS stockée dans le widget Table d'Appsmith menant à une élévation de privilèges verticale et à une prise de contrôle totale de l'administrateur via une attaque XSS-to-CSRF.
Preuve de concept pour l'élévation de privilèges dans Appsmith via XSS stocké
Divulgation : Signalé à l'origine par moi via GHSA-5hw4-whxv-6794
⚠️ Usage autorisé uniquement pour des tests d'intrusion/recherche.
| Champ | Valeur |
|---|---|
| ID CVE | CVE-2026-30862 |
| Sévérité | 🔴 Critique |
| Score CVSS | 9.1 |
| Vecteur CVSS | [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 |
| Produit concerné | Appsmith ≤ 1.95 |
| Version corrigée | 1.96 |
| Avis de sécurité | GHSA-5hw4-whxv-6794 |
Une vulnérabilité XSS stocké critique existe dans le Table Widget (TableWidgetV2). La cause racine est l'absence d'assainissement HTML dans le pipeline de rendu des composants React, permettant l'interpolation d'attributs malveillants dans le DOM. En exploitant la fonctionnalité « Inviter des utilisateurs », un attaquant disposant d'un compte utilisateur standard ([email protected]) peut forcer un administrateur système à exécuter un appel API à privilèges élevés (/api/v1/admin/env), entraînant une prise de contrôle totale du compte administrateur.
1. Cause racine : absence de point de sortie d'assainissement La vulnérabilité réside dans le moteur de rendu du Table Widget
Fichier : app/client/src/widgets/TableWidgetV2/component/cellComponents/BasicCell.tsx
Le composant BasicCell ne parvient pas à assainir les données lorsque le columnType est défini sur URL ou Plain Text. Il renvoie des valeurs brutes fournies par l'utilisateur qui sont directement rendues comme enfants React, que le navigateur interprète comme du HTML exécutable.
Extrait de code vulnérable (lignes 132-143 et 172-173) :
const contentToRender = useMemo(() => {
switch (columnType) {
case ColumnTypes.URL:
// Interpolation directe de 'url' dans href sans assainissement
return <a href={url} target="_blank">{value}</a>;
default:
return value; // Ligne 141 : valeur brute renvoyée
}
}, [columnType, url, value]);
// Ligne 173 : point de sortie final où le contenu non assaini est injecté dans le DOM
<Content ref={contentRef}>{contentToRender}</Content>
2. Vecteur d'attaque : XSS vers CSRF via ingénierie sociale (fonctionnalité Inviter) Bien que le cookie SESSION soit protégé par HttpOnly, le XSRF-TOKEN est accessible via document.cookie. Comme Appsmith permet à tout utilisateur d'« inviter » d'autres personnes dans son application, un attaquant peut utiliser ce mécanisme comme vecteur de livraison pour exécuter une falsification de requête inter-privilèges (CPRF) dans la session active de l'administrateur.
Étape 1 : Vérification de la vulnérabilité XSS
Connectez-vous avec un compte utilisateur standard : [email protected].
Créez une nouvelle application et ajoutez un Table Widget.
Dans la propriété Table Data, injectez ce qui suit :
[{ "id": 1, "payload": "" }]
-- Étape 2 : Armement (prise de contrôle totale de l'administrateur)
[email protected], mettez à jour les Table Data avec la charge utile suivante conçue pour modifier l'environnement administratif :[
{
"id": 1,
"Status": "System Update Required",
"payload": "alert('Admin Privileges Granted to [email protected]'));\">"
}
]
Utilisez la fonctionnalité « Partager » pour inviter l'administrateur système ([email protected]) dans l'application. Cela force l'administrateur à consulter le tableau malveillant lors de l'ouverture de l'invitation.
Une fois que l'administrateur lance l'application, le script s'exécute en arrière-plan. Il lit le XSRF-TOKEN de l'administrateur et envoie une requête PUT pour ajouter [email protected] à la liste blanche administrative.
Résultat : Reconnectez-vous en tant que [email protected]. Vous aurez désormais un accès complet aux paramètres d'administration et à toutes les configurations de l'instance.
Type de vulnérabilité : XSS stocké / élévation verticale de privilèges.
Sévérité : 9.1 (Critique) | CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:H/I:H/A:H
Risque : Compromission complète de l'instance Appsmith. Les attaquants obtiennent l'accès aux variables d'environnement sensibles, aux identifiants de base de données et la capacité de modifier toute application au sein de l'instance.
Assainir les points de sortie : Enveloppez toutes les sorties dynamiques dans BasicCell.tsx et les composants associés avec DOMPurify.sanitize().
CSP renforcé : Implémentez une politique connect-src stricte pour empêcher les appels API non autorisés vers les points de terminaison administratifs depuis les charges utiles XSS.
https://github.com/user-attachments/assets/206a10e4-1619-4887-a552-99761baa0a29