Session Flask : décoder, casser le secret et forger un cookie
Un cookie de session Flask est signé, pas chiffré. Son contenu reste donc lisible par n’importe qui, et son intégrité repose entièrement sur une clé secrète serveur, la SECRET_KEY. Si cette clé est faible, on la retrouve hors ligne, on modifie le payload et on resigne un cookie valide pour se faire passer pour un autre acteur.
Cette fiche suppose que le cookie a déjà été identifié comme un cookie Flask. La reconnaissance au préfixe .eJw et au nom session= est détaillée dans la fiche « Fingerprint cookie Flask ».
Lire le payload
Section intitulée « Lire le payload »Le payload étant seulement compressé et encodé, il se décode sans aucun secret. CyberChef permet une lecture rapide en chaînant les opérations From Base64 puis Zlib Inflate. En ligne de commande, flask-unsign fait la même chose directement.
pip3 install flask-unsign
flask-unsign --decode --cookie '<COOKIE>'La sortie révèle le contenu de session, par exemple :
{'logged_in': True, 'user': 'alice'}À ce stade, on voit les données que le serveur fait confiance, mais on ne peut pas encore les modifier : toute altération invaliderait la signature.
Casser la clé secrète
Section intitulée « Casser la clé secrète »Pour forger un cookie accepté, il faut la SECRET_KEY qui signe. flask-unsign teste chaque mot d’un dictionnaire en resignant le payload jusqu’à retrouver la signature d’origine. La rockyou.txt fait un premier dictionnaire efficace.
cd /usr/share/wordlistsgunzip rockyou.txt.gz
flask-unsign --wordlist /usr/share/wordlists/rockyou.txt \ --unsign --cookie '<COOKIE>' --no-literal-eval--unsignlance la recherche de la clé.--wordlistfournit le dictionnaire.--no-literal-evalévite d’interpréter le payload comme du code Python, utile quand son contenu n’est pas un littéral propre.
Si la clé est faible ou par défaut, flask-unsign l’affiche. Une clé forte et aléatoire résiste à cette attaque, c’est tout l’intérêt de la mesure de protection.
Forger un cookie modifié
Section intitulée « Forger un cookie modifié »Avec la clé en main, on resigne un payload modifié. Ici, on remplace l’utilisateur pour usurper un compte privilégié.
flask-unsign --sign \ --cookie "{'logged_in': True, 'user': 'admin'}" \ --secret '<SECRET_TROUVE>'flask-unsign renvoie un cookie complet et valide. Il ne reste qu’à remplacer la valeur session= dans la requête, via Burp ou l’inspecteur du navigateur, et à la rejouer. Le serveur vérifie la signature, la trouve correcte, et traite la session forgée comme légitime.
Remédiation
Section intitulée « Remédiation »Une SECRET_KEY forte et secrète
Section intitulée « Une SECRET_KEY forte et secrète »La signature ne vaut que par sa clé. Elle doit être longue, aléatoire et jamais commitée dans le dépôt.
import secretsapp.config['SECRET_KEY'] = secrets.token_hex(32) # 256 bits aléatoiresEn production, la clé se charge depuis une variable d’environnement ou un gestionnaire de secrets, jamais en dur dans le code.
Ne pas placer de décision de sécurité dans le cookie
Section intitulée « Ne pas placer de décision de sécurité dans le cookie »Un cookie côté client reste modifiable par définition, la signature ne fait que détecter l’altération. Les données sensibles (rôle, droits) ne doivent pas déterminer une autorisation sur leur seule présence. Le serveur doit revérifier les droits à chaque accès, à partir d’une source de confiance.
Préférer des sessions côté serveur
Section intitulée « Préférer des sessions côté serveur »Stocker l’état de session côté serveur (extension Flask-Session avec Redis, base ou système de fichiers) ne laisse au client qu’un identifiant opaque. Il n’y a plus de payload à lire ni à forger.
À retenir
Section intitulée « À retenir »Un cookie Flask se lit sans secret et se forge dès que la SECRET_KEY est faible. La chaîne est directe : décoder le payload, casser la clé au dictionnaire avec flask-unsign, resigner un contenu modifié. La défense tient en une clé forte et secrète, et surtout dans le principe de ne jamais faire reposer une autorisation sur une donnée que le client peut présenter lui-même.