5.2 KiB
SEC-02 — Un manager peut modifier une autre organisation
Gravité historique : Élevée. Classification : CWE-863.
État au 14 septembre 2026 : Corrigé dans le code suivi. Tout acteur autre que UserRole.ADMIN est refusé lorsque l'organisation cible diffère de celle de sa session, indépendamment de la casse qui avait déclenché le problème.
Executive Summary
Un MANAGER connecté connaît l'UUID d'une autre organisation. Il peut appeler PATCH /api/v1/organizations/:id. Le rôle de gestion est légitime pour sa propre organisation ; il ne doit pas permettre de modifier celle d'Alice.
Cette fiche repose sur la relecture du code historique accessible et du correctif courant, ainsi que des preuves documentées lors des passes précédentes. Elle ne constate aucun incident réel. La plus ancienne version ici vérifiée est le snapshot 8446f87 ; les corrections historiques figurent dans c09b8be. Aucun tag local ni version déployée n'a permis d'établir une première release vulnérable ou corrigée. Voir METHODOLOGIE.md.
Background
Le rôle autorise une catégorie d’opérations, tandis que organizationId délimite le client concerné. Les deux conditions doivent tenir ensemble, sauf exception explicite pour l’administrateur de plateforme.
Vulnerability Details
JwtStrategy expose le rôle de l'utilisateur tel qu'il est stocké. RolesGuard compare les rôles sans tenir compte de la casse, mais ne transforme pas la valeur portée par la requête. Dans updateOrganization, l'ancien test user.role === 'manager' ne s'applique donc pas à MANAGER. Après lecture de l'organisation par son UUID, le contrôleur met à jour les champs demandés, y compris le statut actif, puis appelle organizationRepository.save. Le contrôle global du rôle laisse passer la requête tandis que le contrôle local du tenant est sauté.
Extrait historique vérifié, apps/backend/src/application/controllers/organizations.controller.ts, lignes 241–256 du snapshot préaudit :
async updateOrganization(
@Param('id', ParseUUIDPipe) id: string,
@Body() dto: UpdateOrganizationDto,
@CurrentUser() user: UserPayload
): Promise<OrganizationResponseDto> {
this.logger.log(`[User: ${user.email}] Updating organization: ${id}`);
const organization = await this.organizationRepository.findById(id);
if (!organization) {
throw new NotFoundException(`Organization ${id} not found`);
}
// Authorization: Managers can only update their own organization
if (user.role === 'manager' && organization.id !== user.organizationId) {
throw new ForbiddenException('You can only update your own organization');
}
Les numéros ci-dessus décrivent le snapshot ancien ; les liens suivants ouvrent les fichiers courants, où les lignes peuvent avoir changé.
Sources à examiner ensemble :
- apps/backend/src/application/auth/jwt.strategy.ts
- apps/backend/src/application/guards/roles.guard.ts
- apps/backend/src/application/controllers/organizations.controller.ts
Exploitability Analysis
Modification de données d'une autre organisation et retour de sa fiche : l'atteinte à l'isolation entre clients est directe. L'attaquant ne devient pas ADMIN et ne peut pas contourner l'authentification. La connaissance de l'UUID cible reste un prérequis ; aucune méthode universelle de découverte de ces UUID n'est établie ici.
Le code applicatif établit le chemin décrit, mais ne renseigne pas les protections effectives d'un déploiement donné, sa version en ligne ou les accès déjà exercés par un attaquant. La gravité ci-dessus est celle du mécanisme vulnérable avant correction ; elle n'est pas un score de risque résiduel calculé pour la production.
Proof of Concept
Tests de non-régression existants, inspectables dans le dépôt :
Ils testent les refus et les usages autorisés avec des données locales. Ils ne prouvent pas qu'une ancienne exploitation a eu lieu en production. Les commandes et résultats consolidés sont dans VALIDATION.md ; aucun nouvel exploit n'a été exécuté pendant la rédaction.
Remediation
Corrigé dans le code suivi. Tout acteur autre que UserRole.ADMIN est refusé lorsque l'organisation cible diffère de celle de sa session, indépendamment de la casse qui avait déclenché le problème.
Pour solder le constat en exploitation, vérifier le comportement sur la version effectivement déployée et conserver les contrôles légitimes décrits. La présente passe ajoute uniquement de la documentation ; les correctifs mentionnés existaient avant sa rédaction.
Summary
Un manager peut modifier une autre organisation est un constat historique de l'audit, à lire avec son état courant ci-dessus. La preuve porte sur le mécanisme et les contrôles cités ; elle ne constitue ni une attestation d'exploitation réelle ni une certification exhaustive du projet.