
Le filtre SSRF vérifiait le texte du nom d'hôte, mais la destination réelle était décidée plus tard par le DNS. Cette lacune a permis aux URL Webhook contrôlées par l'attaquant d'atteindre des cibles en boucle locale, des métadonnées et du réseau privé.
Le filtre SSRF vérifiait le texte du nom d'hôte, mais la destination réelle était décidée plus tard par le DNS. Cette lacune permettait aux URL de Webhook contrôlées par un attaquant d'atteindre des cibles loopback, de métadonnées et de réseau privé.
J'ai découvert ce problème en examinant Typebot, un constructeur de chatbots open-source, avec une simple question de sécurité en tête :
Que se passe-t-il si la protection SSRF valide le texte du nom d'hôte, mais que la destination réelle est décidée plus tard par le DNS ?
Dans ce cas, cette question a conduit à un vrai bug.
La protection SSRF de Typebot pour les blocs Webhook / Requête HTTP ne validait que :
Elle ne résolvait pas les noms d'hôte avant d'autoriser la requête.
Cela signifiait qu'un nom d'hôte comme ssrf-repro.example pouvait sembler inoffensif lors de la validation, puis se résoudre en :
127.0.0.1169.254.169.254et être tout de même récupéré par le client HTTP backend.
Ce problème est devenu CVE-2026-34207.
Typebot : Typebot sur GitHub
CVE : CVE-2026-34207
Corrigé dans : 3.16.0
Cela affectait Typebot, une plateforme de chatbot open-source largement utilisée. Sur son site officiel, Typebot est présenté comme étant utilisé par 650+ entreprises dans le monde. Le site annonce également 2M+ de discussions mensuelles et 1.5M+ de bots publiés.
URL de Webhook contrôlée par l'attaquant -> le nom d'hôte passe la validation SSRF uniquement littérale -> aucune résolution DNS avant la décision d'autorisation -> le client HTTP backend résout le nom d'hôte vers une cible interne -> la requête côté serveur atteint loopback / métadonnées / réseau privé -> les données de réponse deviennent disponibles via les logs d'exécution
Typebot est un constructeur de chatbots.
Il permet aux utilisateurs de créer des flux capables de :
Webhook / Requête HTTPCela signifie que l'exécution de requêtes sortantes constitue une véritable frontière de sécurité.
La question importante ici n'était pas de savoir si Typebot supportait les blocs Webhook.
La véritable question était :
La protection SSRF valide-t-elle la destination réelle à laquelle le serveur va se connecter, ou seulement le texte du nom d'hôte apparaissant dans l'URL ?
Dans ce cas, elle ne validait d'abord que la forme textuelle.
C'était l'erreur.
Les défenses SSRF échouent de manière très prévisible.
La plupart du temps, les erreurs intéressantes ne sont pas :
169.254.169.254 »localhost »Les erreurs plus graves sont des erreurs de frontière :
C'était le bon endroit à vérifier ici.
Typebot avait déjà une logique de durcissement SSRF pour les adresses IP de métadonnées littérales, loopback, plages privées et astuces d'IP encodées.
Cela rendait la question suivante évidente :
Et si le nom d'hôte n'est pas littéralement dangereux, mais se résout en une destination dangereuse plus tard ?
C'est exactement ce qui s'est produit.
Le problème fondamental était une validation de la destination basée sur le texte du nom d'hôte au lieu de l'adresse IP résolue.
Dans l'implémentation vulnérable, validateHttpReqUrl() :
http: et https:metadata.google.internal, metadata.goog, metadata et localhostC'est la partie importante.
Si le nom d'hôte était une valeur normale comme :
ssrf-repro.example
alors parseIPAddress(hostname) renvoyait null, et le validateur s'arrêtait là.
Aucune résolution DNS n'avait lieu avant l'approbation.
Ainsi, la logique vulnérable se résumait effectivement à :
const ip = parseIPAddress(hostname);
if (ip) {
validateIPAddress(ip);
}
Cela signifie que :
La seconde moitié du bug se trouvait dans le chemin d'exécution.
Dans executeHttpRequest(), Typebot exécutait d'abord la validation puis effectuait la requête réelle avec ky(request.url, ...).
Donc la séquence était :
C'est l'intégralité de la vulnérabilité.
La distinction importante est où la décision de confiance a été prise.
Beaucoup de bugs semblent petits si on les décrit mal.
Si vous décrivez celui-ci comme :
« le filtre de nom d'hôte était incomplet »
cela ressemble à un problème de qualité.
Ce n'est pas le vrai problème.
Le vrai problème était :
Ce n'est pas une faiblesse cosmétique de filtrage.
C'est une défaillance de la frontière de confiance.
Et comme l'exécuteur HTTP enregistrait les données de réponse dans les logs d'exécution, le problème n'était même pas aveugle dans les cas les plus forts.
Donc ce n'était pas simplement :
C'était :
C'est une véritable vulnérabilité SSRF.
J'ai utilisé deux couches de preuve car elles démontraient deux choses différentes.
La première PoC isolait proprement la cause racine.
J'ai utilisé un petit harnais local qui :
127.0.0.1http://ssrf-repro.example:18080/...ssrf-repro.example se résolve en 127.0.0.1Cela démontrait exactement le défaut :
La sortie capturée montrait :
Cela prouvait directement la lacune de validation.
La seconde PoC montrait le bug via le chemin de fonctionnalité réel qui importe.
La reproduction la plus simple était :