Un code TOTP n'est pas intrinsèquement à usage unique. Il est valide pendant un intervalle de temps — le pas de temps, généralement trente secondes, souvent élargi par la tolérance de décalage d'horloge. Ce qui le rend à usage unique, c'est le vérificateur, s'il mémorise les codes déjà consommés. À défaut, le même code reste utilisable jusqu'à la fin de sa fenêtre, et plusieurs cas de rejeu réapparaissent.
Trois formes de rejeu, trois responsabilités
Le rejeu dans la fenêtre. L'attaquant obtient le code — par hameçonnage, par observation ou par un appel frauduleux — et l'utilise pendant que la fenêtre court. Si le serveur n'a pas invalidé le code consommé par la victime, la seconde utilisation aboutit. La responsabilité est entièrement côté implémentation.
Le rejeu croisé entre services. Une même graine enrôlée sur plusieurs points d'entrée — portail web, accès distant, application métier — produit le même code partout. Un code capturé lors d'une authentification sur le portail est alors rejouable sur l'accès distant, car chaque vérificateur tient sa propre mémoire des codes consommés, sans la partager avec les autres. Ce cas est fréquent dans les systèmes d'information hétérogènes, et rarement testé.
Le rejeu de la conséquence. Le jeton de session émis après l'authentification est réutilisable jusqu'à expiration ou révocation. C'est la forme de rejeu la plus rentable, et aucun paramètre du TOTP ne l'influence.
| Forme de rejeu | Possible avec TOTP ? | Condition | Correctif |
|---|---|---|---|
| Réutilisation après expiration | Non | — | Propriété du mécanisme |
| Réutilisation dans la fenêtre | Oui | Code non invalidé après usage | Mémorisation des codes consommés |
| Tolérance de décalage élargie | Oui | Plusieurs pas acceptés | Limiter à un pas de part et d'autre |
| Rejeu sur un autre service | Oui | Graine partagée, mémoires cloisonnées | Graines distinctes par service |
| Rejeu du cookie de session | Oui | Session valide et non liée au poste | Révocation, sessions courtes, liaison au dispositif |
| Rejeu d'un code de secours | Non, mais usage unique différé | Code non consommé | Inventaire et alerte à l'usage |
Ce que le mécanisme protège réellement
Comparé à un mot de passe, l'apport est net. Un mot de passe capturé conserve sa valeur pendant des mois, souvent jusqu'à un changement contraint. Un code TOTP capturé perd la sienne en moins d'une minute, ce qui exclut de fait les attaques différées : les listes d'identifiants vendues en lot ne contiennent rien d'exploitable côté second facteur.
C'est la raison pour laquelle un attaquant sérieux ne collecte plus les codes pour plus tard : il les relaie en direct, ou il vise directement la session. Le TOTP a donc modifié la nature des attaques, sans les empêcher.
Le cas du décalage d'horloge, souvent mal réglé
La tolérance de décalage existe parce que les horloges dérivent. Elle mérite un examen, car deux réglages courants dégradent la sécurité sans nécessité.
Une tolérance trop large. Accepter plusieurs minutes de décalage multiplie le nombre de codes valides simultanément, ce qui élargit la fenêtre de rejeu et facilite la force brute.
La resynchronisation automatique permissive. Certains vérificateurs proposent, en cas d'échecs répétés, de resynchroniser l'horloge à partir de codes fournis par l'utilisateur. Mal encadrée, cette fonction devient un oracle : elle accepte plusieurs essais, indique implicitement quand la valeur est correcte, et peut être déclenchée par un attaquant.
La bonne pratique : un pas de temps de part et d'autre au maximum, resynchronisation manuelle et tracée, alerte lorsque le décalage constaté est important.
Fermer la dernière forme de rejeu
Les deux premières formes se corrigent par la configuration. La troisième — le rejeu de la session — demande un changement d'approche, car elle n'est pas un défaut d'implémentation mais une conséquence du modèle : on authentifie une entrée, puis on fait confiance.
Deux orientations la traitent.
Faire varier ce qui est observé. Une exécution mouvante (Moving Target Defense), où les paramètres changent en continu, prive un attaquant de cible stable à rejouer : ce qui a été capturé n'est plus valide au moment de l'utilisation.
Rattacher la preuve à l'acte. Une opération sensible exige alors une validation produite dans son propre contexte, impossible à fournir depuis une session héritée. C'est la logique de l'authentification cognitive, fondée sur un challenge résolu au moment de l'action, sans secret réutilisable ni valeur mémorisable par un tiers.
Tests à inscrire dans une recette
- Saisir deux fois le même code, sur le même service, dans la même fenêtre : la seconde tentative doit échouer.
- Saisir un code obtenu sur le service A sur le service B partageant la même graine : l'acceptation révèle un cloisonnement insuffisant.
- Mesurer la tolérance réelle de décalage, en pas de temps.
- Tenter une resynchronisation d'horloge sans authentification préalable.
- Vérifier que la révocation de session est effective sur toutes les applications fédérées, pas seulement sur le portail principal.
FAQ
Un code TOTP est-il vraiment à usage unique ?
Seulement si le vérificateur mémorise les codes déjà acceptés. La spécification décrit un code valable sur un intervalle ; l'unicité d'usage est une obligation d'implémentation, pas une propriété automatique.
Faut-il une graine différente par service ?
Oui pour les services sensibles. Le partage d'une graine unique entre plusieurs points d'entrée crée un chemin de rejeu croisé et complique la révocation en cas de compromission.
Réduire la fenêtre à quinze secondes améliore-t-il la sécurité ?
Marginalement, au prix d'échecs plus nombreux pour les utilisateurs dont l'horloge dérive. Le gain est très inférieur à celui obtenu par l'invalidation des codes consommés et la limitation des tentatives.
Comment détecter un rejeu réussi ?
Cherchez deux authentifications acceptées à quelques secondes d'intervalle pour un même compte depuis des contextes différents, ou une session ouverte depuis une origine sans rapport avec le poste habituel de l'utilisateur.
Aller plus loin : le 4ᵉ facteur cognitif · Moving Target Defense contre le rejeu · vol de session : ce qui reste possible · MFA résistante au phishing