Retour à l’étude BotGuard
Document de l’étude · Octobre 2026

Rapport d’analyse

Synthèse technique de l’étude.

Powered by RESONEO

BotGuard et SearchGuard, octobre 2026

Étude publiée en janvier 2026, mise à jour le 19 octobre 2026.

Le corpus d'exécution d'origine présenté ci-dessous date du 17 octobre. Les expériences du 18 octobre sont résumées à la fin de ce rapport et dans le document de l'étude « Expériences du 18 octobre 2026 » ; les dénominateurs ne doivent pas être regroupés.

La protection de Google côté client évolue alors que BotGuard conserve la version majeure 41. En mars, les moteurs intègrent du code pour les iframes et le chargement de scripts. En août, le programme encodé du contrôle de fond grossit d'environ 13 %. En septembre, le canal de fond est associé à Google Flights.

Évolution de la protection

Les dates renvoient aux mécanismes établis par cette étude, pas nécessairement à leur premier déploiement ni à une généralisation à tous les utilisateurs.

PériodeMécanisme
Octobre 2024BotGuard utilise déjà la version 41
Janvier 2025Le code des résultats traite sg_ss et prévoit un repli sans JavaScript
Mai 2025Page intermédiaire knitsail, cookie SG_SS et relance de la navigation
Octobre 2025/sgasync livre un script, son hash et son programme
Novembre 2025Canal QyE de contrôle de fond
Janvier 2026Contrôle ON4 déclenché par une requête, puis nouvelle tentative
Mars 2026Les moteurs intègrent du code pour les iframes et le chargement de scripts
Juillet 2026Une partie des réponses du contrôle de fond ajoute un module qui enregistre des données dans localStorage et les relit au passage suivant
Août 2026Quatre nouvelles familles de tests dans le programme de fond (réglages déclarés par le navigateur, rendu du texte, précision du pointeur, WebGPU) ; le programme encodé grossit d'environ 13 %
Septembre 2026Canal de fond associé à Google Flights
Octobre 2026Test WebGPU retiré du programme de fond le 5 octobre

Rôles à l'exécution

VMPrésence dans neuf pages de résultatsRôle observé
Résultats9/9Listeners de clic et tactiles, visibilité et mesures de temps ; aucune lecture de navigator, screen ou canvas observée
Knitsail5/9Inspection du navigateur et de l'environnement, signaux de souris, de clavier et de molette ; envois Validate
Publicité9/9Attestation publicitaire, y compris des requêtes d'images ; une destination de token distincte
YouTube2/9Attestation dans un lecteur intégré ; code et version non conservés

Les quatre VM ne sont pas présentes sur toutes les pages. Les résultats classiques et le Mode IA figurent tous deux parmi les pages avec knitsail. Aucun listener scroll n'a été observé dans les sessions tracées. Le script de la page d'accueil a été analysé statiquement ; disposer de son code ne fournit pas de trace d'exécution de ses lectures du navigateur.

La page intermédiaire initiale reçoit HTTP 200, produit SG_SS et relance la recherche. L'intervalle observé entre la première requête de recherche et la nouvelle tentative va de 63 à 262 ms. Un parcours qui échoue peut mener, par une redirection, à /sorry, à un HTTP 429 et à reCAPTCHA. Un statut HTTP seul ne permet pas de savoir si une réponse de recherche contient des résultats ou une page intermédiaire.

Enveloppe /sgasync

Le client ajoute 97 à chaque octet de la réponse, modulo 256, puis décode l'UTF-8 et analyse le résultat. Cette transformation de transport réversible est distincte du chiffrement du token.

Les réponses examinées comptent huit positions, numérotées à partir de zéro :

PositionContenu
0Marqueur bfkj
1Tableau de six éléments, avec cinq null et le JavaScript à l'indice 5
2null
3SHA-256 en Base64url du JavaScript embarqué
4Programme encodé, préfixe de la fonction d'entrée compris
5Espace de noms knitsail
6null
7Chaîne auxiliaire dont le sens n'est pas établi

Les hash des scripts embarqués examinés correspondent au champ 3. Le moteur et le programme sont des artefacts distincts. Les préfixes de fonction d'entrée correspondent aux trois premiers caractères du programme dans les 26 programmes capturés pendant les sessions d'exécution.

En-têtes et codes de branche locaux

x-sg-e annonce un mode de traitement de la requête et les capacités du client. La valeur capturée initialement est 2,isrpe=1,hcs=1 ; le pilote VPS capture aussi 1,isrpe=1,hcs=1. Le client conserve le mode 1 lorsqu'il est demandé et utilise 2 sinon. isrpe provient de isrpeEnabled ou de window.sglc.isrpe ; hcs provient de hasCaptchaSupport ou de window.sglc.hcs.

X-Sg-Cs est lu dans les réponses. Un gestionnaire distingue les préfixes s et a ; un autre teste les valeurs exactes s et a. Le préfixe sfl reçoit un traitement particulier. X-Sg-Ss transporte un token calculé lors d'une requête relancée et se distingue du cookie SG_SS. X-Sorry-Redirect, ou une URL de réponse /sorry/index, intervient dans le parcours CAPTCHA.

Dans la fonction de nouvelle tentative examinée, les codes locaux signifient :

  • 0 : calculer un token et réessayer avec X-Sg-Ss.
  • 1 : émettre sglacte.
  • 2 : émettre sglhcte et attendre sglhcte_retry avant de réessayer.
  • 3 : renvoyer la réponse sans passer par ces branches.

Ce sont des codes de branche locaux, pas des scores de confiance. Des surcouches installées tôt ou de façon différée autour des requêtes fetch/XHR de même origine communiquent par __sg_lite_queue.

Message Validate

Les neuf appels du corpus initial du 17 octobre sont des requêtes GET qui portent un tableau JSON dans le paramètre de requête reqpld. Leurs réponses valent [""] ; cela n'établit ni acceptation ni rejet.

Champ du messageContenu observé
1, indice 0 du tableauToken texte, 1 471 à 1 544 caractères
2, indice 1 du tableauContexte ; le champ imbriqué 9 contient un sous-message avec ei au champ 1
3, indice 2 du tableauNull dans les captures ; le code prévoit une alternative binaire dans le même groupe exclusif que le champ 1
4, indice 3 du tableau3 dans toutes les captures ; un autre chemin du code accepte 1 et 2

Commutateurs de configuration

Le client analysé tire sa configuration de champs de bits. Ses noms de propriétés locaux, obfusqués, ne sont pas des noms d'API stables :

  • Ob conditionne l'initialisation ; Qb choisit entre un démarrage synchrone et une attente d'une seconde suivie d'un rappel en période d'inactivité.
  • Dd peut déclencher la production du résultat lorsque la page devient masquée.
  • Bd saute la récupération du résultat de la VM dans sa branche.
  • Cd conditionne l'envoi ; vc choisit /sgvalid au lieu de Validate.
  • bd et cd permettent un envoi différé, par un rappel sur DOMContentLoaded ou par un délai supplémentaire d'une seconde.
  • Lc et zd pilotent des chemins de télémétrie distincts pour les étapes et pour les durées.

La présence du code ne prouve pas qu'un commutateur était activé dans chaque session. Le chemin de requête synchrone sélectionne ON4, l'autre branche de chargement BMW ; le trafic de fond capturé utilise QyE.

Moteur et statistiques

Les moteurs examinés déclarent la version 41 ; le nombre de tours extrait est de 14, 15 ou 16. Les constantes et les bornes de boucle peuvent être des arguments plutôt que des littéraux. L'extracteur suit les arguments littéraux des appels et gère les deux sens de comparaison ; lire seulement les nombres voisins donne des résultats erronés.

Copie localeToursConstante
Résultats, 17 octobre152905
Publicité, 17 octobre152905
Knitsail, 17 octobre161088
Page d'accueil, 18 octobre151795

Le chiffrement combine addition, rotation et XOR. Sa structure seule ne permet pas de l'identifier à un chiffrement répertorié. La rotation des hash de scripts et des constantes ne révèle pas la fenêtre pendant laquelle le serveur accepte des tokens plus anciens.

La routine statistique calcule l'écart-type de population, sqrt(M2/n), par mises à jour incrémentales. Un réservoir borné existe aussi. Ces routines n'établissent pas de seuils de détection côté serveur. Des indices de registre allant jusqu'à 511 sont compatibles avec un espace de 512 emplacements ; on ne peut pas supposer que le rôle de chaque registre reste stable d'une variante de script à l'autre.

Limites

L'étude distingue les capacités du code en analyse statique, l'exécution observée et les décisions du serveur. Knitsail et YouTube inspectent l'intégrité des accesseurs et peuvent détecter une instrumentation. Aucune vérification d'accesseur n'a été observée pour les VM des résultats et de la publicité, mais cela ne garantit pas que l'instrumentation soit restée sans effet. Les règles de décision du serveur, les scores de risque, les fenêtres d'acceptation et l'efficacité de la détection ne sont pas révélés par cette analyse.

La page publiée contient les tableaux d'observation détaillés et la chronologie.


BotGuard / SearchGuard : expériences du 18 octobre 2026

Corpus distincts

  • 17 octobre : quatre sessions, trois profils, neuf SERP, 43 documents Google. Les observations détaillées des lectures des VM appartiennent à ce corpus.
  • Pilote VPS : 37 essais enregistrés, plus une navigation supplémentaire dans une session ouverte. Trois enregistrements se sont arrêtés au contrôle d'IP, avant Google. Comparaison avec Chromium invalidée par des problèmes de version et de contrôles.
  • Série contrôlée sur VPS : 21 navigations, trois profils sources neufs et neuf paires NID conservé/supprimé, une sortie VPN américaine fixe.
  • Travail hors ligne : 96 replays de VM sur quatre échantillons (64 de la matrice initiale + 16 contrôles du tirage aléatoire + 16 contrôles conservant l'enveloppe), plus 48 cas synthétiques du contrôleur.

Accès et session

Sur le VPN suisse initial, Camoufox avec profil neuf a obtenu trois SERP après challenge ; Chrome avec interface et Chrome headless ont chacun enregistré trois refus. Le client HTTP sans JavaScript est resté sur un challenge dans trois essais. Sur la sortie native du VPS, Camoufox avec profil neuf a obtenu trois SERP après challenge, Chrome avec interface trois refus. Ce sont des observations par configuration, pas des taux de réussite généraux.

Série contrôlée : les trois sources neuves ont obtenu des SERP après challenge ; les neuf copies avec NID conservé ont obtenu des SERP directes ; les neuf copies avec NID supprimé ont obtenu des SERP après challenge. L'IP était stable avant et après chaque navigation ; l'identité du navigateur observée à l'exécution était identique. Huit paires sur neuf ne différaient que par NID parmi les cookies réellement transmis ; une différait aussi par __Secure-STRP. Les attentes de 5/35/120 secondes partent de l'ouverture du contexte, pas de l'émission de SG_SS, et n'établissent pas la validité du cookie à 30 secondes.

Binaire Camoufox Firefox 135.0.1-beta.24 ; paquet Python 0.4.11 ; Playwright 1.51.0. Chrome 153.0.8010.52. Le Chromium 141 en cache (révision 1194) ne correspondait pas à la révision 1161 attendue, absente. Requête : musée du Louvre site officiel, fr-FR, hl=fr, gl=fr. La série contrôlée a utilisé une sortie américaine fixe alors que la France était demandée ; toutes les branches partagent cette condition.

La qualité n'est pas certifiée

Les 21 SERP contrôlées contiennent toutes un domaine louvre.fr identifié. Aucune vidéo n'a été détectée par les résultats H3, les liens ou cartes de sources vidéo identifiables ou les titres de modules ; cette heuristique peut manquer des cartes sans libellé. Trois paires sur neuf ont des ensembles de titres extraits disjoints. Le titre candidat de la page d'accueil apparaît au rang 1 sur trois pages, au rang 7 sur dix-sept, et n'est pas identifié sur une. La présentation des sitelinks influe aussi sur l'extraction.

Les six pages avec NID conservé où le candidat de l'accueil est au rang 7 enregistrent Validate, contrairement aux trois pages avec NID conservé où il est au rang 1, dans la fenêtre d'observation. C'est exploratoire : les pages passées par un challenge ont elles aussi l'accueil à un rang bas, sans Validate. Ce n'est pas un classifieur global de qualité.

Les dix-neuf SERP capturées du pilote montrent aussi des variations de classement sur VPN et sur IP native, sans vidéo détectée. Il n'existe aucune référence humaine indépendante contemporaine ; les liens /goto opaques n'ont pas été suivis. Ni un empoisonnement des résultats ni son absence ne sont établis. L'abondance de vidéos reste un signal candidat, pas une signature prouvée de détection. Les observations de la VM YouTube du 17 octobre appartiennent à un autre corpus.

Contrôles hors ligne des VM

Les sorties A/B d'origine sont stables sur les quatre échantillons. L'extraction brute modifie les quatre sorties. Rétablir un tirage Math.random manquant ne rétablit que la VM IoM extraite. Conserver l'enveloppe d'origine et le code interne extrait rétablit les quatre sorties ; reformater ce code interne modifie de nouveau les quatre, deux fois par condition. Cela va dans le sens d'une sensibilité au texte source, sans localiser un mécanisme d'intégrité précis. Des interceptions d'accesseurs supplémentaires laissent les sorties d'origine inchangées dans ce banc d'essai hors ligne ; cela ne prouve pas que l'instrumentation passe inaperçue en ligne. La couverture des cadres enfants about:blank immédiats reste incertaine. Aucun token généré n'a été envoyé à Google.

Les 48 cas synthétiques du contrôleur concordent avec les assertions et la reconstruction : totaux 4 092/4 093/4 094, ancien cookie présent/absent, écriture acceptée/refusée, ss_cgi true/false, ce=30/0. La condition de transport stricte < 4 093 et la vérification de présence d'un SG_SS périmé sont reproduites. Le repli à deux secondes est un chemin d'aide, pas nécessairement une annulation de la VM. L'acceptation par le serveur est inconnue.

Protocole capturé

Le pilote enregistre X-Sg-Cs:s puis, 678 ms plus tard, une nouvelle tentative sur /async/callback:6761 avec sei et X-Sg-Ss (1 072 caractères) en plus, suivie de X-Sg-Cs:a. La méthode, le corps et les autres paramètres comparés restent identiques ; la réponse passe de 59 à 260 350 octets. Mode de requête : 1,isrpe=1,hcs=1. Le HAR n'identifie pas la pile JavaScript à l'origine de la requête.

La série contrôlée enregistre douze documents intermédiaires avec ce=30, ss_cgi=false, challenge_version=0, r=1. Les longueurs de ses six tokens Validate sont 1 403, 1 404, 1 400, 1 424, 1 448 et 1 435 ; le pilote avait 1 441 et 1 417, contre 1 471 à 1 544 dans neuf appels du corpus initial. Aucun X-Sg-Cs n'apparaît dans la série contrôlée. Un HTTP 200, des réponses vides et des longueurs de token proches n'établissent pas l'acceptation.

Limites et éléments conservés

Le test de visibilité n'a pas été concluant : les onglets, la fenêtre pop-up et le retrait effectif de la fenêtre X11 de l'affichage n'ont jamais produit document.hidden=true. Aucune comparaison valide de Google entre page visible et page masquée n'est revendiquée. Les comparaisons d'instrumentation et de session du pilote comptaient une répétition par branche, avec des empreintes de navigateur non figées. Les services déjà présents sur le VPS sont restés actifs. Aucun compte Google personnel ; essais séquentiels, ordre alterné, pauses de 20 secondes ; un refus explicite met fin à l'essai, sans changer d'IP pour chercher un succès. L'accès natif du VPS a été testé avec parcimonie dans le pilote et n'a pas été repris en phase deux.

Les classes de parcours distinguent SERP directe, SERP après challenge, challenge non terminé, refus et autre. Les documents réseau et les navigations JavaScript complètent les vérifications de structure, de titres et de liens. Le hash des 201 fichiers de capture privés définitifs a été calculé et vérifié. La rotation du VPN a été rétablie et les minuteurs de reprise supprimés.

Retour à l’étude BotGuard