
Write-up et proof-of-concept pour CVE-2026-94609, une faille d'élévation de privilèges dans authentik permettant aux utilisateurs disposant de add_user_to_group de rejoindre des groupes superutilisateurs via l'API Groups.
Analyse et preuve de concept d'une vulnérabilité d'élévation de privilèges dans goauthentik/authentik, corrigée dans 2026.2.7 / 2026.5.7 / 2026.8.2 et référencée sous CVE-2026-94609 (GHSA-h6c5-mpvq-j4jc).
J'étais l'un des rapporteurs crédités sur cet avis (
@anthonyk2923— crédit accepté). Ce dépôt documente le chemin de code précis que j'ai découvert et signalé de manière indépendante, ainsi qu'un PoC. L'avis publié couvre le problème complet et plus large (hiérarchie des groupes + attribution de rôles), qui a été signalé par plusieurs chercheurs indépendants et corrigé conjointement.
Un compte ne disposant que d'une permission routinière et couramment déléguée —
authentik_core.add_user_to_group (ajouter des membres à un groupe) — pouvait s'ajouter
lui-même ou n'importe quel autre utilisateur directement dans un groupe existant marqué
is_superuser=True via l'API standard des groupes, et cet utilisateur devenait immédiatement
un véritable superutilisateur authentik. Cela se produisait sans jamais détenir
authentik_core.enable_group_superuser, la permission spécifiquement
conçue pour contrôler cette action précise.
authentik avait déjà corrigé la version en miroir de ce bug du côté Utilisateur (attribuer des groupes superutilisateurs à un utilisateur). La vérification équivalente manquait du côté Groupe (attribuer des utilisateurs à un groupe superutilisateur).
| Classe de vulnérabilité | Élévation de privilèges / Contrôle d'accès inapproprié |
| CWE | CWE-269 (Gestion inappropriée des privilèges), CWE-863 (Autorisation incorrecte) |
| CVSS 3.1 | AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H — Élevée |
| Affecté | authentik ≤ 2026.2.6, ≤ 2026.5.6, ≤ 2026.8.1 |
| Corrigé dans | 2026.2.7, 2026.5.7, 2026.8.2 |
| Route accessible | PATCH /api/v3/core/groups/{group_uuid}/ |
| Cause racine | GroupSerializer.validate_users() ne vérifiait jamais enable_group_superuser |
authentik modélise deux permissions RBAC intentionnellement distinctes pour la gestion des appartenances aux groupes :
authentik_core.add_user_to_group — destinée à la gestion routinière et déléguée
des appartenances (par exemple un rôle « helpdesk » ou « chef d'équipe » qui gère
les effectifs quotidiens d'une équipe).authentik_core.enable_group_superuser — destinée à contrôler l'acte bien plus
sensible consistant à accorder ou rejoindre un groupe dont l'indicateur is_superuser=True
fait de chaque membre un superutilisateur authentik complet.Cette séparation existe précisément pour qu'une organisation puisse déléguer largement la gestion ordinaire des groupes, sans pour autant donner la capacité de créer des superutilisateurs.
authentik avait déjà corrigé cette confusion exacte une fois, du côté Utilisateur
de la relation (PATCH /api/v3/core/users/{pk}/ via
UserSerializer.validate_groups()), suivi sous
GHSA-h6x7-hjjc-wjc9 / CVE-2026-40172
(CVSS 8.1, Élevée). Le correctif ajoutait :
# authentik/core/api/users.py (fixed)
def validate_groups(self, groups: list) -> list:
"""Require enable_group_superuser permission when adding a user to a superuser group."""
...
for group in groups:
if not group.is_superuser:
continue
if group in current_groups:
continue
if not request.user.has_perm("authentik_core.enable_group_superuser"):
raise ValidationError(...)
Le chemin de code symétrique du côté Groupe — ajouter des membres à un groupe, plutôt que d'ajouter des groupes à un utilisateur — n'a jamais reçu la vérification équivalente.
GroupSerializer.validate_users() dans authentik/core/api/groups.py ne vérifiait
que add_user_to_group, et n'inspectait jamais self.instance.is_superuser :
# authentik/core/api/groups.py (vulnerable)
def validate_users(self, users: list) -> list:
"""Require add_user_to_group permission when adding new members via group PATCH."""
request: Request = self.context.get("request", None)
if not request:
return users
if not self.instance:
return users
current_user_pks = set(self.instance.users.values_list("pk", flat=True))
new_users = [u for u in users if u not in current_user_pks]
if not new_users:
return users
has_perm = request.user.has_perm(
"authentik_core.add_user_to_group"
) or request.user.has_perm("authentik_core.add_user_to_group", self.instance)
if not has_perm:
raise ValidationError(_("User does not have permission to add members to this group."))
return users
Il n'existe aucune garde if self.instance.is_superuser: require enable_group_superuser
nulle part dans cette méthode. Par conséquent :
Tout appelant qui détient
add_user_to_group— soit globalement, soit limité à un seul groupe superutilisateur spécifique — peut faire unPATCHsur le champusersde ce groupe pour ajouter n'importe quel utilisateur (y compris lui-même), et cet utilisateur devient immédiatement un véritable superutilisateur authentik.
add_user_to_group est exactement le type de permission que le modèle RBAC à granularité fine
d'authentik encourage à déléguer largement et indépendamment de
enable_group_superuser — par exemple à un rôle personnalisé « gestionnaire d'utilisateurs » ou « helpdesk ».
Le test existant
authentik/core/tests/test_groups_api.py::test_patch_users_with_global_perm
démontrait déjà qu'une attribution globale de add_user_to_group (sans
portée d'objet du tout) suffit pour faire un PATCH de membres dans n'importe quel groupe de
l'instance — ce test n'exerçait simplement jamais un groupe avec
is_superuser=True, de sorte que la faille est passée inaperçue.
Il s'agit de la même faille sous-jacente que l'avis publié décrit plus largement : les groupes forment une hiérarchie et le statut de superutilisateur est hérité de tout groupe parent, mais les vérifications contrôlant qui peut modifier l'appartenance à un groupe, la parenté d'un groupe et l'attribution de rôles soit ne recherchaient pas du tout le statut de superutilisateur, soit ne regardaient que l'indicateur propre au groupe plutôt que l'indicateur effectif (hérité).
Élévation de privilèges complète depuis « tout compte détenant une permission routinière et couramment déléguée de gestion des appartenances aux groupes » vers « superutilisateur authentik complet » — qui contrôle chaque tenant, le SSO de chaque application en aval, chaque compte utilisateur, tous les secrets/certificats gérés par authentik, et l'intégralité de la configuration de l'instance.
CVE-2026-94609.py
Un PoC autonome de type client HTTP en direct. Il prend une URL cible et un jeton d'API
pour un compte à faibles privilèges (détenant uniquement add_user_to_group), et
éventuellement un groupe cible/une victime, puis tente la même élévation via
l'API réelle :
# Check your own deployment for the bug, no mutation:
python3 exploit_CVE-2026-94609.py --url https://authentik.example.com \
--token <low-priv-api-token> --group "superadmins" --check-only
# List superuser groups reachable to this token:
python3 exploit_CVE-2026-94609.py --url https://authentik.example.com \
--token <low-priv-api-token> --list-groups
# Attempt the actual escalation (self, or a named/PK victim):
python3 exploit_CVE-2026-94609.py --url https://authentik.example.com \
--token <low-priv-api-token> --group "superadmins" --victim jdoe
Nécessite uniquement pip install requests. Usage autorisé uniquement — exécutez ceci
contre des instances que vous êtes explicitement autorisé à tester.
| Branche | Affectée | Corrigée |
|---|---|---|
| 2026.2.x | ≤ 2026.2.6 | 2026.2.7 |
| 2026.5.x | ≤ 2026.5.6 | 2026.5.7 |
| 2026.8.x | ≤ 2026.8.1 | 2026.8.2 |
Mettez à niveau vers une version corrigée. Si vous ne pouvez pas mettre à niveau immédiatement, selon le contournement de l'avis officiel : restreignez les permissions de créer/modifier des groupes, de modifier des utilisateurs et d'ajouter des utilisateurs aux groupes afin que seuls les administrateurs complets les détiennent — ne déléguez aucune de ces permissions à des rôles non-administrateurs tant que le correctif n'est pas appliqué.
Cette analyse et ce PoC sont fournis à des fins de recherche en sécurité éducative et défensive. Voir la licence propre d'authentik (MIT) pour le projet sous-jacent.