abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · joomla-media-override
类别: 权限残留 可达性: 远程
Joomla CMS 6.1.3 (0f2d4de) - Open Source Matters
CVE-2026-48947 让 webservice 媒体 API 在设置 override 时要求 core.edit。站点 JSON API 仍然没有。默认 Author 在 com_media 上拥有 core.create,但没有 core.edit。站点调度器认为 core.create 就足够了,并加载管理员 ApiController。随后 postFiles() 将 override 直接传入 createFile()。
一个默认 Author 可以替换磁盘上已存在的文件。访客继续访问同一个公开 URL,却得到新的字节内容。
| ID | 暂无 CVE |
| 类别 | 权限残留 / 完整性 |
| 可达性 | 远程(默认 Author,无需 API token) |
| CWE | CWE-863, CWE-639 |
| CVSS | 中危:6.5 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:N |
| 产品 | Joomla CMS |
| 受影响版本 | 6.1.3 (0f2d4de4729eb951e0878fec98c7990da07915b2),站点 com_media JSON API |
| 认证 | 默认 Author(组 3)。无需 API token。 |
| 许可证 | GNU Affero GPL v3.0 |
| 实验环境 | 仅 127.0.0.1 |
以默认 Author 身份登录,替换站点上已存在的文件。这是对已存储媒体的篡改 / 调包,而非站点接管。扩展名黑名单未变,因此这不是 .php 上传。
| 权限 | 方法 / 路径 | 类型 | 实验验证或推断 |
|---|---|---|---|
| 覆盖已存在的媒体文件(logo、文章图片) | 站点 POST /index.php?option=com_media&task=api.files&format=json&path=local-images:/,JSON 中带 override: true | 完整性 | 实验验证。HTTP 200,磁盘 SHA 改变,公开 GET /images/joomla_black.png 返回了携带 JOOMLA-MEDIA-OVERRIDE-WITNESS 的新 PNG |
| 篡改仍指向该 URL 的内容 | 同一公开路径,无缓存刷新 | 完整性 | 实验验证公开字节已改变。对 images/ 下其他适配器为推断 |
| 创建新的允许文件 | 同一 POST,不带 override | 预期行为 | Author 在 com_media 上拥有 core.create |
| 通过 PUT 编辑 | PUT 同一任务,路径包含文件名 | 不适用 | 实验验证已关闭。HTTP 403。putFiles() 已要求 core.edit |
| 名称已存在时创建,不带 override | POST override: false(默认) | 不适用 | 实验验证已关闭。HTTP 409,原始 SHA 在 override POST 之前保持不变 |
上传 .php 或其他被拒绝类型 | createFile / isMediaFile 黑名单 | 不适用 | 推断已关闭。本实验仅发送 PNG |
| 带 override 调用 webservice 媒体 API | /api/index.php/v1/media/files | 不适用 | 推断已关闭。MediaController::allowAdd 在设置 override 时检查 core.edit(CVE-2026-48947) |
| Super User / RCE | 不适用 | 不适用 | 已关闭。Author 仍是 Author |
在 2026-07/08 JSST 浪潮之后,我锁定了 6.1.3。Groups API 已要求 core.admin。Webservice 媒体在 override 时已要求 core.edit。内部控制器仍然没有。
默认 Author 在 com_media 上拥有 core.create,而 core.edit 中没有任何权限:
{"core.admin":{"7":1},"core.manage":{"6":1},"core.create":{"3":1},"core.delete":{"5":1}}
站点 Dispatcher 放行 core.create 并加载管理员 ApiController。随后 postFiles():
if (!$this->app->getIdentity()->authorise('core.create', 'com_media')) {
throw new \Exception(Text::_('JLIB_APPLICATION_ERROR_CREATE_RECORD_NOT_PERMITTED'), 403);
}
$override = $content->get('override', false);
if ($mediaContent) {
$name = $this->getModel()->createFile($adapter, $name, $path, $mediaContent, $override);
已修复的 webservice(api/.../MediaController.php):
if ($this->input->json->get('override', false)) {
return $user->authorise('core.edit', 'com_media');
}
已记录的弯路:将 PUT 视为残留(PUT 已是 403);认为 webservice 路径仍然开放(CVE-2026-48947 已关闭它);将不带 override 的 409 视为未命中(那是有意设计的“不存在则创建”路径)。表演性内容:反弹 shell。判定依据是 POST override 返回 200,加上 PUT 返回 403,加上公开 GET 到见证 PNG。
同一版本的其他残留:levels API、menu items API、articles catid。
python3 joomla-media-override-Abraxas-Labs.py
或
cd lab
./run.sh
目标仅限 http://127.0.0.1:19540。镜像 joomla:6.1.3-php8.3-apache 加 mariadb:11.4。
SUCCESS joomla-media-override post-http=200 override=yes bytes-changed=yes put-http=403 no-edit=yes conflict-http=409 JOOMLA-MEDIA-OVERRIDE-WITNESS
在 ApiController::postFiles() 中、createFile() 之前,加入与 MediaController::allowAdd 相同的 override -> core.edit 检查。PUT 保持要求 core.edit。
0f2d4de4729eb951e0878fec98c7990da07915b2)ApiController.php postFilesGNU Affero GPL v3.0。参见 LICENSE。仅限回环实验环境。无担保。