· 18 min read

La majorité du trafic internet n’est pas humaine: comprendre les bots

La majorité du trafic internet n’est pas humaine: comprendre les bots
🇫🇷
Note: This blog post is written in French. I’m publishing it alongside a video I did with Micode, a French YouTuber, so it felt more natural to share this content in French as well.

Je profite de la sortie de ma vidéo avec Micode/Underscore pour écrire un article en français sur un sujet assez particulier: les bots.

C’est un sujet de niche, souvent traité dans des articles techniques et majoritairement en anglais. C’est aussi un sujet que je connais bien, donc j’ai tendance à trouver ça assez “normal”. Mais dès que j’en parle autour de moi, les gens sont souvent surpris d’apprendre que:

Dit autrement: une partie significative du trafic sur internet n’est pas humaine.

Et pourtant, en tant qu’utilisateur, tout ça reste largement invisible. On navigue, on clique, on crée des comptes, sans forcément se rendre compte de ce qui se passe en arrière-plan.

Ce décalage est important, parce qu’il explique aussi beaucoup de choses du côté des sites.

Par exemple, les protections qui peuvent sembler frustrantes au quotidien:

Ces mécanismes dégradent clairement l’expérience utilisateur, et les sites en sont parfaitement conscients.

Mais dans beaucoup de cas, ils ne sont pas là par confort. Sans ces protections, certaines plateformes ne pourraient tout simplement pas fonctionner face au volume de fraude.

L’objectif de cet article n’est pas de rentrer dans tous les détails techniques, ni de faire un guide exhaustif. Il y aurait largement de quoi écrire plusieurs articles pour ça.

L’idée est plutôt de poser les bases, de manière simple, pour:

Si à la fin de l’article les CAPTCHA, les files d’attente ou les protections anti-bot sont perçus un peu différemment, alors l’objectif est rempli.

Qu’est-ce qu’un bot?

Un bot (ou robot informatique) est simplement un programme informatique qui automatise des actions sur internet. Dit comme ça, ça peut paraître un peu abstrait, mais en pratique c’est assez simple: au lieu qu’un humain clique, tape au clavier et navigue sur un site, c’est du code qui le fait à sa place.

Et surtout, il peut le faire:

C’est cette combinaison qui change tout !

Un humain peut effectuer quelques actions par minute. Un bot peut en effectuer des milliers, voire beaucoup plus, sans pause. C’est précisément ce passage à l’échelle qui rend les bots intéressants… et problématiques.

Des bots utiles

Tous les bots ne sont pas mauvais, loin de là. Un exemple très concret: Googlebot.

C’est le bot de Google qui parcourt le web pour indexer les pages. Sans ce type de bot, les moteurs de recherche ne pourraient pas fonctionner correctement.

On retrouve aussi des bots dans des usages plus “internes”:

Dans ces cas-là, les bots permettent surtout de gagner du temps et de fiabiliser certaines opérations.

Des bots malveillants

Le problème apparaît quand cette capacité d’automatisation est utilisée pour abuser des systèmes.

Par exemple:

Ce qui rend ces attaques efficaces, ce n’est pas forcément leur complexité technique: c’est le volume.

Un humain ne peut pas tester 100 000 mots de passe. Un bot, lui, peut le faire très rapidement, et même répéter l’opération sur des dizaines de sites.

Des usages dans une zone grise

Entre les deux, il existe des usages plus ambigus.

Par exemple:

Dans ces cas-là, ce n’est pas forcément illégal dans tous les contextes, mais l’impact est bien réel.

Typiquement:

Ce qui est intéressant, c’est que techniquement, tous ces cas reposent sur la même base: automatiser des actions humaines.

C’est ensuite l’usage et l’échelle qui font toute la différence.

À quoi ressemble un bot en pratique?

Quand on parle de bots, on peut vite imaginer quelque chose de complexe ou “high-tech”, qui fonctionne à base d’intelligence artificielle.

En réalité … c’est juste du code.

Un bot, c’est simplement un programme informatique (un logiciel) qui va reproduire ce qu’un humain ferait sur un site:

Sauf qu’il le fait automatiquement.

Et surtout, il peut répéter ces actions:

Un exemple simple

Prenons un exemple concret avec https://pptr.dev/ (Puppeteer), une librairie développée par Google qui permet de contrôler Chrome avec du code.

const puppeteer = require('puppeteer');

(async () => {
    const browser = await puppeteer.launch();
    const page = await browser.newPage();
    await page.goto('https://antoinevastel.com/');

    // Get the list of article titles
    const titleArticles = await page.$$eval('article a', aElts => {
        return aElts.map(aElt => aElt.text)
    })

    console.log(titleArticles)
    // [
    //     "Analyzing Recent's Magento 1 Credit Card Skimmer",
    //     'Creating a simple ExpressJS middleware to detect bots',
    //     'Bot detection 101: How to detect web bots?',
    //     'Bot detection 101: Categories of web bots',
    //     'Benchmarking our JavaScript obfuscator',
    //     'Improving our homemade JavaScript obfuscator',
    //     'A simple homemade JavaScript obfuscator',
    //     'The Intriguing Sneaker Bot industry',
    //     'Detecting Chrome headless, the game goes on!',
    //     'Automatically beautify JavaScript files on the fly with Puppeteer and Chrome headless'
    //   ]
    await browser.close()
})()

Ce script:

  1. lance un navigateur
  2. va sur un site (mon site)
  3. récupère les titres des articles

C’est exactement ce que ferait un humain… sauf que là c’est automatisé. Et surtout, ce type de script peut être exécuté:

C’est là que l’échelle devient intéressante, et problématique quand c’est utilisé à des fins malveillantes.

Des bots sans code

Un point souvent sous-estimé: aujourd’hui, il n’est même plus nécessaire de savoir programmer pour utiliser des bots.

Il existe des outils avec interface graphique.

Exemple d’un bot de scalping avec interface graphique (Cybersole)

Par exemple, Cybersole permet d’acheter automatiquement des produits en édition limitée. L’utilisateur configure quelques paramètres (site, produit, taille, etc.), et le bot s’occupe du reste.

Des outils plus avancés

Pour des usages plus offensifs, comme le vol de comptes, on trouve des outils comme OpenBullet.

Interface graphique d’OpenBullet pour configurer des attaques

Ces outils vont plus loin:

Exemple de configuration avancée avec scripting

Ces programmes/configurations sont fréquemment partagées ou vendues sur Telegram:

Configurations Open Bullet partagées sur Telegram pour cibler des sites de VPNs.

Concrètement, quelqu’un peut:

Sans forcément comprendre en détail comment le site fonctionne.

Pourquoi c’est important

Ce point est clé pour comprendre l’écosystème:

Cela est encore plus vrai avec l’IA, qui a rendu la génération de code encore plus simple.

Résultat: des attaques qui étaient réservées à des profils techniques il y a quelques années sont aujourd’hui beaucoup plus accessibles. Et ça explique en partie pourquoi le volume de bots a fortement augmenté.

Comment les sites détectent les bots?

Maintenant qu’on a vu à quoi ressemble un bot, la question logique est la suivante: comment les détecter?

Après tout, un bot moderne peut:

Donc, vu de l’extérieur, il peut ressembler à un humain.

C’est précisément ce qui rend le problème difficile.

Il n’existe pas une technique unique qui permet de dire “c’est un bot” ou “c’est un humain”.

En pratique, les sites combinent plusieurs signaux pour essayer de faire la différence entre:

Les CAPTCHA

Le mécanisme le plus connu, c’est le CAPTCHA.

Exemple de Google reCAPTCHA

Le principe est simple: proposer un test que les humains peuvent résoudre facilement, mais qui est plus difficile pour un programme.

Par exemple:

C’est une première barrière utile, mais elle a plusieurs limites importantes:

En pratique, les CAPTCHA sont rarement utilisés seuls. Ils viennent en complément d’autres mécanismes.

Les empreintes de navigateur (fingerprinting)

Une autre approche consiste à observer l’environnement dans lequel le navigateur s’exécute. Quand une page web se charge, le navigateur expose de nombreuses informations, par exemple:

Signaux liés à la résolution écran qui peuvent être collectés dans un navigateur

On peut aller plus loin avec des techniques comme le canvas fingerprinting.

Exemple de rendu canvas utilisé pour fingerprinting

Le principe est de demander au navigateur de produire un rendu graphique. Ce rendu dépend de nombreux paramètres (carte graphique, système, pilotes…), ce qui permet d’obtenir une sorte de signature de l’appareil.

À noter que les empreintes de navigateurs utilisées en pratique sont bien plus complexes que les exemples simplifiés présentés ici.

Les systèmes anti-fraude modernes ne se basent pas sur quelques propriétés, mais sur des centaines de signaux différents, collectés et corrélés entre eux.

Pour donner un ordre de grandeur, voici un exemple d’empreinte collectée avec https://fpscanner.com/, une librairie open source de détection de bots que je développe.

L’idée n’est pas de comprendre chaque champ individuellement, mais plutôt d’illustrer:

Exemple:

{
  "signals": {
    "automation": {
      "webdriver": false,
      "webdriverWritable": false,
      "selenium": false,
      "cdp": false,
      "playwright": false,
      "navigatorPropertyDescriptors": "00000"
    },
    "device": {
      "cpuCount": 14,
      "memory": 32,
      "platform": "MacIntel",
      "screenResolution": {
        "width": 2560,
        "height": 1440,
        "pixelDepth": 24,
        "colorDepth": 24,
        "availableWidth": 2560,
        "availableHeight": 1410,
        "innerWidth": 1707,
        "innerHeight": 859,
        "hasMultipleDisplays": true
      },
      "multimediaDevices": {
        "speakers": 1,
        "microphones": 1,
        "webcams": 1
      },
      "mediaQueries": {
        "prefersColorScheme": "dark",
        "prefersReducedMotion": false,
        "prefersReducedTransparency": false,
        "colorGamut": "srgb",
        "pointer": "fine",
        "anyPointer": "fine",
        "hover": true,
        "anyHover": true,
        "colorDepth": 8
      }
    },
    "browser": {
      "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/147.0.0.0 Safari/537.36",
      "features": {
        "bitmask": "1000111100010111100111111111",
        "chrome": true,
        "brave": false,
        "applePaySupport": false,
        "opera": false,
        "serial": true,
        "attachShadow": true,
        "caches": true,
        "webAssembly": true,
        "buffer": false,
        "showModalDialog": false,
        "safari": false,
        "webkitPrefixedFunction": true,
        "mozPrefixedFunction": false,
        "usb": true,
        "browserCapture": true,
        "paymentRequestUpdateEvent": true,
        "pressureObserver": true,
        "audioSession": false,
        "selectAudioOutput": false,
        "barcodeDetector": true,
        "battery": true,
        "devicePosture": true,
        "documentPictureInPicture": true,
        "eyeDropper": true,
        "editContext": true,
        "fencedFrame": true,
        "sanitizer": true,
        "otpCredential": true
      },
      "plugins": {
        "isValidPluginArray": true,
        "pluginCount": 5,
        "pluginNamesHash": "-2cdc5c8b",
        "pluginConsistency1": true,
        "pluginOverflow": false
      },
      "extensions": {
        "bitmask": "00000000",
        "extensions": []
      },
      "highEntropyValues": {
        "architecture": "arm",
        "bitness": "64",
        "brands": [
          {
            "brand": "Google Chrome",
            "version": "147"
          },
          {
            "brand": "Not.A/Brand",
            "version": "8"
          },
          {
            "brand": "Chromium",
            "version": "147"
          }
        ],
        "mobile": false,
        "model": "",
        "platform": "macOS",
        "platformVersion": "26.4.1",
        "uaFullVersion": "147.0.7727.102"
      },
      "etsl": 33,
      "maths": "67d0b556",
      "toSourceError": {
        "toSourceError": "TypeError: Cannot read properties of null (reading 'usdfsh')",
        "hasToSource": false
      }
    },
    "graphics": {
      "webGL": {
        "vendor": "Google Inc. (Apple)",
        "renderer": "ANGLE (Apple, ANGLE Metal Renderer: Apple M4 Pro, Unspecified Version)"
      },
      "webgpu": {
        "vendor": "apple",
        "architecture": "metal-3",
        "device": "",
        "description": ""
      },
      "canvas": {
        "hasModifiedCanvas": false,
        "canvasFingerprint": "-4793ee0a"
      }
    },
    "codecs": {
      "audioCanPlayTypeHash": "688c7345",
      "videoCanPlayTypeHash": "-126cde82",
      "audioMediaSourceHash": "-3cbc04a4",
      "videoMediaSourceHash": "-48c15d34",
      "rtcAudioCapabilitiesHash": "26a15cc5",
      "rtcVideoCapabilitiesHash": "4f24a817",
      "hasMediaSource": true
    },
    "locale": {
      "internationalization": {
        "timezone": "Europe/Paris",
        "localeLanguage": "en-US"
      },
      "languages": {
        "languages": [
          "en",
          "fr-FR",
          "fr",
          "en-US"
        ],
        "language": "en"
      }
    },
    "contexts": {
      "iframe": {
        "webdriver": false,
        "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/147.0.0.0 Safari/537.36",
        "platform": "MacIntel",
        "memory": 32,
        "cpuCount": 14,
        "language": "en"
      },
      "webWorker": {
        "vendor": "Google Inc. (Apple)",
        "renderer": "ANGLE (Apple, ANGLE Metal Renderer: Apple M4 Pro, Unspecified Version)",
        "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/147.0.0.0 Safari/537.36",
        "language": "en",
        "platform": "MacIntel",
        "memory": 32,
        "cpuCount": 14
      }
    }
  }
}

L’objectif ici n’est pas d’identifier une personne de manière unique.

On cherche plutôt à:

Le comportement utilisateur

Même si un bot imite un humain, son comportement reste souvent différent. On peut analyser par exemple:

Exemple de trajectoire de souris

Un humain:

Un bot:

Pris individuellement, ces signaux ne suffisent pas. Mais combinés, ils deviennent beaucoup plus pertinents.

Une approche multi-signaux

Le point le plus important, c’est celui-ci: aucun signal ne suffit seul.

Les systèmes modernes combinent donc plusieurs dimensions:

Mais collecter des signaux ne suffit pas. Il faut ensuite les interpréter. En pratique, les systèmes de détection utilisent généralement un mélange de:

L’idée est de détecter des combinaisons de signaux qui, prises ensemble, deviennent suspectes.

Par exemple:

C’est typiquement ce que font des entreprises comme https://castle.io/ (où je travaille).

Et c’est aussi ce qui rend la détection difficile: ce n’est pas une règle simple, mais une accumulation d’indices qu’il faut analyser ensemble.

Comment les bots contournent la détection

On a vu que les sites collectent différents types de signaux:

Maintenant, il faut regarder le problème du point de vue des attaquants. Leur objectif n’est pas simplement d’automatiser une action.

L’objectif est de pouvoir exécuter cette action des milliers voire des millions de fois, sans se faire détecter.

C’est ce passage à l’échelle qui change complètement la difficulté.

Une action isolée peut passer inaperçue.

La même action répétée des milliers de fois va forcément attirer l’attention… sauf si tout est fait pour ressembler à du trafic légitime.

Et c’est là que les techniques d’évasion entrent en jeu.

De manière générale, chaque mécanisme de détection devient une contrainte à contourner.

Par exemple:

C’est pour cette raison qu’on parle souvent d’un jeu du chat et de la souris.

Modifier leur empreinte navigateur

On a vu que les sites collectent des informations sur le navigateur pour détecter des environnements suspects.

Le problème, côté attaquant, c’est que les environnements automatisés (navigateurs automatisés, ou les serveurs sur lesquels ils sont éxecutés) ont souvent des caractéristiques différentes:

Ces différences peuvent suffire à déclencher un blocage. Pour contourner ça, des outils existent pour modifier ces empreintes.

Exemple d’outil permettant de modifier une empreinte navigateur: Camoufox

Des projets comme Camoufox permettent de:

En pratique, le bot ne change pas forcément de comportement, mais il change la manière dont il est perçu.

Contourner les CAPTCHA

Les CAPTCHA sont souvent perçus comme une protection forte. Dans la pratique, ils sont régulièrement contournés.

Historiquement, cela passait par des “captcha farms”:

Aujourd’hui, avec les progrès en reconnaissance d’image (intelligence artificielle), une grande partie de ce travail peut être automatisée.

Des services comme CapSolver permettent de résoudre des CAPTCHA à grande échelle.

CapSolver: Service de résolution automatique de CAPTCHA

Ordre de grandeur: environ 0.68€ ($0.8) pour 1000 CAPTCHA.

Ce que cela implique:

Autrement dit, un CAPTCHA devient souvent un simple coût opérationnel, pas un blocage réel.

Utiliser des proxies pour masquer leur adresse IP

L’adresse IP est un signal très utilisé en cybersécurité.

Par exemple:

Sans mécanisme supplémentaire, une attaque ne passerait pas à l’échelle.

C’est là que les proxies deviennent essentiels.

Un proxy est un intermédiaire entre le bot et le site. On peut voir ça comme une sorte de VPM.

Au lieu d’envoyer directement une requête au site visé:

Le site voit donc l’adresse IP du proxy, pas celle du bot.

Et surtout, les bots utilisent un grand nombre de proxies.

Concrètement:

Du point de vue du site, cela ressemble à des utilisateurs différents.

C’est ce qui permet:

Sans proxies, une attaque serait rapidement bloquée après quelques dizaines ou centaines de requêtes.

Les différents types de proxies

Tous les proxies ne se valent pas: certains sont plus coûteux, plus lents, plus difficiles à détecter… et donc plus ou moins adaptés selon le type d’attaque.

Le choix du proxy est un compromis entre:

Type Description Avantages Inconvénients
Datacenter IP de cloud (AWS, OVH…) rapide, peu cher facilement détectable
Résidentiel IP de particuliers difficile à détecter plus cher
ISP IP “résidentielle” hébergée en datacenter compromis parfois détectable
Mobile IP 4G/5G très difficile à détecter coûteux

Dans la pratique:

Les prix varient beaucoup selon le fournisseur, le type de proxy, la qualité des proxies et le volume acheté. Pour donner un ordre de grandeur, les proxies résidentiels tournent souvent autour de 1,5$ à 5$ par Giga.

Exemple de coût pour des proxies résidentiels via le fournisseur de proxies BrightData

D’où viennent les proxies résidentiels?

C’est souvent la partie la moins connue. Les proxies résidentiels utilisent des adresses IP appartenant à des particuliers (Orange, Free, SFR, etc.).

Ces IPs sont particulièrement intéressantes pour les attaquants, car elles ressemblent à du trafic légitime.

Mais d’où viennent-elles?

Dans beaucoup de cas:

Ces logiciels vont utiliser la connexion internet de l’utilisateur comme proxy, parfois sans que celui-ci en ait réellement conscience.

Autrement dit, une partie des utilisateurs sert involontairement d’infrastructure pour ces réseaux.

C’est un sujet sur lequel je travaille aussi directement chez Castle. Par exemple, nous avons développé un product qui permet de monitorer les adresses IP utilisées par ces réseaux de proxies résidentiels:

IP Intelligence API – Castle
Identify residential proxies, VPNs, and their operators with fresh IP intelligence built for real-time decisions.

Sur une période de 30 jours, on observe environ 45 millions d’adresses IP uniques utilisées dans ces réseaux.

Pour donner un ordre de grandeur côté français (sur 60 jours), voici quelques chiffres:

Fournisseur Nombre d’IP observées
Orange 254 924
Bouygues Telecom 157 692
Free Mobile 138 328
SFR 130 556
Free 124 324

Même en se limitant à ces quelques acteurs, le volume est déjà très important.

Ce que cela implique concrètement:

Et c’est précisément ce qui rend ces proxies difficiles à distinguer du trafic normal.

Pourquoi c’est plus compliqué qu’il n’y paraît

Quand on découvre le sujet, on a souvent des solutions qui paraissent évidentes:

En pratique, aucune de ces approches ne tient à grande échelle.

Pourquoi? Parce que les bots ne sont pas statiques. Ils s’adaptent en permanence aux mécanismes de défense.

“Il suffit de bloquer par IP”

Sur le papier, l’idée est simple:

Le problème, c’est que cette logique ne fonctionne que si l’attaquant utilise peu d’IPs.

Comme on l’a vu, les bots utilisent des proxies, souvent par milliers.

Résultat:

Donc deux problèmes apparaissent:

C’est un exemple typique du compromis entre sécurité et expérience utilisateur.

“Il suffit de mettre un CAPTCHA”

Les CAPTCHA sont utiles, mais ils ont des limites structurelles.

Comme vu précédemment:

Donc pour un attaquant, un CAPTCHA devient souvent:

Et côté utilisateur, l’impact est réel:

Encore une fois, compromis.

“Il suffit de détecter une fois”

Autre idée fréquente: trouver “le bon signal”.

Par exemple:

Le problème, c’est que dès qu’un signal est utilisé:

Exemples:

Ce n’est pas un problème statique. C’est un système qui évolue en permanence des deux côtés (jeu du chat et de la souris).

Le problème de l’échelle

C’est probablement le point le plus important. Ce qui rend le problème difficile, ce n’est pas uniquement la technique: c’est l’échelle.

Un attaquant peut:

Et surtout:

Côté défense, les contraintes sont différentes:

Ce déséquilibre rend le problème particulièrement difficile.

Pourquoi il n’existe pas de solution parfaite

Il faut accepter un point important: il n’existe pas de solution parfaite.

Même les systèmes les plus avancés:

L’objectif n’est pas d’éliminer tous les bots.

L’objectif est plutôt de:

Autrement dit: rendre le passage à l’échelle beaucoup plus compliqué pour les attaquants.

Pour aller plus loin

On a vu les bases, mais en réalité, on a à peine gratté la surface.

L’écosystème des bots évolue très vite, et il y a encore beaucoup de sujets intéressants à explorer. Voici quelques exemples pour donner une idée de jusqu’où ça peut aller.

Faux comptes et emails jetables

Créer un compte, ce n’est souvent que la première étape.

Les attaquants utilisent:

L’objectif est d’avoir une identité qui a l’air crédible, pour:

Exemple intéressant:

https://blog.castle.io/detecting-gmail-based-fake-accounts-what-emailnator-teaches-us/

Fingerprinting avancé côté plateformes

Certaines plateformes vont beaucoup plus loin que les exemples simples vus plus haut.

Par exemple, LinkedIn utilise des techniques avancées pour:

Quelques exemples:

Protection du code de fingerprinting (ex: TikTok)

Les scripts de fingerprinting peuvent aussi intégrer des mécanismes pour se protéger des attaquants qui chercheraient à les analyser. Un exemple intéressant: TikTok (côté web, pas l’application mobile)

https://blog.castle.io/what-tiktoks-virtual-machine-tells-us-about-modern-bot-defenses/

Ici, l’objectif n’est pas seulement de collecter des signaux, mais de rendre clee code difficile à analyser.

En pratique:

En rendant cette analyse difficile, on ralentit fortement les attaques et leur capacité à passer à l’échelle.

Collecte d’empreintes côté attaquants

Un point assez contre-intuitif: les attaquants ne font pas que contourner les empreintes… ils en collectent aussi.

Ils peuvent:

On peut parle de “fermes d’empreintes”.

https://castle.io/research/fingerprint-harvesting-in-the-bot-ecosystem/

L’objectif est simple: utiliser des empreintes réelles pour rendre les bots beaucoup plus crédibles.

Fermes de CAPTCHA

Même logique pour les CAPTCHA.

On trouve:

https://castle.io/research/botmasterlabs-powering-an-era-of-spam/