Table des matières de l'article :
En matière de sécurité web, une erreur fréquente consiste à concevoir des défenses en se basant uniquement sur le point de vue du développeur. On vérifie le code, on installe un pare-feu, on ajoute un CAPTCHA, et on suppose que le problème est résolu.
En réalité, les concepteurs de bots n'analysent pas l'application comme le feraient un développeur, un administrateur système ou un utilisateur final. L'apparence graphique de la page, la disposition des boutons ou la qualité de l'expérience de navigation ne les intéressent pas. Ils se concentrent plutôt sur les requêtes HTTP, les points de terminaison, les paramètres, les cookies, les jetons, les en-têtes et les réponses renvoyées par le serveur.
C’est précisément de cette différence de perspective que découle l’une des leçons les plus importantes que nous avons apprises en travaillant quotidiennement avec des infrastructures Linux, des applications web, des services gérés et des systèmes exposés publiquement : pour défendre une application contre les bots, il faut d’abord comprendre comment un bot est construit.
Cela ne signifie pas développer des outils destinés à pirater les systèmes d'autrui. Il s'agit d'étudier, dans des environnements autorisés et contrôlés, comment un logiciel automatisé interagit avec un site, maintient une session, reproduit une requête et tente de contourner les protections.
Une application publique n'est jamais complètement fermée.
Toute application accessible via Internet doit communiquer avec l'appareil de l'utilisateur. Le navigateur envoie des requêtes au serveur, reçoit des réponses, télécharge des ressources, transmet des données et appelle des API. Le client peut observer tout ce qui doit parvenir au client.
Nous pouvons minimiser les informations divulguées, appliquer des contrôles rigoureux et rendre le processus extrêmement complexe, mais nous ne pouvons pas transformer la communication publique en quelque chose de totalement invisible.
Un utilisateur suffisamment motivé peut analyser le trafic généré par le navigateur et identifier :
- les adresses des points de terminaison utilisés par l'application ;
- les paramètres envoyés dans les requêtes ;
- les en-têtes HTTP requis par le serveur dorsal ;
- cookies nécessaires au maintien de la session ;
- la structure des réponses JSON ;
- l'ordre dans lequel les opérations sont effectuées ;
- tous les jetons utilisés par l'interface utilisateur.
Une fois ces informations assimilées, l'interface graphique devient presque superflue. Le bot n'a plus besoin d'ouvrir la page comme le ferait un humain : il peut tenter de communiquer directement avec le serveur.
Il est impossible d'empêcher totalement la surveillance d'un système public. Cependant, nous pouvons rendre son automatisation plus difficile, plus instable et plus coûteuse.
Le problème ne se limite pas au web scraping.
Quand on parle de « scraping », beaucoup pensent à un programme qui télécharge le contenu HTML de certaines pages pour en extraire les titres, les prix ou les descriptions. Ce n'est pourtant qu'une forme d'automatisation parmi d'autres.
Un bot peut être conçu pour créer des comptes, tester des identifiants, remplir des formulaires, interroger des API, réserver des ressources, vérifier la disponibilité, envoyer des spams, télécharger des fichiers ou reproduire certaines des fonctionnalités offertes par une application.
Du point de vue de l'infrastructure, certaines automatisations génèrent des charges très importantes. Elles produisent des milliers de requêtes à proximité les unes des autres, proviennent de la même adresse IP et suivent des schémas facilement identifiables.
Les automatisations plus avancées fonctionnent différemment. Elles répartissent les requêtes sur plusieurs adresses, respectent les pauses variables, stockent des cookies, exécutent du JavaScript et utilisent des navigateurs avec ou sans interface graphique. Elles peuvent même reproduire des séquences de navigation d'un réalisme saisissant.
C’est pourquoi le simple comptage des requêtes provenant d’une adresse IP ne suffit pas . L’adresse IP est un indicateur utile, mais elle ne représente pas nécessairement l’identité d’un visiteur. Plusieurs utilisateurs légitimes peuvent partager la même adresse, tandis qu’un seul opérateur automatisé peut en utiliser des centaines.
Le CAPTCHA est utile, mais ce n'est pas une solution complète.
Lorsqu'un formulaire est utilisé à mauvais escient, le premier réflexe est souvent d'insérer un CAPTCHA. Cela se comprend : l'ajout d'une vérification supplémentaire permet de bloquer de nombreux scripts basiques et de réduire rapidement le spam et les requêtes automatisées.
Le problème survient lorsque le CAPTCHA est considéré comme une garantie absolue.
Ce type de vérification ne représente qu'une étape du processus. Si l'application effectue un contrôle insuffisant du résultat côté serveur, accepte des jetons réutilisables ou sécurise le formulaire mais pas le point de terminaison recevant les données, le bot peut tenter de contourner l'interface et de communiquer directement avec le serveur.
De plus, un système automatisé peut utiliser un navigateur complet, attendre la validation, puis traiter les requêtes. Dans certains cas, une intervention humaine peut même effectuer la vérification, le reste des opérations étant réalisé automatiquement.
Cela ne rend pas le CAPTCHA inutile. Cela signifie simplement qu'il doit s'inscrire dans une stratégie plus globale, où le système vérifie le jeton, sa date d'expiration, l'action pour laquelle il a été émis et sa cohérence avec la session en cours.
Une protection côté client qui n'est pas correctement validée côté serveur ne constitue, au mieux, qu'un obstacle temporaire.
La première ligne de défense doit être construite sur le périmètre.
Dans les infrastructures que nous gérons, une partie de la protection est appliquée avant même que la requête n'atteigne l'application. Des services tels que les pare-feu d'applications web, les systèmes de limitation de débit, l'analyse de la réputation et les outils de gestion des bots contribuent à réduire le trafic indésirable en périphérie du réseau.
Par exemple, nous pouvons appliquer différentes limites aux points de terminaison de connexion, d'inscription, de recherche ou de récupération de mot de passe. Nous pouvons également mettre en place des contrôles supplémentaires lorsqu'une source dépasse une certaine fréquence, présente des caractéristiques anormales ou tente de manière répétée la même opération.
Il est important d'éviter les configurations trop génériques. Un seuil valide pour une page de connexion peut être totalement inadapté à une API utilisée par une application mobile ou à une page chargeant de nombreuses ressources en parallèle.
La protection doit donc être contextuelle . Ce n'est pas seulement le nombre de requêtes envoyées qui importe, mais aussi la ressource demandée, leur ordre d'utilisation, les informations d'identification utilisées et le résultat obtenu.
Le périmètre de sécurité peut considérablement ralentir un bot, mais il ne doit pas constituer l'unique couche de protection. Si l'application accepte toute requête formellement valide, un système d'automatisation suffisamment sophistiqué pourrait continuer à fonctionner à une vitesse réduite.
La protection doit se poursuivre au sein de l'application
Une défense plus robuste exige que le système dorsal vérifie non seulement la présence des paramètres attendus, mais aussi le contexte dans lequel ces paramètres ont été générés.
Dans un flux sensible, nous pouvons utiliser des jetons signés, des valeurs aléatoires imprévisibles et des identifiants à durée de validité limitée. Ces éléments peuvent être associés à la session, à l'utilisateur, à l'action demandée ou à une étape spécifique du processus.
Lorsque le serveur reçoit la requête, il doit au moins vérifier que :
- Le jeton a en fait été généré par le serveur dorsal ;
- n'a pas expiré ;
- n'a pas déjà été utilisé ;
- est connecté à la session appropriée ;
- est valable pour l'opération demandée ;
- La séquence des opérations est cohérente.
Ainsi, il ne suffit pas de copier une simple requête observée dans le navigateur. Le bot doit reconstituer l'intégralité du processus, maintenir un état correct et obtenir de nouvelles valeurs à chaque tentative.
Vous pouvez rendre certains éléments de formulaire dynamiques, insérer certains champs uniquement après une vérification JavaScript, ou modifier périodiquement la structure de la requête. Ces techniques peuvent augmenter le coût de l'automatisation, mais elles ne doivent pas remplacer la validation côté serveur.
L'obfuscation JavaScript à elle seule ne constitue pas une mesure de sécurité infaillible. Le code accessible par le navigateur doit toujours être téléchargé et exécuté. On peut certes le rendre plus difficile à analyser, mais il ne peut être considéré comme secret.
La décision finale doit toujours revenir au serveur.
La création d'un robot de test modifie votre façon de concevoir votre défense.
Lors de l'analyse de la sécurité d'un flux applicatif, nous privilégions également une approche d'automatisation. Au sein des systèmes dont nous sommes propriétaires ou pour lesquels nous avons reçu une autorisation explicite, nous pouvons développer des clients de test simulant différents niveaux de complexité.
La première couche peut être un simple client HTTP qui envoie des requêtes sans exécuter JavaScript. La deuxième couche peut gérer les cookies, les redirections, les jetons et les sessions. Une couche ultérieure peut utiliser un navigateur automatisé et reproduire une expérience de navigation plus réaliste.
Cette approche nous permet de répondre à des questions très concrètes :
- Est-il possible d'appeler ce point de terminaison sans visiter la page ?
- Un jeton peut-il être réutilisé plusieurs fois ?
- La vérification est-elle effectivement associée à la session ?
- La séquence des opérations est-elle vérifiée ?
- Le système est-il capable de distinguer une erreur isolée parmi des centaines de tentatives ?
- Est-il possible de contourner une limitation en changeant simplement l'adresse IP ?
Sans ce type de test, vous risquez de mettre en place des protections théoriquement correctes mais inefficaces en pratique. Observer votre système fonctionner avec un client non officiel permet de mettre immédiatement en évidence les informations réellement nécessaires et les contrôles qui peuvent être contournés.
Il n'existe aucun signal unique capable d'identifier tous les bots.
Un agent utilisateur inhabituel peut être suspect, mais il est possible de le modifier. Une adresse IP invalide est un indice important, mais elle peut être remplacée. L'absence de JavaScript peut révéler un script rudimentaire, mais les navigateurs automatisés peuvent l'exécuter.
Même un comportement en apparence humain n'est pas une garantie. Des pauses aléatoires, des mouvements de souris et des séquences de clics peuvent être simulés.
Une stratégie efficace combine donc plusieurs éléments d'information : taux de requêtes, continuité de session, cohérence des en-têtes, réputation de la source, résultats des vérifications JavaScript, erreurs générées, chemins de navigation et comportement historique.
Un seul signal peut générer des faux positifs. La combinaison de plusieurs signaux permet d'attribuer un niveau de risque et de choisir une réponse proportionnée.
Une requête modérément suspecte peut faire l'objet d'un examen plus approfondi. Une requête fortement anormale peut être ralentie ou bloquée. Un robot d'exploration reconnu et utile, tel qu'un moteur de recherche, peut être autorisé.
L’objectif n’est pas de bloquer toute automatisation, mais de distinguer ce qui est utile de ce qui est nuisible.
Bloquer trop peut être aussi néfaste que de ne pas bloquer suffisamment.
Une configuration anti-bot trop agressive peut empêcher les utilisateurs légitimes d'accéder à votre site, perturber les intégrations légitimes, bloquer les systèmes de suivi ou compromettre l'indexation de votre site.
C’est pourquoi chaque règle doit être respectée après son activation. Il est important de surveiller les événements générés, les requêtes bloquées, les vérifications effectuées et tout problème signalé par les utilisateurs.
Les seuils doivent être adaptés au trafic réel. Un site e-commerce, un portail de publication, un système de gestion et une API publique ont des comportements totalement différents. Copier la même configuration d'un projet à l'autre peut entraîner des résultats imprévisibles.
La sécurité anti-bots n'est pas une action ponctuelle. C'est un processus d'observation et de correction continues.
L'objectif réaliste est d'augmenter le coût de l'attaque.
Aucune protection ne peut garantir qu'une application publique ne sera jamais automatisée. Une partie disposant de suffisamment de temps, d'expertise et de ressources peut continuer à étudier le système et à adapter ses outils.
Cela ne signifie pas que les défenses sont inutiles. Au contraire, leur intérêt réside dans leur capacité à modifier l'équilibre économique de l'opération.
Un bot simple à développer, rapide et stable peut s'avérer économique. En revanche, s'il nécessite des navigateurs complets, des proxys, des mises à jour fréquentes, une gestion complexe des sessions et une intervention manuelle constante, son coût augmentera rapidement.
Chaque couche supplémentaire peut ralentir l'automatisation, accroître les erreurs et nécessiter une maintenance constante. Dans bien des cas, cela suffit à rendre le coût d'une utilisation abusive supérieur aux avantages.
Une bonne stratégie anti-bot ne promet pas l'impossible : elle transforme une opération simple et pratique en une opération lente, fragile et coûteuse.
Notre approche en tant que serveur géré
Chez Managed Server Srl, nous abordons ces problématiques en commençant par l'infrastructure, mais pas seulement. Les serveurs Linux, les proxys inverses, les CDN, les pare-feu et les systèmes de protection périmétrique sont essentiels, mais ils doivent communiquer avec la logique applicative.
Une règle de limitation de débit ne suffit pas à elle seule pour déterminer la valeur commerciale d'une transaction. Une application, en revanche, peut faire la distinction entre une recherche et un achat, entre une tentative de connexion infructueuse et une connexion réussie, ou encore entre un compte nouvellement créé et celui d'un client existant.
Pour ce faire, nous travaillons à plusieurs niveaux : analyse des journaux, configuration des serveurs web, protection des terminaux, gestion des sessions, observation des anomalies et coordination avec les développeurs, ainsi que mise en œuvre de WAF propriétaires et analyse comportementale.
Le point de départ reste le même : comprendre comment automatiser le système . Ce n’est qu’alors que nous pourrons décider quelles étapes protéger, quels signaux collecter et où introduire des frictions sans pénaliser les utilisateurs légitimes.
Se défendre implique de changer de perspective
Les concepteurs d'applications ont naturellement tendance à suivre le chemin prévu. En revanche, les créateurs de bots recherchent le chemin le plus court, le plus reproductible et le moins coûteux.
Apprendre à penser de cette manière vous permet d'identifier les points de terminaison trop permissifs, les jetons réutilisables, les contrôles présents uniquement dans l'interface utilisateur et les flux que le serveur ne vérifie pas correctement.
La connaissance offensive, exercée de manière éthique et appropriée, améliore les capacités de défense. Non pas parce qu'elle permet la création d'une barrière inviolable, mais parce qu'elle contribue à éviter des protections purement décoratives.
Sur le web, tout ce qui est transmis peut être observé et, moyennant un effort suffisant, imité. Notre tâche n'est pas de dissimuler comme par magie ce qui doit être communiqué, mais de construire des systèmes où chaque requête est évaluée, contextualisée et vérifiée.
Voilà la différence entre ajouter un CAPTCHA et concevoir une véritable stratégie anti-bot. C'est aussi pourquoi, avant de tenter de bloquer une automatisation, il est essentiel de comprendre son fonctionnement.
