Ce qui rend un format de stockage récupérable
Quatre formats de stockage, classés par récupérabilité :
| Format | Récupérable ? | Exemple | Méthode de récupération |
|---|---|---|---|
| Texte clair | Oui | password: hunter2 | Lire le fichier |
| Base64 | Oui | cGFzc3dvcmQ= | base64 --decode |
| Chiffrement réversible (AES) | Oui | ENC[AES256:...] | Déchiffrer avec la clé |
| Hachage unidirectionnel (bcrypt) | Non | $2b$12$... | Impossible à inverser ; force brute nécessaire |
Texte clair, base64 et chiffrement réversible : tous récupérables. Un seul dump de la base de données des identifiants donne à un attaquant tous les mots de passe en clair, pour tous les utilisateurs, simultanément. Une seule brèche ; exposition totale.
L’exemple de Mailman 2.x
Mailman 2.x (gestionnaire de listes de diffusion GNU) : stockait les mots de passe des abonnés en texte clair. E-mail mensuel de rappel de mot de passe : envoyait à tous les abonnés leur mot de passe en clair. Deux défauts distincts, tous deux MOAD-0006 :
1. Stockage : texte clair dans la base de données de la liste. Une compromission du serveur expose tous les mots de passe des abonnés.
2. Diffusion : l’e-mail mensuel envoie le mot de passe en clair via SMTP vers le serveur de messagerie de l’abonné. L’e-mail circule en clair sur plusieurs sauts SMTP.
L'équipe Mailman a conçu les deux comportements. La récupération était la fonctionnalité : les abonnés pouvaient récupérer les mots de passe oubliés. Le nom Glass Safe vient de cela : le coffre-fort contient les identifiants sous forme visible. Toute personne qui accède au coffre-fort peut lire tout le contenu simultanément.
Le Principe du Déjà-Volé
Un identifiant stocké sous forme récupérable est un identifiant déjà volé. L'attaquant n'est pas encore arrivé. La violation n'a pas encore eu lieu. Mais l'architecture garantit : lorsqu'une violation se produit, tous les identifiants tombent simultanément. Aucune violation ne se produit de manière isolée ; chaque identifiant dans le stockage récupérable est transféré à l'attaquant dans la même opération.
MOAD-0006 vs MOAD-0004
MOAD-0004 (Secret Journalisé) : identifiants écrits dans les journaux par accident. L'écriture dans le journal n'était pas l'intention ; c'était un effet secondaire de l'activation de la journalisation des en-têtes pour le débogage.
MOAD-0006 (Glass Safe) : identifiants stockés sous forme récupérable par conception. La récupération était l'intention. La fonctionnalité de rappel de mot de passe nécessitait de stocker le mot de passe. La fonctionnalité d'affichage du mot de passe nécessitait de le stocker. L'engagement architectural envers la récupération a créé le défaut.
Distinction en une ligne : MOAD-0004 place les identifiants dans les journaux par accident ; MOAD-0006 stocke les identifiants sous forme récupérable intentionnellement. Les correctifs opèrent à différents niveaux.
Structurel vs Accidentel
La distinction architecturale entre MOAD-0006 et MOAD-0004 détermine la stratégie de correction. Une écriture accidentelle dans les logs : corriger la couche de sérialisation. Un stockage conçu pour la récupération : repenser la fonctionnalité qui nécessitait la récupération.
Pourquoi bcrypt fonctionne
Une fonction de hachage unidirectionnelle accepte un mot de passe et produit un condensat de longueur fixe. Étant donné le condensat, le mot de passe original ne peut pas être récupéré. Pas « difficile à récupérer » : impossible à inverser. La fonction ne s'exécute que dans un sens.
Trois propriétés requises pour le stockage des identifiants :
1. Unidirectionnel (résistance à la préimage). Étant donné hash(password), aucun algorithme ne peut récupérer password plus rapidement qu'une attaque par force brute. bcrypt, scrypt et argon2 satisfont tous cette propriété.
2. Sel. Une valeur aléatoire ajoutée au début du mot de passe avant le hachage. Même mot de passe, sel différent, hachage différent. Objectif : contrer les tables arc-en-ciel (dictionnaires de hachages précalculés). Sans sel : un attaquant calcule hash('password123') une seule fois et vérifie simultanément les 1 million d'utilisateurs. Avec sel : chaque utilisateur a un hachage unique même pour le même mot de passe.
3. Lent par conception. bcrypt accepte un facteur de travail. Facteur de travail plus élevé : plus d'itérations, plus de temps de calcul par tentative de hachage. Connexion : 300 ms pour hacher une fois. Acceptable. Force brute : 300 ms par tentative. À 1 milliard de tentatives : 9,5 ans par mot de passe. Inacceptable pour un attaquant. La lenteur : une fonctionnalité, pas un défaut.
import bcrypt
# Stockage : hachage unidirectionnel avec sel
def store_password(plaintext: str) -> bytes:
return bcrypt.hashpw(plaintext.encode(), bcrypt.gensalt(rounds=12))
# Vérifier : hacher le candidat et comparer les empreintes
def verify_password(plaintext: str, stored_hash: bytes) -> bool:
return bcrypt.checkpw(plaintext.encode(), stored_hash)
# JAMAIS stocké : le mot de passe en clair
# JAMAIS récupéré : le texte en clair à partir du hash
# Réinitialisation du mot de passe, pas rappel du mot de passe
Le compromis
Le hachage unidirectionnel rend impossible la récupération du mot de passe. Un utilisateur qui oublie son mot de passe ne peut pas le récupérer. Un e-mail de rappel de mot de passe ne peut pas exister. L'expérience utilisateur change : « mot de passe oublié ? réinitialisez-le ». Ce n'est pas une dégradation : c'est une limite de sécurité. Le système qui ne peut pas récupérer un mot de passe ne peut pas divulguer un mot de passe.
Une violation de base de données qui expose des hachages bcrypt : tous les hachages visibles, aucun mot de passe visible. Un attaquant doit forcer chaque hachage individuellement, à 300 ms par tentative, avec un sel par utilisateur qui neutralise les tables précalculées. Une violation qui expose des mots de passe en clair : exposition totale et immédiate.
Le chiffrement fort ne suffit pas
Un audit de sécurité identifie un système de stockage des identifiants. Les mots de passe sont stockés à l'aide du chiffrement AES-256-CBC avec une clé côté serveur. Le rapport d'audit le signale comme un défaut Glass Safe.
L'équipe d'ingénierie répond : « AES-256 est le chiffrement symétrique le plus robuste disponible. La clé réside dans un module de sécurité matériel. Aucun attaquant ne peut déchiffrer ces mots de passe. »