
Joomla 6.1.3 - Élevé - À distance - ACL - GET /api/v1/users/levels divulgue les niveaux de visibilité
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · joomla-levels-api
Classe : Privilège résiduel Portée : Distante
Joomla CMS 6.1.3 (0f2d4de) - Open Source Matters
Administrateurs Utilisateurs -> Afficher les niveaux d'accès nécessite core.admin sur com_users (LevelController::allowSave et suppression). Le webservice Groups fait déjà de même (GroupsController, 6.1.1). LevelsController n'a pas de surcharge allowAdd, allowEdit ou delete, donc ApiController laisse passer core.manage plus core.create.
Un jeton API de classe Manager, accordé core.login.api sans core.admin, peut créer des niveaux d'accès en visualisation que l'interface interdit.
| ID | pas encore de CVE |
| Classe | Privilège résiduel / contournement d'autorisation |
| Portée | Distante (jeton API avec core.login.api) |
| CWE | CWE-863 |
| CVSS | Moyen : 6.1 CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:N |
| Produit | Joomla CMS |
| Affecté | 6.1.3 (0f2d4de4729eb951e0878fec98c7990da07915b2) |
| Auth | Jeton API pour Manager (groupe 6) avec core.login.api et com_users manage/create/edit. Pas de core.admin. Par défaut, core.login.api est réservé au Super Utilisateur. |
| Licence | GNU Affero GPL v3.0 |
| Lab | 127.0.0.1 uniquement |
Utiliser un jeton API non-Super-Utilisateur pour modifier quels groupes voient quelles pages. Il ne devient pas Super Utilisateur à partir de ce seul privilège résiduel. Il s'agit d'un contrôle de visibilité du contenu, pas d'une prise de contrôle du site.
| Privilège | Méthode / chemin | Type | Prouvé en lab ou déduit |
|---|---|---|---|
| Créer un niveau d'accès en visualisation | POST /api/index.php/v1/users/levels JSON title, rules (ids de groupe) | intégrité | Prouvé en lab. HTTP 200, #__viewlevels id=7, titre poc-level-JOOMLA-LEVELS-API-WITNESS |
| Modifier un niveau existant (liste de groupes / titre) | PATCH /api/index.php/v1/users/levels/{id} | intégrité | Déduit. Même contrôleur, pas de allowEdit. Lab : création uniquement. |
| Supprimer un niveau | DELETE /api/index.php/v1/users/levels/{id} | intégrité / disponibilité des lignes ACL | Déduit. Même surcharge manquante. Le lab n'a pas effectué de DELETE. |
| Exposer un article, module ou élément de menu réservé aux membres | Nouveau niveau ou niveau modifié dont les rules incluent Public / Invité / Enregistré | reconnaissance (visibilité du contenu) | Déduit de #__viewlevels.rules. Le lab a inséré la ligne ; il n'a pas re-ACL un article en production. |
| Masquer une page aux Enregistrés, ou ajouter le groupe de l'attaquant à un niveau Spécial | Même PATCH / création | intégrité | Déduit. Même stockage. |
| Modifier les groupes d'utilisateurs depuis l'API | POST /api/index.php/v1/users/groups | n/a | Prouvé en lab fermé. HTTP 403 (GroupsController core.admin) |
| Ouvrir Utilisateurs -> Afficher les niveaux d'accès dans l'administrateur | GET /administrator/index.php?option=com_users&view=levels | n/a | Prouvé en lab fermé. HTTP 403 |
| Enregistrer un niveau depuis l'interface | POST ... task=level.save | n/a | Prouvé en lab fermé. HTTP 403 (LevelController::allowSave nécessite core.admin) |
Solliciter l'API avec un Manager standard (sans core.login.api) | Jeton Bearer / X-Joomla-Token | n/a | Déduit fermé. Par défaut, core.login.api est réservé au Super Utilisateur (groupe 8). Ce lab l'accorde d'abord au groupe 6. |
| RCE Super Utilisateur / installateur | n/a | n/a | Fermé. Le Manager reste Manager. |
J'ai épinglé joomla/joomla-cms 6.1.3 après la vague JSST de 2026-07/08. L'API Groups exige déjà core.admin. Les niveaux de visualisation passent toujours par ApiController (core.manage plus core.create / core.edit / core.delete). La seule logique supplémentaire sur LevelsController est le décodage JSON de rules pour PATCH.
Sibling Groups corrigé :
public function allowAdd($data = [])
{
return $this->app->getIdentity()->authorise('core.admin', $this->option);
}
Interface administrateur :
protected function allowSave($data, $key = 'id')
{
return $this->app->getIdentity()->authorise('core.admin', $this->option)
&& parent::allowSave($data, $key);
}
Fausses pistes déjà consignées : considérer l'API Groups comme encore ouverte (elle renvoie 403) ; solliciter l'API avec un Manager standard sans accorder d'abord core.login.api (par défaut réservé au Super Utilisateur, même configuration que CVE-2026-71574 / 72531 / 48904) ; lire le 403 de l'interface comme l'histoire complète (le privilège résiduel est dans l'API). Théâtre : un reverse shell. L'oracle est API 200 plus Groups 403 plus UI 403.
Autres privilèges résiduels du même pin : API des éléments de menu, surcharge média, catid des articles.
python3 joomla-levels-api-Abraxas-Labs.py
ou
cd lab
./run.sh
Cible uniquement http://127.0.0.1:19520. Image joomla:6.1.3-php8.3-apache plus mariadb:11.4.
SUCCESS joomla-levels-api api-http=200 level-id=7 groups-api=403 ui-view=403 ui-save=403 JOOMLA-LEVELS-API-WITNESS
Copier allowAdd / allowEdit / delete avec core.admin de GroupsController vers LevelsController. Conserver la barrière de l'interface administrateur.
0f2d4de4729eb951e0878fec98c7990da07915b2)LevelsController.phpcore.admin (6.1.1) · CVE-2026-71574GNU Affero GPL v3.0. Voir LICENSE. Lab en boucle locale uniquement. Aucune garantie.