Rejouer un retrait signé : réutilisation de nonce et double dépense

Sécurité des Cryptomonnaies & Blockchain Niveau 3/4 ~5 min 23 août 2026

Le défi

Cette API de portefeuille dépositaire signe chaque retrait avec un nonce à usage unique pour qu'une requête ne puisse pas servir deux fois. Sauf qu'elle n'enregistre jamais quels nonces elle a déjà dépensés. Envoyez d'abord votre retrait frais pour le voir réussir, puis renvoyez un nonce d'un retrait signé antérieur et regardez le même argent partir deux fois. Lisez le flag que le double-paiement laisse fuiter.

Ce que tu vas apprendre

  • Reconnaître une attaque par rejeu où une requête signée, autrefois valide, est renvoyée pour répéter son effet
  • Comprendre l'objectif d'un nonce à usage unique et pourquoi il échoue s'il n'est pas suivi côté serveur
  • Exécuter un exploit en deux étapes : envoyer une requête fraîche, puis rejouer une requête antérieure
  • Lire les réponses de l'API pour confirmer qu'une double dépense a été acceptée
  • Expliquer pourquoi les nonces doivent être marqués comme consommés de façon durable et les doublons rejetés de manière atomique

Compétences testées

Inspection des requêtes HTTP et manipulation en plusieurs étapes avec un éditeur de type proxyIdentification des vulnérabilités de rejeu et de réutilisation de nonceLecture et interprétation des réponses JSON d'une APIRaisonnement sur l'idempotence et l'état dans les API financières

Prérequis

  • Compréhension de base des requêtes HTTP et des corps JSON
  • Connaissance du concept de nonce en tant que valeur à usage unique
  • Conscience qu'un retrait déplace des fonds et ne devrait se produire qu'une seule fois par autorisation

Comment ça marche

Un nonce (nombre utilisé une seule fois) est censé rendre une requête signée à usage unique : chaque retrait est autorisé avec un nonce unique, de sorte que capturer et renvoyer la requête ne puisse pas déplacer l'argent une seconde fois. La protection ne fonctionne que si le serveur se souvient des nonces déjà réglés et refuse toute répétition. Cette API génère et vérifie la signature du nonce, mais ne conserve jamais d'enregistrement des nonces dépensés, si bien que le même nonce peut être présenté autant de fois que l'attaquant le souhaite.

Cette lacune se transforme en attaque par rejeu. Un retrait antérieur, le nonce 41, avait déjà été signé et exécuté. Comme rien ne marque 41 comme consommé, le renvoyer est de nouveau accepté et le portefeuille diffuse le même transfert une seconde fois, une double dépense. Aucune signature n'a été forgée et aucune valeur n'a été modifiée ; la requête originale, légitimement signée, a simplement été rejouée. C'est l'une des failles les plus courantes dans les flux de paiement, de portefeuille et d'autorisation, et c'est pourquoi l'idempotence est une propriété de sécurité, pas seulement une propriété de fiabilité.

L'exploit se déroule intrinsèquement en deux étapes, ce qui le place au-dessus d'une simple modification d'un champ : vous envoyez d'abord votre propre nonce frais pour établir que l'endpoint fonctionne et voir à quoi ressemble un règlement réel, puis vous rejouez un nonce antérieur et observez le doublon être accepté. Comprendre pourquoi 42 réussit une fois mais 41 réussit à nouveau est toute la leçon.

Erreurs fréquentes

  • Incrémenter le nonce vers une valeur future comme 43 et abandonner face au 409 : les nonces supérieurs ne sont pas encore signés par le portefeuille, ils sont donc correctement rejetés.
  • Supposer que la signature de la requête rend son renvoi sûr, alors qu'une signature prouve l'authenticité, pas l'usage unique.
  • Envoyer seulement le nonce frais et conclure que l'API est saine, en manquant le fait que la faille n'apparaît que lorsqu'un nonce déjà réglé est rejoué.
  • Considérer cela comme un bug de manipulation plutôt que la vraie faille : la requête est inchangée et légitimement signée ; le serveur a simplement oublié qu'il avait déjà honoré ce nonce.

Comment s'en protéger

Rendez chaque nonce véritablement à usage unique en enregistrant durablement sa consommation et en rejetant toute réutilisation avant que les fonds ne se déplacent. Un nonce qui n'est pas suivi n'est qu'un décor, pas une défense.

  • Conservez chaque nonce réglé par compte et rejetez les doublons ; ou imposez une séquence strictement croissante par compte et refusez toute valeur non supérieure à la dernière valeur réglée.
  • Rendez la vérification de dépense et le règlement atomiques (une seule transaction ou une contrainte d'unicité sur compte plus nonce) afin que des rejeux concurrents ne puissent pas gagner la course tous les deux.
  • Liez l'autorisation signée à tous les champs déterminants (montant, actif, destination, nonce, identifiant de chaîne) ainsi qu'à une courte expiration, afin qu'une requête capturée ne puisse pas être réutilisée plus tard ni contre un transfert différent.
  • Journalisez et alertez sur toute requête présentant un nonce déjà consommé, car il s'agit sans ambiguïté d'une tentative de rejeu.

Solution complète

Les membres Pro et Max débloquent la solution complète étape par étape.

Passer Pro

Statistiques de la communauté

111 résolutions
79% taux de réussite
M2F14M3 Premier sang

Hacks du jour associés

25 000+ Hackers 100+ Labs & Cours Gratuit
Commencer Gratuitement