
Persistance de session de listmonk après réinitialisation du mot de passe et changement de mot de passe
Persistance de session dans listmonk après la réinitialisation et le changement de mot de passe
J'ai trouvé ce problème en analysant listmonk, un gestionnaire open-source de lettres d'information et de listes de diffusion, en gardant à l'esprit une simple question de sécurité :
Lorsqu'un utilisateur change ou réinitialise son mot de passe, l'application met-elle réellement fin aux sessions déjà émises ?
Dans ce cas, la réponse était non.
Les sessions authentifiées précédemment émises restaient valides après :
Cela signifiait qu'un cookie de session volé pouvait survivre aux événements de sécurité mêmes sur lesquels les utilisateurs comptent pour récupérer leur compte.
Le problème a été accepté et s'est vu attribuer le CVE-2026-34828.
Projet : listmonk sur GitHub
CVE : CVE-2026-34828
Cela touchait listmonk, un projet largement adopté avec 5M+ téléchargements Docker.
stolen authenticated session → victim resets or changes password → old session remains valid → attacker retains account access after credential recovery
listmonk est un gestionnaire auto-hébergé de listes de diffusion et de lettres d'information.
Il fournit :
Cela signifie que son modèle de session constitue une véritable frontière de sécurité.
La question importante ici n'était pas de savoir si listmonk prend en charge la réinitialisation du mot de passe.
La vraie question était :
La réinitialisation ou le changement de mot de passe révoque-t-il réellement la persistance de l'attaquant si une session a déjà été volée ?
Dans ce cas, non.
Beaucoup de revues de sécurité se concentrent de manière trop étroite sur les contournements de connexion et les escalades de privilèges évidentes.
Elles passent à côté d'une classe importante de faiblesses :
les échecs de récupération
Si un utilisateur change ou réinitialise son mot de passe, cette action est censée avoir un sens.
Elle est censée réduire la confiance accordée aux anciens identifiants et à l'ancien état d'authentification.
Si un attaquant dispose déjà d'une session valide et que cette session survit à l'événement de récupération, alors la victime n'a pas réellement récupéré son compte en totalité.
C'était le problème ici.
Ce n'était pas un bug de validation de connexion. Ce n'était pas un problème cryptographique. Ce n'était pas une défaillance du hachage des mots de passe.
C'était une défaillance du cycle de vie des sessions :
C'est suffisant pour créer une véritable vulnérabilité.
Je n'ai pas abordé listmonk en frappant des points de terminaison au hasard en espérant que l'un d'eux cède.
La voie la plus solide consistait à identifier d'abord la frontière de confiance à plus haute valeur.
Pour les logiciels fortement orientés authentification, l'une des meilleures frontières à tester est celle-ci :
Les modifications de compte sensibles à la sécurité révoquent-elles les sessions précédemment approuvées ?
Cette question devient généralement intéressante autour de :
Dans listmonk, le signal le plus fort provenait des deux premiers.
C'est là que le problème est devenu clair.
Le bug n'était pas que les changements de mot de passe échouaient.
Le bug était que les sessions leur survivaient.
D'après la revue du code source, le flux de réinitialisation du mot de passe :
mais aucune révocation visible des sessions plus anciennes n'était effectuée.
Le même schéma apparaissait dans le flux de changement de mot de passe authentifié :
Ce comportement correspondait exactement aux résultats constatés en conditions réelles.
Les portions de code pertinentes que j'ai examinées étaient :
cmd/auth.go pour le comportement lié à l'oubli et à la réinitialisation du mot de passecmd/users.go pour les mises à jour de profil authentifiéesinternal/core/users.go pour la gestion de la mise à jour du mot de passeParce que le vol de session est une condition d'attaque réelle.
Dès qu'un attaquant obtient un cookie de session authentifié valide par quelque moyen que ce soit, tel que :
la victime devrait pouvoir mettre fin à cette persistance de l'attaquant en changeant ou en réinitialisant son mot de passe.
Ici, elle ne le pouvait pas.
La chaîne d'attaque était simple :
C'est là toute la vulnérabilité.
La distinction importante est la persistance après la récupération.
Beaucoup d'applications traitent le changement de mot de passe comme un événement purement lié aux identifiants. Ce n'est pas suffisant.
La vraie question n'est pas :
« La valeur du mot de passe a-t-elle changé en stockage ? »
La vraie question est :
« La relation de confiance attachée aux sessions plus anciennes a-t-elle été révoquée ? »
Dans listmonk, non.
Cela transforme ce qui aurait pu être une maintenance de compte ordinaire en une récupération de sécurité incomplète.
C'est la différence entre :
J'ai validé le problème dans deux flux distincts.
Tout d'abord, j'ai créé un utilisateur de test normal et je me suis connecté, en enregistrant le cookie de session authentifié.
Ensuite, j'ai déclenché le flux mot de passe oublié, capturé le lien de réinitialisation et réinitialisé le mot de passe.
Après la réinitialisation :
Une requête de validation représentative ressemblait à ceci :
GET /api/profile HTTP/1.1
Host: 127.0.0.1:9000
Cookie: session=<old_pre_reset_session>
Et le serveur renvoyait toujours :
HTTP/1.1 200 OK
Content-Type: application/json
avec le profil authentifié.
Cela établissait l'affirmation centrale :