Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Submit
ToolsExploitsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

FeedsContactPrivacy© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
joomla-articles-catid — Joomla 6.1.3 - High - Remote - ACL - POST /api/v1/content/articles ignores per-category ACL | Kitploit
Tools/GitHubGitHub/abraxas/joomla-articles-catid
Authentication & AuthorizationVulnerability AnalysisExploitationWeb Application ExploitationWeb SecurityPenetration TestingAPI SecurityLabs & Practice
GitHubabraxas/joomla-articles-catid

joomla-articles-catid

Joomla 6.1.3 - High - Remote - ACL - POST /api/v1/content/articles ignores per-category ACL

View Repository
4 days agoNot yet reviewed

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

Abraxas Labs - joomla-articles-catid

abraxaslabs.tech  ·  github.com/abraxas  ·  @abraxas_null  ·  [email protected]  ·  joomla-articles-catid

joomla-articles-catid

Class: Privilege leftover Reach: Remote

Joomla CMS 6.1.3 (0f2d4de) - Open Source Matters

Administrator ArticleController::allowAdd checks com_content.category.{catid}. api/components/com_content/src/Controller/ArticlesController.php has no allowAdd. ApiController::add() then calls allowAdd() with no data, so the JSON catid never enters the check. Base allowAdd is true if the user can create in any category.

A Manager-class API user, granted core.login.api and create on one category, can POST an article into a category they are denied in the UI.

IDno CVE yet
ClassPrivilege leftover / authorization bypass
ReachRemote (API token with core.login.api)
CWECWE-863
CVSSMedium: 6.5 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:N
ProductJoomla CMS
Affected6.1.3 (0f2d4de4729eb951e0878fec98c7990da07915b2), POST /api/index.php/v1/content/articles
AuthAPI token for Manager (group 6) with core.login.api, com_content core.manage, and core.create on one category only. No Super User. Default core.login.api is Super User only.
LicenseGNU Affero GPL v3.0
Lab127.0.0.1 only

What an attacker can do

Use a non-Super-User API token that may create in one category to publish into categories they are banned from. They do not become Super User from this leftover. This is unauthorized publishing, not a site takeover and not a read of hidden articles.

PrivilegeMethod / pathKindLab-proven or inferred
Create an article in a category they are deniedPOST /api/index.php/v1/content/articles JSON catid of BintegrityLab-proven. HTTP 200, #__content id=1, catid=9 (Press), title poc-art-JOOMLA-ARTICLES-CATID-WITNESS
Plant published copy in Official notices / Press while only allowed DraftsSame POST, state=1integrityLab-proven create into denied Press. Inferred for any other category asset with core.create denied
Edit an existing article via the APIPATCH /api/index.php/v1/content/articles/{id}n/aInferred closed for this Manager. Base allowEdit needs component core.edit; lab com_content rules give core.edit to Author (4), not Manager (6). Lab did not PATCH
Delete an article via the APIDELETE /api/index.php/v1/content/articles/{id}n/aInferred closed. Base allowDelete needs component core.delete. Lab did not DELETE
Save an article into allowed category A from administratorPOST ... task=article.save jform[catid]=AintendedLab-proven open as intended. HTTP 200, not denied
Save an article into denied category B from administratorSame task, jform[catid]=Bn/aLab-proven closed. HTTP 200 with "not permitted" / create-not-permitted (UI allowAdd on com_content.category.B)
Hit the API with a stock Manager (no core.login.api)Bearer token / X-Joomla-Tokenn/aInferred closed. Default core.login.api is Super User (group 8) only. This lab grants it to group 6 first
Same gap on contacts / banners / newsfeedsPOST /api/index.php/v1/contacts (and siblings) with foreign catidintegrityInferred. Those API controllers also lack allowAdd. Lab did not exercise them
Super User / installer RCEn/an/aClosed. Manager stays Manager

How I found it

I pinned 6.1.3 after the 2026-07/08 JSST wave. Groups API already requires core.admin. Media webservice already requires core.edit on override. Articles API still falls through ApiController and treats "create in any category" as enough for every catid.

public function add()
{
    if (!$this->allowAdd()) {
        throw new NotAllowed('JLIB_APPLICATION_ERROR_CREATE_RECORD_NOT_PERMITTED', 403);
    }
    $recordId = $this->save();
    $this->displayItem($recordId);
}

Base check:

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 already keys off 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();
}

Wrong turns already recorded: reading UI HTTP 200 as allow (denial of B is the "not permitted" body); treating component core.create as the hole (the lab Manager has none; one category allow is enough for the base getAuthorisedCategories count); a stock Manager without core.login.api. Theatre: a reverse shell. The oracle is API 200 into Press plus UI allow on Drafts plus UI deny on Press.

Same pin leftovers: levels API, menu items API, media override.

Lab

python3 joomla-articles-catid-Abraxas-Labs.py

or

cd lab
./run.sh

Target only http://127.0.0.1:19550. Image joomla:6.1.3-php8.3-apache plus 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 is the next #__content autoincrement (1 on a clean 6.1.3 install). ui-a / ui-b are HTTP 200; denial of B is the UI "not permitted" body, not a 403 status.

The fix

Override allowAdd (and allowEdit) on api/components/com_content/src/Controller/ArticlesController.php the same way as administrator ArticleController: check core.create on com_content.category.{catid}. Pass the request JSON into ApiController::add() so catid actually reaches that check. Apply the same pattern to contacts, banners, and newsfeeds if those controllers stay on the default allowAdd.

References

Download Tool