
Joomla 6.1.3 - 높음 - 원격 - ACL - POST /api/v1/content/articles가 카테고리별 ACL을 무시함
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · joomla-articles-catid
분석 문서: https://abraxaslabs.tech/research/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입니다.
core.login.api와 한 카테고리에 대한 생성 권한을 부여받은 Manager 등급 API 사용자는, UI에서 거부된 카테고리로 기사를 POST할 수 있습니다.
| ID | 아직 CVE 없음 |
| 분류 | 권한 잔여 / 인가 우회 |
| 도달 범위 | 원격 (core.login.api가 있는 API 토큰) |
| 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 |
| 인증 | core.login.api, com_content core.manage, 그리고 하나의 카테고리에 대한 core.create를 가진 Manager(그룹 6)용 API 토큰. Super User 아님. 기본 core.login.api는 Super User 전용입니다. |
| 라이선스 | GNU Affero GPL v3.0 |
| 랩 | 127.0.0.1 전용 |
하나의 카테고리에서 생성할 수 있는 비-Super-User API 토큰을 사용하여, 자신이 금지된 카테고리로 게시할 수 있습니다. 이 잔여 권한으로 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 |
| 초안만 허용된 상태에서 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로 글 저장 | 동일한 task, jform[catid]=B | n/a | 실험실 입증 차단됨. HTTP 200과 함께 "not permitted" / create-not-permitted (UI allowAdd on com_content.category.B) |
기본 Manager( core.login.api 없음)로 API 호출 | Bearer 토큰 / X-Joomla-Token | n/a | 차단된 것으로 추론. 기본 core.login.api는 Super User(그룹 8) 전용임. 이 실험실에서는 먼저 그룹 6에 이를 부여함 |
| contacts / banners / newsfeeds에서 동일한 결함 | POST /api/index.php/v1/contacts (및 유사 엔드포인트)에 외부 catid 지정 | 무결성 | 추론. 해당 API 컨트롤러들도 allowAdd가 없음. 실험실에서 이를 실행하지는 않음 |
| Super User / 설치 프로그램 RCE | n/a | n/a | 차단됨. Manager는 Manager로 유지됨 |
2026-07/08 JSST 파동 이후 6.1.3을 고정했습니다. Groups API는 이미 core.admin을 요구합니다. Media 웹서비스는 이미 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'));
}
Administrator 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. 연극: 리버스 셸. 오라클은 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 autoincrement 값입니다(클린 6.1.3 설치 시 1). ui-a / ui-b는 HTTP 200이며, B에 대한 거부는 403 상태가 아니라 UI의 "not permitted" 본문입니다.
administrator의 ArticleController와 동일한 방식으로 api/components/com_content/src/Controller/ArticlesController.php에서 allowAdd(및 allowEdit)를 재정의합니다. com_content.category.{catid}에 대해 core.create를 확인합니다. 요청 JSON을 ApiController::add()에 전달하여 catid가 실제로 해당 검사에 도달하도록 합니다. contacts, banners, newsfeeds 컨트롤러가 기본 allowAdd를 그대로 사용하는 경우에도 동일한 패턴을 적용합니다.
0f2d4de4729eb951e0878fec98c7990da07915b2)ArticlesController.phpApiController.phpGNU Affero GPL v3.0. LICENSE를 참조하세요. 루프백 랩 전용입니다. 보증은 제공되지 않습니다.