AWS WAF Bot Control : ce que voit le client
Common et Targeted n’inspectent pas les mêmes signaux, les étiquettes enchaînent les règles et un blocage diffère d’un Challenge. Une mesure à 403 le montre.
BotBrowser Team
Vous voulez la documentation structurée pour Empreinte ?
Cet article fait partie de la bibliothèque éditoriale. Pour les étapes de configuration, la référence et les mises à jour continues, passez directement à la section docs.
Un groupe de règles géré est un moteur de décision, et la question utile n’est pas de savoir s’il s’est déclenché mais ce qu’il a reçu. BotBrowser fournit un profil déclaré qui garde cohérentes entre elles les surfaces qu’une page peut lire, et il ne change pas ce qu’un groupe de règles décide en périphérie. La structure compte plus qu’un score : deux niveaux de protection qui n’inspectent pas la même chose, un mécanisme d’étiquettes qui permet à une règle d’alimenter la suivante et un ensemble d’actions où un blocage et un Challenge produisent des réponses visiblement différentes.
Résumé
- Bot Control est un seul groupe de règles géré avec deux niveaux de protection, common et targeted, et n'activer que le niveau common laisse les contrôles comportementaux désactivés.
- Le niveau
commondétecte les robots qui s'identifient eux-mêmes par analyse statique des données de la requête ; le niveautargetedinclutcommonet ajoute la détection des robots qui ne s'identifient pas. - Une règle correspondante peut attacher une étiquette, et les règles suivantes peuvent correspondre à cette étiquette, ce qui rend le langage de règles composable plutôt qu’un score unique.
BlocketChallengesont des actions différentes : l’une termine la requête, l’autre demande au client d’exécuter un script puis de réessayer.- Une requête mesurée sans user agent a renvoyé
403avec un corps HTML de 919 octets et aucun script de Challenge, ce qui correspond à un blocage et non à un Challenge. - Le même endpoint a renvoyé
200avec un user agent de navigateur, donc la différence dans cette mesure tenait à la requête, pas au chemin. - Les étiquettes sont l’élément que la plupart des équipes manquent, car un tableau de bord affichant « bloqué » ne dit ni quel groupe de règles ni quelle étiquette a produit la décision.
- Un profil côté page peut garder ses propres surfaces cohérentes et ne peut pas faire réussir une décision de périphérie.
Sommaire
- Un groupe de règles, deux niveaux de protection
- Les étiquettes comme langage de règles
- Un blocage mesuré et les actions distinctes
- Ce que le groupe de règles ne voit pas et la conclusion pratique
Un groupe de règles, deux niveaux de protection
Le premier point à établir est que Bot Control n’est pas une seule chose. Il a deux niveaux de protection dans un seul groupe de règles géré : le niveau common s'exécute par défaut, et le niveau targeted est une option qui ajoute la détection des agents qui ne s'identifient pas. Une équipe qui active le moins cher et lit son tableau de bord a couvert une partie réelle du problème, pas sa totalité.
Le niveau common détecte des robots qui s'identifient eux-mêmes par des techniques traditionnelles comme l'analyse statique des données de la requête ; dans les termes de la documentation, il étiquette les robots auto-identifiés, vérifie les agents désirables comme les moteurs de recherche et détecte les signatures à haute confiance. Ces contrôles peuvent être calculés sans rien demander au client, ce qui explique qu’ils s’exécutent en premier et qu’ils attrapent l’automatisation la moins soignée.
Le niveau targeted inclut les protections de common et ajoute la détection des robots sophistiqués qui ne s'identifient pas, en atténuant par limitation de débit, CAPTCHA et défis de navigateur en arrière-plan, et en utilisant l'interrogation du navigateur, les empreintes et les heuristiques de comportement. Cette différence est la plus pratique pour un travail de données : un client qui satisfait Common peut encore échouer sur Targeted, et les deux échecs se ressemblent dans un code de statut.
Lire les deux ensemble change ce que signifie un nombre de « blocages ». Un blocage attribué à Common est une affirmation sur la requête. Un blocage attribué à Targeted est une affirmation sur la session, ce qui veut dire que la même requête envoyée une fois peut passer et envoyée plusieurs fois peut échouer. Sans le nom du groupe de règles, un rapport ne distingue pas ces deux situations, et la réponse à chacune est différente.
Les étiquettes comme langage de règles
C’est la différence structurelle qui sépare AWS WAF d’un produit fondé sur un score, et c’est la partie qui récompense l’étude. Quand une règle correspond, elle peut attacher une étiquette à la requête. Les règles suivantes de la même web ACL peuvent correspondre à cette étiquette comme s’il s’agissait d’une entrée.
rule A matches -> label aws:bot:category:http_library attached
(namespaced by the service, e.g. awswaf:managed:aws:bot-control:bot:category:http_library)
rule B reads -> if label present, apply its own action
rule C reads -> combine two labels into a narrower decision
Cette composition rend le langage expressif. Un score réduit toutes les observations à un nombre, et un nombre ne peut pas dire quels deux contrôles se sont accordés. Un ensemble d’étiquettes le peut, parce que chaque étiquette garde son nom et son origine, et une règle qui lit deux étiquettes énonce une conjonction plutôt qu’un seuil.
La conséquence opérationnelle est que l’étiquette est l’unité à journaliser. Un tableau de bord qui ne rapporte que l’action finale perd la raison, et une équipe qui débogue un faux positif doit alors modifier le client pour découvrir quelle règle s’est déclenchée. Enregistrer les étiquettes présentes sur une requête bloquée répond directement à cette question, pour le coût d’un champ dans le journal.
Les étiquettes expliquent aussi un comportement qui paraît incohérent de l’extérieur. Deux requêtes avec le même chemin et les mêmes en-têtes peuvent recevoir des actions différentes lorsqu’une règle antérieure a correspondu à quelque chose que la seconde requête ne portait pas, et la différence est une étiquette plutôt qu’un changement de l’endpoint.
L’ensemble d’actions est l’endroit où une lecture côté client se trompe le plus souvent, parce que les deux issues ressemblent à « cela n’a pas fonctionné » dans un journal qui ne consigne que succès ou échec.
Block -> 403 by default; the client receives an error response
Challenge -> 202; the client receives a script, runs it, retries with a token
CAPTCHA -> 405; the client receives a page a person is expected to complete
Seule l’action intermédiaire attend du client qu’il exécute du code. Un client qui traite tout ce qui n’est pas 200 comme un blocage réessaiera un Challenge indéfiniment, parce que la nouvelle tentative ne porte jamais le jeton demandé par le Challenge. Un client qui traite tout ce qui n’est pas 200 comme un Challenge exécutera un script inexistant, parce que le corps est une page d’erreur et non un Challenge.
La distinction est visible dans la réponse avant toute analyse. Un Challenge porte un script que le client est censé exécuter ; un blocage porte un document d’erreur. Chercher le script est un test moins coûteux que comparer un code de statut, parce que le code de statut d’un Challenge et celui d’un blocage peuvent être identiques.
Un blocage mesuré et les actions distinctes
L’affirmation selon laquelle ils diffèrent est facile à avancer, aussi une requête a été enregistrée. Un client HTTPS simple a demandé une page de documentation sans en-tête user agent, puis le même client a demandé la même page avec un user agent de navigateur.
no_ua: status=403 bytes=919 challenge_marker=false block_marker=true
server=CloudFront content-type=text/html
browser_ua: status=200 bytes=18804
server=Server content-type=text/html
Trois éléments de cette sortie méritent d’être nommés. Le premier est le statut, une erreur simple plutôt qu’une poignée de main de Challenge. Le second est la longueur du corps, assez courte pour être un document d’erreur et bien trop courte pour être une page avec laquelle un client doit interagir. Le troisième est l’analyse des marqueurs, qui n’a trouvé aucun script de Challenge dans la réponse.
Le quatrième élément est la comparaison. Le même client, le même chemin et la même seconde de la journée ont renvoyé une page complète dès que la requête portait un user agent de navigateur. Ce n’est pas la preuve qu’une règle s’est déclenchée, car l’endpoint pourrait faire tout autre chose ; cela montre que la différence entre les deux requêtes tenait à la requête, et qu’un client peut modifier l’une sans l’autre.
Un blocage ne dit pas non plus au client quelle règle l’a produit. C’est intentionnel : la réponse ne porte ni l’identité de la règle, ni l’ensemble d’étiquettes, ni le groupe de règles. L’information existe dans les journaux du fournisseur et dans la console, ce qui explique que le diagnostic doive s’y déplacer plutôt que rester côté client.
La frontière est celle qui s’applique à toute décision de périphérie, et il vaut la peine de l’énoncer avec les termes de ce produit. Un groupe de règles lit ce qui arrive : la ligne de requête, les en-têtes, la source, le motif des requêtes dans le temps et les paramètres de connexion que la périphérie peut observer.
Il ne lit pas le document. Une valeur qui n’existe qu’après l’exécution de JavaScript, comme un hash de canvas, une chaîne de rendu WebGL ou une mesure de mise en page calculée, n’est pas une entrée pour une règle qui s’exécute avant l’envoi de la réponse. Ce n’est pas une limitation choisie par le fournisseur ; c’est l’ordre des opérations. La périphérie décide avant que la page existe.
Cet ordre a une conséquence pratique pour un travail de données. Un client qui produit un document parfaitement cohérent doit encore satisfaire les contrôles antérieurs, et ces contrôles portent sur la requête plutôt que sur le rendu. Inversement, un client qui satisfait tous les contrôles au niveau de la requête n’a rien dit de la cohérence de son document, parce que le groupe de règles ne l’a jamais demandé.
Les deux couches ne forment donc pas un score unique avec un seuil. Ce sont deux questions posées à des moments différents, et un rapport qui les fusionne ne peut pas dire laquelle a reçu une réponse. Consigner l’action de périphérie à côté du résultat côté page les garde séparables, et c’est ce qui rend une enquête ultérieure possible.
Une troisième mesure affine la distinction entre blocage et Challenge, car le même endpoint a répondu à trois requêtes de formes différentes de trois manières différentes :
clean_get: status=200 bytes=18804 challenge_marker=false block_marker=false
no_ua: status=403 bytes=919 challenge_marker=false block_marker=true
scripted_post: status=403 bytes=1053 challenge_marker=false block_marker=true
Deux de ces réponses sont des blocages et une est un succès, et les deux blocages diffèrent de cent trente-quatre octets en longueur de corps. La différence est assez faible pour qu’un lecteur qui ne note que le code de statut voie un seul événement, tandis qu’un lecteur qui note la longueur et l’analyse des marqueurs en voie deux. Aucun blocage ne portait de script de Challenge, ce qui rend les deux définitifs : il n’y a rien à exécuter pour un client, donc répéter la même requête produit la même réponse.
L’ensemble d’en-têtes ajoute une seconde lecture. La réponse réussie indiquait server=Server, et les deux blocages indiquaient server=CloudFront. La valeur server=CloudFront n’est pas une identité de règle et ne nomme pas le groupe de règles, mais elle dit au lecteur quelle couche a répondu, et sépare un blocage généré devant l’application d’une réponse produite par l’application.
Ce qu’un lecteur ne doit pas en conclure, c’est que le user agent est l’entrée décisive. C’était la variable modifiée dans la première comparaison, et elle a suffi à faire passer un endpoint d’une erreur à une page complète. Savoir si elle suffit ailleurs est une question sur la configuration de cet endpoint, et la seule manière honnête d’y répondre est d’enregistrer les mêmes trois champs sur le site concerné plutôt que de généraliser depuis ce cas.
Les chiffres contiennent une leçon de second ordre. Une réponse de 919 octets et une réponse de 18804 octets diffèrent d’un facteur vingt, et un pipeline qui ne stocke que le statut les traite comme la même classe d’événement alors que l’une est un document d’erreur et l’autre une page. Stocker la longueur ne coûte presque rien et sépare immédiatement les deux, ce qui justifie sa place dans l’enregistrement à côté du statut plutôt que dans une séance de débogage séparée.
Le groupe de règles possède aussi une dimension temporelle qu’une seule requête ne peut pas montrer. Les contrôles comportementaux observent plusieurs requêtes, donc un client qui envoie une requête et lit la réponse a mesuré la partie la moins coûteuse du système. Un travail qui en envoie des milliers exerce la partie qui s’accumule, et un rapport construit à partir de requêtes isolées ne peut pas la décrire. Ce n’est pas une lacune de la documentation du fournisseur ; c’est une lacune de ce qu’une observation peut étayer.
Ce que le groupe de règles ne voit pas et la conclusion pratique
Lisez l’action avant de modifier le client. Un 403 au corps court est un Block et demande la console pour l’expliquer ; une réponse portant un script de Challenge est un Challenge et demande un client capable de l’exécuter. Nommez le groupe de règles dans l’enregistrement, car Common et Targeted échouent pour des raisons différentes et le même code de statut couvre les deux. Gardez les étiquettes, puisqu’elles sont le seul champ qui dit quelle règle s’est accordée avec quelle autre, et un résumé fondé sur un score les jette. Pour le fournisseur qui compose autrement, lisez Cloudflare et DataDome : ce que voit un scraper ; pour savoir quelles règles exigent une valeur qui n’atteint jamais la page, lisez les règles de périphérie qu’un script de page ne peut pas évaluer.
Un profil déclaré peut garder cohérentes entre elles les valeurs qu’une page expose, et il ne décide pas de ce que renvoie un groupe de règles géré. La décision appartient à l’endpoint, et le travail utile côté client consiste à rendre l’enregistrement assez précis pour expliquer la décision ensuite.
Le mécanisme d’étiquettes mérite un paragraphe de plus, car il change ce qu’on peut demander à un rapport de prouver. Un score unique est un résumé : il écarte les observations individuelles et conserve un nombre, et un lecteur qui conteste le nombre n’a plus rien à examiner. Un ensemble d’étiquettes conserve les observations, donc un lecteur peut demander quelles étiquettes étaient présentes, quelle règle a émis chacune et si l’action finale exigeait toutes ou une seule. C’est la différence entre un verdict et un enregistrement, et c’est pourquoi un langage de règles fondé sur des étiquettes peut être audité alors qu’un nombre unique ne le peut pas.
Cette expressivité a un coût, et il vaut la peine de le nommer pour qu’une équipe le prévoie. Une web ACL comportant de nombreuses règles qui lisent les étiquettes des autres est plus difficile à raisonner qu’un score unique, parce que l’ordre d’évaluation compte et qu’une étiquette présente sur un chemin peut manquer sur un autre. Une règle qui lit deux étiquettes se comporte différemment de deux règles qui en lisent une chacune, et la différence est invisible dans un tableau de bord qui ne rapporte que l’action finale. Conserver la liste des étiquettes dans le journal rend cette différence récupérable après coup, et c’est le même champ qui répond à une question de faux positif un mois plus tard.
Une remarque sur le périmètre, car c’est le genre de sujet où un léger dépassement rend tout l’enregistrement inutile. Rien ici n’affirme qu’un site particulier exécute Bot Control, qu’un code de statut particulier vienne d’un groupe de règles géré ou qu’une requête acceptée un jour sera acceptée le lendemain. Les mesures décrivent trois requêtes vers un endpoint de documentation et la structure documentée du produit ; elles ne décrivent aucune application protégée, et les mêmes trois champs relevés sur une cible réelle sont ce dont un lecteur aurait besoin pour en dire quoi que ce soit.
La même prudence vaut pour le vocabulaire des étiquettes. L’exemple utilise un nom en forme de catégorie pour montrer le fonctionnement de la composition, et un déploiement réel verra les noms émis par ses propres règles, y compris le préfixe d’espace de noms ajouté par le service. Copier une chaîne d’étiquette depuis un tutoriel dans une règle qui la lit est le moyen le plus rapide de construire une règle qui ne correspond jamais, et le correctif consiste à relever les étiquettes sur une requête réelle plutôt qu’à faire confiance à un exemple.
Enfin, l’ensemble d’actions présente une asymétrie à retenir au moment de rédiger un rapport. Un blocage est une décision qui peut s’expliquer ensuite depuis la console, et un Challenge est une décision qui a produit une seconde requête. Ne compter que la première requête sous-estime de moitié un chemin avec Challenge, car la nouvelle tentative avec le jeton est une entrée distincte qui peut réussir sans laisser de trace dans un décompte d’échecs. Un rapport qui veut décrire ce qui s’est passé doit décider laquelle des deux il compte avant d’imprimer un nombre.
Sources
Cet article fait partie du guide : Qu'est-ce qu'une empreinte de navigateur ?
Articles Connexes
ua-parser-js : Client Hints, bots et un plafond de 500
EmpreinteNavigateur non détecté : ce qu’un détecteur lit
EmpreintePreuves et journaux Cloudflare Bot Score
EmpreinteLire les signaux d’empreinte du navigateur
EmpreinteLes groupes de signaux de CreepJS et leur combinaison
EmpreinteFingerprinting CSS : comment les styles vous suivent
Exécutez la même vérification dans BotBrowser
Chargez un profil, gardez dans le navigateur les signaux que vous venez de lire, puis confirmez le résultat sur votre propre machine avant le déploiement.