Skip to content
Artwork for PolySécure Podcast
PolySécure Podcast · September 3 · 1 hr 6 min

Teknik - CAIDO, le proxy offensif, ou la complexité de coder un proxy - Parce que... c'est l'épisode 0x33C!

Parce que… c’est l’épisode 0x33C! Shameless plug 19 septembre 2026 - Montréal Canada - Bsides Montréal 2026 22 septembre 2026 - Belgique - BE-Cyber 24 au 25 septembre 2026 - Belgique - BruCON 1er au 3 octobre 2026 - Krakow, Pologne - AligatorCon 13 et 14 novembre 2026 - Worldwide - DEATHCon 16 au 19 novembre - Rennes, France - European Cyber Week 2026 1 au 3 décembre 2026 - Ottawa, Canada - Forum inCYBER Canada 25 et 26 février 2027 - Québec, Canada - SéQCure 2027 I.A. Café - Enquête au cœur de la recherche sur l’intelligence artificielle Description Cette description a été faite à l’aide de GLM 5.3 Flash, à partir de la transcription qui a été effectuée par ElevenLabs Scribev2. Aucune vérification humaine n’a été faite. Si vous découvrez des erreurs ou des inexactitudes, vous pouvez m’en faire part afin que je procède aux modifications appropriées. Présentation de Caido Cet épisode technique de Polysécure accueille Émile Fugulin et Christopher Guay, cofondateurs de Caido, un projet développé depuis cinq ans. Tous deux proviennent de l’ingénierie, Christopher dirigeant la technique et Émile venant de la sécurité web. Leur produit se définit comme un proxy offensif, une boîte à outils pour les audits web et d’API, destiné aux chasseurs de primes, aux testeurs d’intrusion et aux équipes red team. Le fonctionnement du proxy Le proxy s’insère entre le navigateur et l’API, qui lui envoie toutes ses requêtes. La première étape consiste à faire accepter au navigateur un certificat généré par l’outil afin de terminer la connexion HTTPS localement. Le navigateur envoie ensuite une requête Connect pour établir un tunnel vers le serveur distant. Un proxy ordinaire laisse passer des octets chiffrés sans les lire, mais Caido se substitue au serveur distant et termine lui-même le tunnel pour pouvoir lire et modifier le trafic. TLS et détection de robots L’interception ne pose pas de difficulté puisque le certificat est installé sur la machine de l’utilisateur, peu importe la version de TLS. Le défi se situe du côté sortant, où la détection de robots analyse la structure du paquet TLS, des extensions comme Grease signalant un vrai navigateur, leur absence trahissant un automate. Les CDN comme Cloudflare ou Akamai croisent les empreintes TLS avec les en-têtes HTTP et bloquent facilement selon la réputation des adresses IP. Des plugins répartissent le trafic sur plusieurs IP, mais Amazon a restreint l’usage de son API Gateway après des abus, et les proxys résidentiels demeurent une zone grise sans support officiel. Une stack HTTP maison Le modèle de base demeure la paire requête-réponse, majoritairement en HTTP/1.1, avec un support récent de HTTP/2. La spécification HTTP/1, ancienne et vague, ne sépare en-têtes et corps que par des caractères de contrôle. Cette ambiguïté a donné naissance aux attaques de désynchronisation, où un proxy et un backend interprètent différemment les frontières des requêtes, notamment entre le content-length et le transfer-encoding, permettant d’injecter des requêtes dans une connexion réutilisée pour plusieurs clients. Les stacks standard, rigoureuses surtout en Rust, ne conviennent pas pour injecter des données non conformes, d’où la réécriture complète de la stack maison. Gérer les réponses non conformes exige aussi de la souplesse, un serveur pouvant annoncer dix octets et en envoyer quinze, ces derniers contenant parfois des informations précieuses. Les attaques synchronisées L’attaque last byte sync en HTTP/1 consiste à charger plusieurs requêtes dans des buffers, à ouvrir plusieurs connexions TCP, puis à envoyer le dernier octet de chacune simultanément. Si le verrou applicatif est mal implémenté, un code de rabais peut s’appliquer plusieurs fois. En HTTP/2, le single packet attack exploite le multiplexage des flux sur une même connexion TCP en regroupant les derniers octets de toutes les requêtes dans un unique paquet, ce qui demande de désactiver l’algorithme de Nagle et de composer avec des stacks TCP différentes selon macOS, Windows et Linux. Le streaming et la rupture du modèle requête-réponse HTTP/1 a d’abord introduit le transfer-encoding chunked, puis le web dynamique a amené les WebSockets, qui basculent vers un protocole distinct via un code 101, et les Server-Sent Events, popularisés par l’intelligence artificielle, qui maintiennent une connexion persistante livrant des données de façon irrégulière. Ces protocoles brisent le modèle historique des proxys de sécurité, fondé sur des tables de requêtes et de réponses. Caido gère désormais une deuxième table dédiée aux flux, qu’il espère éventuellement unifier, et le protocole gRPC, fondé sur le streaming, accentue cette rupture. Les connexions persistantes compliquent aussi l’injection, notamment l’automatisation des danses d’authentification. Modification du trafic et workflows Le système de règles match and replace permet de modifier des en-têtes, des parties du corps, ou d’appliquer une règle à chaque message d’un flux. Les usages courants incluent le passage d’un champ admin de false à true, l’activation de fonctionnalités ou l’injection d’un en-tête secret contournant un WAF lors d’un test autorisé. Modifier les réponses sert aussi à vérifier si une injection HTML produirait un XSS sans devoir d’abord contourner le WAF. Le workflow applique des transformations, notamment du JavaScript, sur une portion surlignée d’une requête, par exemple pour recalculer une signature S3, grâce à une machine virtuelle QuickJS intégrée au code Rust et à des modules du runtime LLRT d’Amazon. L’éditeur et les encodages L’outil Replay propose une vue formatée et une vue brute, dont les modifications doivent être réconciliées avec la version originale envoyée au serveur. Un arbre syntaxique abstrait, la gestion du undo-redo et le traitement des caractères échappés ajoutent à la complexité. Les en-têtes HTTP sont encodés en Latin 1 et le corps en UTF-8, alors que l’interface JavaScript fonctionne en UTF-16. La spécification WTF-8 sert à représenter sans perte des octets UTF-8 invalides, notamment dans l’éditeur hexadécimal. Un langage de filtrage nommé HTTPQL cible aussi les requêtes. Des recherches présentées au Defcon par Akamai ont montré comment des caractères Unicode ressemblants, convertis par des systèmes comme IIS, deviennent des vecteurs d’attaque, le best effort demeurant une source de contournements. URL et attaques SNI L’URL n’existe qu’au niveau du navigateur et le fragment après le dièse n’est jamais transmis au proxy. Les manipulations applicatives restent possibles dans les URL, comme l’injection pour un XSS ou du phishing, mais l’attaque protocolaire la plus intéressante concerne l’extension SNI de TLS, qui indique le nom du serveur visé dans le client hello. En envoyant un SNI différent de l’en-tête host, une requête peut être routée par un CDN vers un serveur normalement inaccessible, le contrôle fondé sur le host semblant alors satisfait. Notes Caido Contributeurs Nicolas-Loïc Fortin Emile Fugulin Christopher Guay Crédits Montage par Intrasecure inc Locaux virtuels par Riverside.fm

0:00-1:06:05

transcript

No transcript — this publisher did not publish one.

show notes

Parce que… c’est l’épisode 0x33C!

Shameless plug

Description

Cette description a été faite à l’aide de GLM 5.3 Flash, à partir de la transcription qui a été effectuée par ElevenLabs Scribev2. Aucune vérification humaine n’a été faite. Si vous découvrez des erreurs ou des inexactitudes, vous pouvez m’en faire part afin que je procède aux modifications appropriées.

Présentation de Caido

Cet épisode technique de Polysécure accueille Émile Fugulin et Christopher Guay, cofondateurs de Caido, un projet développé depuis cinq ans. Tous deux proviennent de l’ingénierie, Christopher dirigeant la technique et Émile venant de la sécurité web. Leur produit se définit comme un proxy offensif, une boîte à outils pour les audits web et d’API, destiné aux chasseurs de primes, aux testeurs d’intrusion et aux équipes red team.

Le fonctionnement du proxy

Le proxy s’insère entre le navigateur et l’API, qui lui envoie toutes ses requêtes. La première étape consiste à faire accepter au navigateur un certificat généré par l’outil afin de terminer la connexion HTTPS localement. Le navigateur envoie ensuite une requête Connect pour établir un tunnel vers le serveur distant. Un proxy ordinaire laisse passer des octets chiffrés sans les lire, mais Caido se substitue au serveur distant et termine lui-même le tunnel pour pouvoir lire et modifier le trafic.

TLS et détection de robots

L’interception ne pose pas de difficulté puisque le certificat est installé sur la machine de l’utilisateur, peu importe la version de TLS. Le défi se situe du côté sortant, où la détection de robots analyse la structure du paquet TLS, des extensions comme Grease signalant un vrai navigateur, leur absence trahissant un automate. Les CDN comme Cloudflare ou Akamai croisent les empreintes TLS avec les en-têtes HTTP et bloquent facilement selon la réputation des adresses IP. Des plugins répartissent le trafic sur plusieurs IP, mais Amazon a restreint l’usage de son API Gateway après des abus, et les proxys résidentiels demeurent une zone grise sans support officiel.

Une stack HTTP maison

Le modèle de base demeure la paire requête-réponse, majoritairement en HTTP/1.1, avec un support récent de HTTP/2. La spécification HTTP/1, ancienne et vague, ne sépare en-têtes et corps que par des caractères de contrôle. Cette ambiguïté a donné naissance aux attaques de désynchronisation, où un proxy et un backend interprètent différemment les frontières des requêtes, notamment entre le content-length et le transfer-encoding, permettant d’injecter des requêtes dans une connexion réutilisée pour plusieurs clients. Les stacks standard, rigoureuses surtout en Rust, ne conviennent pas pour injecter des données non conformes, d’où la réécriture complète de la stack maison. Gérer les réponses non conformes exige aussi de la souplesse, un serveur pouvant annoncer dix octets et en envoyer quinze, ces derniers contenant parfois des informations précieuses.

Les attaques synchronisées

L’attaque last byte sync en HTTP/1 consiste à charger plusieurs requêtes dans des buffers, à ouvrir plusieurs connexions TCP, puis à envoyer le dernier octet de chacune simultanément. Si le verrou applicatif est mal implémenté, un code de rabais peut s’appliquer plusieurs fois. En HTTP/2, le single packet attack exploite le multiplexage des flux sur une même connexion TCP en regroupant les derniers octets de toutes les requêtes dans un unique paquet, ce qui demande de désactiver l’algorithme de Nagle et de composer avec des stacks TCP différentes selon macOS, Windows et Linux.

Le streaming et la rupture du modèle requête-réponse

HTTP/1 a d’abord introduit le transfer-encoding chunked, puis le web dynamique a amené les WebSockets, qui basculent vers un protocole distinct via un code 101, et les Server-Sent Events, popularisés par l’intelligence artificielle, qui maintiennent une connexion persistante livrant des données de façon irrégulière. Ces protocoles brisent le modèle historique des proxys de sécurité, fondé sur des tables de requêtes et de réponses. Caido gère désormais une deuxième table dédiée aux flux, qu’il espère éventuellement unifier, et le protocole gRPC, fondé sur le streaming, accentue cette rupture. Les connexions persistantes compliquent aussi l’injection, notamment l’automatisation des danses d’authentification.

Modification du trafic et workflows

Le système de règles match and replace permet de modifier des en-têtes, des parties du corps, ou d’appliquer une règle à chaque message d’un flux. Les usages courants incluent le passage d’un champ admin de false à true, l’activation de fonctionnalités ou l’injection d’un en-tête secret contournant un WAF lors d’un test autorisé. Modifier les réponses sert aussi à vérifier si une injection HTML produirait un XSS sans devoir d’abord contourner le WAF. Le workflow applique des transformations, notamment du JavaScript, sur une portion surlignée d’une requête, par exemple pour recalculer une signature S3, grâce à une machine virtuelle QuickJS intégrée au code Rust et à des modules du runtime LLRT d’Amazon.

L’éditeur et les encodages

L’outil Replay propose une vue formatée et une vue brute, dont les modifications doivent être réconciliées avec la version originale envoyée au serveur. Un arbre syntaxique abstrait, la gestion du undo-redo et le traitement des caractères échappés ajoutent à la complexité. Les en-têtes HTTP sont encodés en Latin 1 et le corps en UTF-8, alors que l’interface JavaScript fonctionne en UTF-16. La spécification WTF-8 sert à représenter sans perte des octets UTF-8 invalides, notamment dans l’éditeur hexadécimal. Un langage de filtrage nommé HTTPQL cible aussi les requêtes. Des recherches présentées au Defcon par Akamai ont montré comment des caractères Unicode ressemblants, convertis par des systèmes comme IIS, deviennent des vecteurs d’attaque, le best effort demeurant une source de contournements.

URL et attaques SNI

L’URL n’existe qu’au niveau du navigateur et le fragment après le dièse n’est jamais transmis au proxy. Les manipulations applicatives restent possibles dans les URL, comme l’injection pour un XSS ou du phishing, mais l’attaque protocolaire la plus intéressante concerne l’extension SNI de TLS, qui indique le nom du serveur visé dans le client hello. En envoyant un SNI différent de l’en-tête host, une requête peut être routée par un CDN vers un serveur normalement inaccessible, le contrôle fondé sur le host semblant alors satisfait.

Notes

Contributeurs

Nicolas-Loïc Fortin Emile Fugulin Christopher Guay
Nicolas-Loïc Fortin LinkedIn Emile Fugulin LinkedIn Christopher Guay LinkedIn

Crédits

links15