Comment un stock de mille places peut-il disparaître en huit secondes alors que le site ne comptait, au même moment, qu’une poignée de centaines de visiteurs actifs ? C’est la question que s’est posée l’équipe technique d’un festival après l’ouverture de sa billetterie en ligne, hébergée sur WordPress avec une extension de vente de billets. Le calcul est simple : personne ne remplit un formulaire de commande, ne choisit un moyen de paiement et ne le confirme en une fraction de seconde. Un humain, en tout cas, ne le fait pas.
L’analyse des journaux serveur a confirmé le soupçon : un script automatisé passait commande en boucle, en réutilisant la même session ouverte pour multiplier les réservations avant même que la majorité des visiteurs humains n’ait fini de charger la page. Ce cas ne traite pas de la revente de billets sur le marché secondaire, sujet distinct qui relève davantage du contrôle des places une fois vendues.
Lire les journaux pour comprendre le schéma
Le journal d’accès du serveur montrait une signature nette : plusieurs centaines de requêtes POST vers l’URL de finalisation de commande, provenant d’un nombre restreint d’adresses IP, espacées de quelques centaines de millisecondes seulement. Un visiteur humain met en général plusieurs secondes entre l’ajout au panier et la validation ; ce script enchaînait les deux étapes sans délai perceptible, et sans jamais charger les ressources statiques (images, polices) qu’un vrai navigateur récupère systématiquement.
Le point faible exploité

Le formulaire de réservation ne comportait aucune protection contre les soumissions automatisées : ni jeton de vérification à usage unique, ni limite de débit par adresse IP, ni contrôle de la fréquence de connexion. Le point de terminaison REST exposé par l’extension acceptait toute requête correctement formée, sans distinguer un navigateur d’un script :
add_action('rest_api_init', function () {
register_rest_route('billetterie/v1', '/commander', array(
'methods' => 'POST',
'callback' => 'billetterie_commander',
'permission_callback' => '__return_true',
));
});
Aucun mécanisme ne limitait le nombre de commandes par session ni par adresse IP dans la fenêtre de temps qui suit l’ouverture des ventes, moment le plus sensible de toute la campagne de billetterie.
Les corrections mises en place
Trois mesures complémentaires ont été déployées avant la vente suivante :
- Un défi Turnstile inséré avant la validation finale de la commande, qui bloque l’essentiel des scripts sans navigateur complet.
- Une limite de débit par adresse IP au niveau du serveur web, restreignant le nombre de requêtes vers l’URL de commande à quelques tentatives par minute.
- Un plafond de billets par session et par moyen de paiement, empêchant qu’une même identité technique valide un volume disproportionné de réservations.
Le compromis entre friction et disponibilité
Ajouter un défi anti-robot à l’ouverture d’une vente très demandée pose une question d’expérience : un visiteur humain pressé ne doit pas être pénalisé au point d’abandonner sa réservation légitime. Le choix s’est porté sur un défi invisible dans la majorité des cas, qui ne demande une interaction visible que lorsque le comportement de la requête paraît suspect, préservant ainsi la fluidité pour l’immense majorité des acheteurs réels.
Ce que la vente suivante a montré
Lors de l’ouverture suivante, le stock s’est épuisé en un peu plus de quatre minutes, un rythme cohérent avec un afflux humain massif. Les journaux ne montraient plus aucune signature de rafale automatisée, et le nombre de plaintes de spectateurs n’ayant pas pu obtenir de billet malgré une tentative rapide a nettement diminué, signe que la disponibilité perçue par le public avait été rétablie.
Notre verdict
Une billetterie très demandée doit être pensée comme une cible, pas comme un simple formulaire de vente. La combinaison d’un défi anti-robot ciblé, d’une limite de débit par adresse IP et d’un plafond de commande par session referme l’essentiel des scénarios d’achat automatisé, sans sacrifier l’expérience des spectateurs qui jouent le jeu.