Intercepter et modifier les réponses dans Chrome via le protocole DevTools

Écosystème F5 | 17 septembre 2018


Chez Shape, nous rencontrons de nombreux morceaux de JavaScript suspects. Nous trouvons des scripts injectés de manière malveillante dans des pages ; il arrive aussi qu’un client nous les envoie pour nous demander conseil, ou que nos équipes de sécurité découvrent sur le Web une ressource qui semble faire spécifiquement référence à certains aspects de notre service. Dans le cadre de notre travail quotidien, nous nous plongeons immédiatement dans ces scripts afin de comprendre ce qu’ils font et comment ils fonctionnent. Ils sont généralement minifiés, souvent obscurcis et nécessitent toujours plusieurs niveaux de modification avant d’être véritablement prêts pour une analyse approfondie.

Jusqu’à récemment, le moyen le plus simple d’effectuer cette analyse consistait soit à utiliser des configurations mises en cache localement permettant une modification manuelle, soit à recourir à des proxys pour réécrire le contenu à la volée. La solution locale est la plus pratique, mais les sites web ne s’adaptent pas toujours parfaitement à d’autres environnements, ce qui conduit souvent à s’enliser dans le dépannage avant même de pouvoir commencer à travailler efficacement. Les proxys sont extrêmement flexibles, mais généralement peu pratiques et difficilement portables : chacun dispose d’une configuration personnalisée adaptée à son environnement, et certaines personnes maîtrisent mieux un proxy qu’un autre. J’ai commencé à utiliser Chrome et son protocole DevTools afin d’intercepter les requêtes et les réponses au moment où elles sont échangées, puis de les modifier à la volée. Cette méthode fonctionne sur toutes les plateformes équipées de Chrome, permet de contourner toute une série de problèmes et s’intègre bien aux outils JavaScript courants. Dans cet article, je vais expliquer comment intercepter et modifier du JavaScript à la volée à l’aide du protocole DevTools de Chrome.

Nous utiliserons Node, mais une grande partie du contenu peut être adaptée au langage de votre choix, à condition que les interfaces de DevTools soient facilement accessibles.

Tout d’abord, si vous ne vous êtes jamais essayé à l’automatisation de Chrome à l’aide de scripts, Eric Bidelman a rédigé un excellent guide de prise en main de Chrome sans interface graphique. Les conseils qui y figurent s’appliquent aussi bien à Chrome sans interface graphique qu’à Chrome avec interface graphique (à une particularité près, que j’aborderai dans la section suivante).

Lancer Chrome

Nous utiliserons la bibliothèque chrome-launcher de npm pour nous simplifier la tâche.

Interception et modification des réponses avec Chrome via le protocole DevTools

chrome-launcher fait exactement ce à quoi vous vous attendez, et vous pouvez lui transmettre sans les modifier les mêmes options de ligne de commande que celles que vous utilisez habituellement dans le terminal (une excellente liste est tenue à jour ici). Nous utiliserons les options suivantes :

–window-size=1200,800

  • Définir automatiquement la taille de la fenêtre sur des dimensions raisonnables.

–auto-open-devtools-for-tabs

  • Ouvrir automatiquement les outils de développement, car nous les utilisons fréquemment.

–user-data-dir=/tmp/chrome-testing

  • Définissez un répertoire de données utilisateur fixe. (Dans l’idéal, cela ne devrait pas être nécessaire, mais le mode non headless sous Mac OSX ne semble pas permettre d’intercepter les requêtes sans cette option. Si vous connaissez une meilleure méthode, faites-le-moi savoir sur Twitter !)
Interception et modification des réponses de Chrome via le protocole DevTools

Essayez d’exécuter votre script pour vérifier que vous parvenez à ouvrir Chrome. Vous devriez voir quelque chose comme ceci :

Interception et modification des réponses de Chrome via le protocole DevTools

Utilisation du protocole Chrome DevTools

Il est également appelé « protocole de débogage de Chrome », les deux termes semblant être employés indifféremment dans la documentation de Google. Commencez par installer le paquet chrome-remote-interface via npm, qui fournit des méthodes pratiques pour interagir avec le protocole DevTools. Pensez à garder la documentation du protocole à portée de main si vous souhaitez approfondir le sujet.

Interception et modification des réponses avec Chrome via le protocole DevTools

Pour utiliser le CDP, vous devez vous connecter au port de débogage. Comme nous utilisons la bibliothèque chrome-launcher, celui-ci est facilement accessible via chrome.port.

Interception et modification des réponses avec Chrome via le protocole DevTools

De nombreux domaines du protocole doivent d’abord être activés, et nous allons commencer par le domaine Runtime afin de pouvoir nous connecter à l’API de la console et transmettre à la ligne de commande tous les appels à la console effectués dans le navigateur.

Intercepter et modifier les réponses avec Chrome via le protocole DevTools

Désormais, lorsque vous exécutez votre script, une fenêtre Chrome entièrement fonctionnelle s’ouvre et affiche également tous les messages de sa console dans votre terminal. C’est déjà formidable en soi, surtout pour effectuer des tests !

Interception des requêtes

Tout d’abord, nous devons indiquer ce que nous souhaitons intercepter en fournissant une liste de RequestPatterns à setRequestInterception. Vous pouvez effectuer l’interception à l’étape « Request » ou « HeadersReceived ». Pour modifier effectivement une réponse, nous devons attendre l’étape « HeadersReceived ». Le type de ressource correspond aux types que vous voyez habituellement dans l’onglet Réseau des outils de développement.

N’oubliez pas d’activer le domaine Network comme vous l’avez fait ci-dessus avec Runtime, en ajoutant Network.enable() au même tableau.

Interception et modification des réponses de Chrome via le protocole DevTools

L’enregistrement du gestionnaire d’événements est relativement simple, et chaque requête interceptée est associée à un ​interceptionId qui permet d’obtenir des informations sur la requête ou, à terme, d’en poursuivre l’exécution. Ici, nous nous contentons d’intervenir et de consigner dans le terminal chaque requête interceptée.

Interception et modification des réponses avec Chrome via le protocole DevTools

Modification des requêtes

Pour modifier les requêtes, nous devrons installer quelques bibliothèques utilitaires permettant d’encoder et de décoder les chaînes en base64. De nombreuses bibliothèques sont disponibles ; n’hésitez pas à choisir celles que vous préférez. Nous utiliserons atob et btoa.

Intercepter et modifier les réponses dans Chrome via le protocole DevTools

L’API permettant de gérer les réponses est un peu délicate à utiliser. Pour traiter les réponses, vous devez inclure toute votre logique de gestion des réponses dans l’interception de la requête (plutôt que de simplement intercepter une réponse, par exemple), puis récupérer le corps à l’aide de l’identifiant d’interception. En effet, le corps peut ne pas être disponible au moment où votre gestionnaire est appelé. Cette approche vous permet donc d’attendre explicitement l’élément précis que vous recherchez. Le corps peut également être encodé en base64 ; pensez donc à le vérifier et à le décoder avant de le transmettre tel quel.

Intercepter et modifier les réponses dans Chrome via le protocole DevTools

À ce stade, vous pouvez laisser libre cours à votre imagination avec le JavaScript. Votre code intervient au cœur d’une réponse, ce qui vous permet à la fois d’accéder à l’intégralité du JavaScript demandé et de renvoyer votre réponse modifiée. Génial ! Il nous suffit de modifier légèrement le JS en ajoutant un console.log à la fin afin que notre terminal affiche un message lorsque notre code modifié est exécuté dans le navigateur.

Interception et modification des réponses avec Chrome via le protocole DevTools

Nous ne pouvons pas simplement transmettre uniquement un corps modifié, car son contenu pourrait entrer en conflit avec les en-têtes envoyés avec la ressource d’origine. Puisque vous êtes en train d’effectuer des tests et des ajustements, mieux vaut probablement commencer par les bases avant de trop vous préoccuper des autres informations d’en-tête à transmettre. Si nécessaire, vous pouvez accéder aux en-têtes de la réponse via ​responseHeaders transmis au gestionnaire d’événements, mais pour l’instant, nous allons simplement créer notre propre ensemble minimal dans un tableau afin de pouvoir le manipuler et le modifier facilement par la suite.

Intercepter et modifier les réponses dans Chrome via le protocole DevTools

Pour envoyer la nouvelle réponse, il faut créer une réponse HTTP complète encodée en base64 (y compris la ligne d’état HTTP) et la transmettre via une propriété rawResponse de l’objet passé à continueInterceptedRequest.

Interception et modification des réponses avec Chrome via le protocole DevTools

Désormais, lorsque vous exécuterez votre script et naviguerez sur Internet, vous verrez dans votre terminal quelque chose de similaire à ce qui suit, à mesure que votre script interceptera le JavaScript et que votre code JavaScript modifié s’exécutera dans le navigateur, tandis que les appels à ​console.log() remonteront par le hook que nous avons créé au début du tutoriel.

Interception et modification des réponses avec Chrome via le protocole DevTools

Le code complet et fonctionnel de l’exemple de base est disponible ici :

Interception et modification des réponses avec Chrome via le protocole DevTools

Pour aller plus loin

Vous pouvez commencer par mettre en forme le code source de manière lisible, ce qui est toujours un bon point de départ pour procéder à la rétro-ingénierie de quelque chose. Bien sûr, vous pouvez le faire dans la plupart des navigateurs modernes, mais il est préférable de contrôler vous-même chaque étape de la modification afin de garantir un résultat cohérent entre les différents navigateurs et leurs versions, et de pouvoir faire le lien entre les éléments au fil de votre analyse du code source. Lorsque j’examine du code inconnu et obscurci, j’aime renommer les variables et les fonctions à mesure que je commence à comprendre leur rôle. Modifier du JavaScript en toute sécurité est loin d’être simple et mériterait un article de blog à part entière, mais pour l’instant, vous pouvez utiliser un outil comme ​unminify pour annuler les techniques courantes de minification et d’obscurcissement.

Vous pouvez installer unminify via npm et encapsuler le nouveau corps JavaScript dans un appel à ​unminify pour le voir en action :

Interception et modification des réponses dans Chrome via le protocole DevTools

Nous approfondirons les transformations dans le prochain article. Si vous avez des questions, des commentaires ou d’autres astuces intéressantes, n’hésitez pas à me contacter sur Twitter !


Partager

À propos de l’auteur

Articles de blog associés

F5 NGINXaaS pour Google Cloud : des applications résilientes et évolutives
Écosystème F5 | 08/09/2025

F5 NGINXaaS pour Google Cloud : des applications résilientes et évolutives

Découvrez comment NGINXaaS s’intègre à Google Cloud pour renforcer les performances et la sécurité, et préparer vos applications critiques à un avenir propulsé par l’IA.

L’intégration de F5 Web Application Firewall (WAF) à AWS est disponible dès aujourd’hui
Écosystème F5 | 24/04/2023

L’intégration de F5 Web Application Firewall (WAF) à AWS est disponible dès aujourd’hui

En faisant appel à un partenaire de déploiement AWS WAF tel que F5, vous pouvez renforcer la sécurité de vos applications web grâce à des règles personnalisées qui bloquent les schémas d’attaque courants, comme les injections SQL ou les attaques par scripts intersites (XSS).

Appliquer le principe de Peter Parker à l’inspection TLS
Écosystème F5 | 09/12/2019

Appliquer le principe de Peter Parker à l’inspection TLS

« Un grand pouvoir implique de grandes responsabilités. » Si l’on en trouve des échos chez Voltaire et Churchill, cette citation est surtout connue grâce aux bandes dessinées Spider-Man, où elle est attribuée à l’oncle Ben. Bien entendu, si cette phrase est si répandue dans la culture populaire, c’est notamment parce qu’elle peut s’appliquer à une multitude de situations et de sujets, y compris à l’inspection TLS.

Le NetOps a besoin de défenseurs, pas d’adversaires
Écosystème F5 | 13/12/2018

Le NetOps a besoin de défenseurs, pas d’adversaires

Il est important de reconnaître que les équipes NetOps ne sont pas toujours celles qui font obstacle au déploiement de la dernière nouveauté, application ou service. Les freins à la rapidité sont souvent dus au fait que les organisations n’adoptent pas tous les principes du DevOps lorsqu’elles cherchent à transformer leurs opérations informatiques.

Mise à jour des services applicatifs : sécurité, rapidité et visiteurs suspects
Écosystème F5 | 01/03/2018

Mise à jour des services applicatifs : sécurité, rapidité et visiteurs suspects

Il est de nouveau temps de nous pencher sur les services applicatifs que les entreprises utilisent réellement pour rendre leurs applications plus rapides et plus sûres. On constate notamment une hausse du recours aux services de protection contre les bots, ainsi que la progression lente mais régulière de HTTP/2. Bien qu’il ne s’agisse pas d’une application…

Les templates prennent le contrôle du cloud
Écosystème F5 | 02/02/2017

Les templates prennent le contrôle du cloud

Les modèles s’imposent dans le cloud. Lisez le blog de F5 pour découvrir comment l’infrastructure en tant que code et les API déclaratives automatisent la mise à disposition des applications.