
Joomla 6.1.3 - 高 - リモート - ACL - POST /api/v1/content/articles がカテゴリ単位の ACL を無視する
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 と 1 つのカテゴリでの作成権限を付与されている場合、UI では拒否されているカテゴリに記事を POST できる。
| ID | CVE 未採番 |
| クラス | 権限の取りこぼし / 認可バイパス |
| 到達性 | リモート (core.login.api を持つ API トークン) |
| CWE | CWE-863 |
| CVSS | Medium: 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 トークンで、core.login.api、com_content の core.manage、および1 つのカテゴリのみに対する core.create を持つ。Super User は不要。デフォルトの core.login.api は Super User のみ。 |
| ライセンス | GNU Affero GPL v3.0 |
| ラボ | 127.0.0.1 のみ |
1 つのカテゴリで作成可能な非 Super User の API トークンを使い、禁止されているカテゴリに公開できる。この取りこぼしによって Super User になれるわけではない。これは不正な公開であり、サイトの乗っ取りでも、非表示記事の読み取りでもない。
| 権限 | メソッド / パス | 種別 | ラボ実証または推測 |
|---|---|---|---|
| 拒否されているカテゴリに記事を作成 | POST /api/index.php/v1/content/articles で B の catid を JSON 指定 | 完全性 | ラボ実証済み。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} | n/a | この Manager では閉じていると推測。基底の allowEdit はコンポーネントの core.edit を必要とする。ラボの com_content ルールでは core.edit は Author (4) に付与され、Manager (6) には付与されない。ラボでは PATCH を実施していない |
| API 経由で記事を削除 | DELETE /api/index.php/v1/content/articles/{id} | n/a | 閉じていると推測。基底の allowDelete はコンポーネントの core.delete を必要とする。ラボでは DELETE を実施していない |
| 管理者画面から許可カテゴリ A に記事を保存 | POST ... task=article.save jform[catid]=A | 意図どおり | ラボ実証済み 意図どおり開いている。HTTP 200、拒否されず |
| 管理者画面から拒否カテゴリ B に記事を保存 | 同じタスク、jform[catid]=B | n/a | ラボ実証済み 閉じている。HTTP 200 で "not permitted" / create-not-permitted (UI の com_content.category.B に対する allowAdd) |
素の Manager (core.login.api なし) で API を叩く | Bearer トークン / X-Joomla-Token | n/a | 閉じていると推測。デフォルトの core.login.api は Super User (グループ 8) のみ。このラボではまずグループ 6 に付与している |
| contacts / banners / newsfeeds での同様のギャップ | 外部の catid を指定した POST /api/index.php/v1/contacts (および類似) | 完全性 | 推測。これらの API コントローラにも allowAdd が存在しない。ラボでは検証していない |
| Super User / インストーラ RCE | n/a | n/a | 閉じている。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 にはそれがなく、1 カテゴリの許可で基底の getAuthorisedCategories のカウントには十分); core.login.api を持たない素の Manager。見せかけ: リバースシェル。オラクルは Press への API 200、Drafts への UI 許可、Press への UI 拒否である。
同じピンでの取りこぼし: 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 ステータスではない。
管理者用の ArticleController と同様に、api/components/com_content/src/Controller/ArticlesController.php の allowAdd (および allowEdit) をオーバーライドする: com_content.category.{catid} に対する core.create をチェックする。リクエスト JSON を ApiController::add() に渡し、catid が実際にそのチェックに到達するようにする。これらのコントローラがデフォルトの allowAdd のままであるなら、contacts、banners、newsfeeds にも同じパターンを適用する。
0f2d4de4729eb951e0878fec98c7990da07915b2)ArticlesController.phpApiController.phpGNU Affero GPL v3.0。LICENSE を参照。ループバックラボのみ。無保証。