Ce qui se passe
Ce qu'un modèle de langage apporte à un attaquant, ce n'est pas une faille inédite : c'est la vitesse à laquelle il essaie des variantes d'une attaque connue, en lisant chaque réponse. Cloudflare a voulu mesurer ce que ça donne contre son propre WAF, sur l'environnement de préproduction d'un client, avec son accord.
Le modèle ne voyait ni le code de l'application, ni les règles du WAF, ni le score d'attaque : seulement une partie de la réponse HTTP.
La boucle
Chaque scénario fixe une famille d'attaque, un emplacement dans la requête, et une charge de départ que le WAF bloque déjà. Ensuite :
- un premier appel au modèle reçoit la requête, le contexte et l'historique récent, et propose la variante suivante ;
- le code construit la requête et l'envoie — jamais le modèle ;
- un second appel lit statut, en-têtes choisis et corps, et choisit l'étape suivante ;
- on recommence jusqu'à épuisement des idées ou 25 essais.
Avant chaque envoi, le code vérifie l'hôte contre une liste autorisée, coupe les redirections et compte les essais. Le texte des réponses est traité comme une entrée non fiable, puisqu'il revient dans les prompts suivants.
Ce qui est passé
Configuration testée : score d'attaque bloquant à 30 ou moins, règles gérées de Cloudflare au complet, jeu OWASP en niveau de paranoïa 3.
| Mesure | Valeur |
|---|---|
| Tentatives | 1 107, sur 45 scénarios |
| Bloquées | 558 |
| Cas retenus après tri humain | 49, dont 48 en injection de commande et SSRF |
XSS, injection SQL, inclusion de fichier et Log4j sont restés presque entièrement couverts. Le reste des tentatives ne comptait pas : requêtes malformées, jamais arrivées, ou devenues inoffensives à force de mutation.
Le cas le plus parlant vise l'adresse des métadonnées cloud, qui distribue des identifiants temporaires aux machines :
| Écriture de la même adresse | Résultat |
|---|---|
169.254.169.254 |
bloquée |
2852039166 (entier décimal) |
bloquée |
0251.0376.0251.0376 (octal) |
bloquée |
169.254.169.254. (point final) |
redirection, pas de blocage |
Il s'agit d'une piste, pas d'une preuve : aucune réponse de l'origine, aucune trace d'accès aux métadonnées. Elle a néanmoins donné trois changements de règles : SSRF - Obfuscated Host et SSRF - Restricted Protocol le 21 juillet, SSRF - Cloud améliorée le 4 août.
Deux constats de méthode : deux versions d'un même modèle ont produit des variantes différentes mais retrouvé les mêmes défauts, et allonger un scénario rapportait moins que multiplier les points de départ.
Ce que ça change pour votre code
Un filtre anti-SSRF qui cherche 169.254.169.254 dans une URL a le même défaut
qu'un WAF : il compare une chaîne, alors que la cible se réécrit. Il faut juger
l'adresse résolue.
function destinationPublique(string $url): ?string
{
$hote = parse_url($url, PHP_URL_HOST);
if (!is_string($hote)) {
return null;
}
// On juge l'IP obtenue, jamais la chaîne saisie : ce que le résolveur
// ne ramène pas à une adresse publique valide est refusé.
$ip = gethostbyname($hote);
$ok = filter_var($ip, FILTER_VALIDATE_IP,
FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE);
return $ok === false ? null : $ip;
}Deux compléments indispensables : connecter ensuite le client HTTP à cette IP
précise (avec cURL, CURLOPT_RESOLVE) pour qu'une seconde résolution DNS ne
change pas la cible, et refaire le contrôle à chaque redirection — ou ne pas en
suivre. gethostbyname() ne traite que l'IPv4.
Côté WAF, Cloudflare conseille de passer les règles gérées en journalisation, de vérifier le trafic légitime, puis de basculer en blocage, et de tester sur une préproduction protégée comme la production. Un prochain billet testera en boîte blanche, modèle informé des failles et des règles.
Source : We tested our own WAF with frontier AI models. Here's what we found, Cloudflare, 29 septembre 2026.