abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · joomla-articles-catid
类别: 权限残留 可达性: 远程
Joomla CMS 6.1.3 (0f2d4de) - Open Source Matters
管理员 ArticleController::allowAdd 会检查 com_content.category.{catid}。api/components/com_content/src/Controller/ArticlesController.php 中没有 allowAdd。随后 ApiController::add() 在无数据的情况下调用 allowAdd(),因此 JSON 中的 catid 从未进入检查。只要用户能在任意分类中创建内容,基础 allowAdd 就返回 true。
一个 Manager 级别的 API 用户,被授予 core.login.api 并在某一个分类上拥有创建权限,就可以将文章 POST 到他们在 UI 中被拒绝的分类中。
| ID | 暂无 CVE |
| 类别 | 权限残留 / 授权绕过 |
| 可达性 | 远程(拥有 core.login.api 的 API token) |
| CWE | CWE-863 |
| 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),POST /api/index.php/v1/content/articles |
| 认证 | Manager(组 6)的 API token,拥有 core.login.api、com_content 的 core.manage,以及仅在一个分类上的 core.create。无需 Super User。默认情况下 core.login.api 仅限 Super User。 |
| 许可证 | GNU Affero GPL v3.0 |
| 实验环境 | 仅限 127.0.0.1 |
使用一个非 Super User 的 API token,该 token 可以在一个分类中创建内容,从而发布到他们被禁止访问的分类中。他们不会因此权限残留而变成 Super User。这是未授权发布,不是站点接管,也不是读取隐藏文章。
| 权限 | 方法 / 路径 | 类型 | 实验验证或推断 |
|---|---|---|---|
| 在他们被拒绝的分类中创建文章 | POST /api/index.php/v1/content/articles,JSON 中 catid 为 B | 完整性 | 实验验证。HTTP 200,#__content id=1,catid=9(Press),标题 poc-art-JOOMLA-ARTICLES-CATID-WITNESS |
| 在仅允许 Drafts 的情况下,向 Official notices / Press 植入已发布副本 | 同一 POST,state=1 | 完整性 | 实验验证可创建到被拒绝的 Press。推断适用于任何其他 core.create 被拒绝的分类资产 |
| 通过 API 编辑现有文章 | PATCH /api/index.php/v1/content/articles/{id} | 不适用 | 推断对该 Manager 已关闭。基础 allowEdit 需要组件级 core.edit;实验环境中 com_content 规则将 core.edit 授予 Author (4),而非 Manager (6)。实验未执行 PATCH |
| 通过 API 删除文章 | DELETE /api/index.php/v1/content/articles/{id} | 不适用 | 推断已关闭。基础 allowDelete 需要组件级 core.delete。实验未执行 DELETE |
| 从管理员端将文章保存到允许的分类 A | POST ... task=article.save jform[catid]=A | 预期行为 | 实验验证按预期开放。HTTP 200,未被拒绝 |
| 从管理员端将文章保存到被拒绝的分类 B | 同一 task,jform[catid]=B | 不适用 | 实验验证已关闭。HTTP 200 并返回 "not permitted" / create-not-permitted(UI 中 com_content.category.B 上的 allowAdd) |
使用原生 Manager(无 core.login.api)访问 API | Bearer token / X-Joomla-Token | 不适用 | 推断已关闭。默认 core.login.api 仅限 Super User(组 8)。本实验先将其授予组 6 |
| contacts / banners / newsfeeds 上存在相同缺口 | POST /api/index.php/v1/contacts(及同类接口),使用外部 catid | 完整性 | 推断。这些 API 控制器同样缺少 allowAdd。实验未测试它们 |
| Super User / 安装器 RCE | 不适用 | 不适用 | 已关闭。Manager 仍然是 Manager |
在 2026-07/08 JSST 浪潮之后,我锁定了 6.1.3。Groups API 已经要求 core.admin。Media webservice 已经要求 override 上的 core.edit。Articles API 仍然落入 ApiController,并将“在任意分类中创建”视为对所有 catid 都足够。
public function add()
{
if (!$this->allowAdd()) {
throw new NotAllowed('JLIB_APPLICATION_ERROR_CREATE_RECORD_NOT_PERMITTED', 403);
}
$recordId = $this->save();
$this->displayItem($recordId);
}
基础检查:
protected function allowAdd($data = [])
{
$user = $this->app->getIdentity();
if (!$user->authorise('core.manage', $this->option)) {
return false;
}
return $user->authorise('core.create', $this->option)
|| \count($user->getAuthorisedCategories($this->option, 'core.create'));
}
管理员 UI 已经基于 catid 进行判断:
protected function allowAdd($data = [])
{
$categoryId = ArrayHelper::getValue(
$data,
'catid',
$this->input->getInt('filter_category_id'),
'int'
);
if ($categoryId) {
return $this->app->getIdentity()->authorise(
'core.create',
'com_content.category.' . $categoryId
);
}
return parent::allowAdd();
}
已记录的弯路:将 UI 的 HTTP 200 解读为允许(对 B 的拒绝是 "not permitted" 响应体);将组件级 core.create 视为漏洞所在(实验中的 Manager 没有该权限;一个分类的允许就足以满足基础 getAuthorisedCategories 计数);使用没有 core.login.api 的原生 Manager。花架子:反向 shell。判定依据是 API 对 Press 返回 200,加上 UI 对 Drafts 允许,加上 UI 对 Press 拒绝。
同一版本的其他残留问题:levels API、menu items API、media override。
python3 joomla-articles-catid-Abraxas-Labs.py
或
cd lab
./run.sh
目标仅限 http://127.0.0.1:19550。镜像 joomla:6.1.3-php8.3-apache 加上 mariadb:11.4。
SUCCESS joomla-articles-catid api-http=200 article-id=1 catid=9 cat-a=8 cat-b=9 ui-a=200 ui-b=200 JOOMLA-ARTICLES-CATID-WITNESS
article-id 是下一个 #__content 自增值(在干净的 6.1.3 安装上为 1)。ui-a / ui-b 是 HTTP 200;对 B 的拒绝是 UI 的 "not permitted" 响应体,而不是 403 状态码。
在 api/components/com_content/src/Controller/ArticlesController.php 上覆盖 allowAdd(以及 allowEdit),方式与管理员 ArticleController 相同:检查 com_content.category.{catid} 上的 core.create。将请求 JSON 传入 ApiController::add(),使 catid 真正到达该检查。如果 contacts、banners 和 newsfeeds 的控制器仍使用默认 allowAdd,则对它们应用相同模式。
0f2d4de4729eb951e0878fec98c7990da07915b2)ArticlesController.phpApiController.phpGNU Affero GPL v3.0。参见 LICENSE。仅限回环实验环境。无担保。