- Un blogueur envoie une Zip Bomb basée sur gzip aux bots malveillants en réponse HTTP afin de réduire les scans de vulnérabilités, le spam et le scraping de contenu
- En exploitant le flux Accept-Encoding: gzip, deflate utilisé par les navigateurs et crawlers légitimes, le serveur renvoie
200 OK et Content-Encoding: gzip aux requêtes suspectes
- Un fichier gzip de 1 Mo grossit à environ 1 Go une fois décompressé, et un fichier de 10 Mo à environ 10 Go, ce qui épuise la mémoire de nombreux bots ou les pousse à abandonner la requête
- Un middleware côté serveur vérifie les IP en liste noire et les motifs de spam ; si une condition correspond, il envoie un fichier Zip Bomb pré-généré puis met fin au traitement de la requête
- Ce n’est pas une défense complète, car elle peut être facilement détectée ou contournée, mais c’est suffisant pour bloquer des bots simples qui perturbent le serveur par du crawling massif
Contexte : trafic de bots et usage des Zip Bomb
- La majeure partie du trafic web provient de bots ; certains ont des usages légitimes, comme les lecteurs RSS, les crawlers de moteurs de recherche ou les bots d’IA à la recherche de nouveaux contenus
- Le problème vient des bots malveillants opérés par des spammeurs, des scrapers de contenu et des hackers
- Dans un ancien emploi, des bots ont trouvé une vulnérabilité WordPress et injecté un script malveillant sur le serveur
- Ce serveur est ensuite devenu une partie d’un botnet utilisé pour des DDoS
- L’un de ses premiers sites a été totalement exclu de Google Search à cause du spam généré par des bots
- Après ces expériences, il a commencé à utiliser des Zip Bomb pour protéger ses serveurs des bots malveillants
Détourner la compression gzip comme moyen de défense
- Une Zip Bomb est un petit fichier compressé qui se déploie en un fichier énorme lors de la décompression et met la machine sous pression
- Aux débuts du web, la compression gzip a été introduite pour réduire les volumes de données transmis sur des connexions internet lentes
- Réduire un fichier HTML de 50 Ko à 10 Ko permettait d’économiser 40 Ko de transfert
- Sur une connexion téléphonique, cela pouvait faire passer le temps de téléchargement d’une page de 12 à 3 secondes
- Lors d’une requête, le navigateur indique les méthodes de compression qu’il prend en charge via un en-tête
Accept-Encoding: gzip, deflate
- Si le serveur prend aussi en charge la compression, il renvoie une version compressée des données attendues
- Les bots de crawling web prennent eux aussi en charge la compression comme gzip pour collecter de gros volumes de données, et cette propriété est exploitée ici à des fins défensives
Réponse envoyée aux requêtes malveillantes
- Le blog reçoit souvent des bots qui scannent des vulnérabilités de sécurité, et la plupart sont ignorés
- Lorsqu’une requête semble chercher à injecter une entrée malveillante ou à explorer les réponses du serveur, une réponse gzip est renvoyée avec
200 OK
Content-Encoding: gzip
- La taille du fichier envoyé varie selon la situation, entre 1 Mo et 10 Mo
- Un fichier de 1 Mo passe à environ 1 Go lors de la décompression
- Un fichier de 10 Mo passe à environ 10 Go lors de la décompression
- En voyant l’en-tête, le bot suppose qu’il s’agit d’un fichier compressé et tente de le décompresser pour en lire le contenu
- À mesure que le fichier continue à s’étendre, la mémoire peut être épuisée et le serveur ou le script peuvent planter
- Pour les scripts particulièrement tenaces auxquels un fichier de 1 Mo ne suffit pas, il envoie un fichier de 10 Mo ; dans ce cas, le script s’arrête immédiatement
Exemple de création d’une Zip Bomb et de déploiement côté serveur
- Créer une Zip Bomb implique d’assumer un risque, car cela peut faire planter ou endommager sa propre machine
- Un fichier gzip qui se décompresse en 10 Go peut être généré avec la commande suivante
dd if=/dev/zero bs=1G count=10 | gzip -c > 10GB.gz
- La commande se décompose ainsi
dd : commande de copie ou de transformation de données
if=/dev/zero : utilise comme entrée un fichier spécial produisant un flux infini d’octets nuls
bs=1G : définit la taille de bloc à 1 Go
count=10 : traite 10 blocs de 1 Go pour produire 10 Go de données nulles
gzip -c > 10GB.gz : compresse la sortie avec gzip et l’enregistre dans le fichier 10GB.gz
- Dans ce cas, la taille du fichier résultant est d’environ 10 Mo
- Côté serveur, un middleware a été ajouté pour vérifier si la requête en cours est malveillante
- Une liste noire d’IP qui scannent de façon répétée l’ensemble du site est maintenue
- Des motifs où un spam est posté puis suivi d’une nouvelle visite pour vérifier s’il a été publié servent aussi à la détection
if (ipIsBlackListed() || isMalicious()) {
header("Content-Encoding: gzip");
header("Content-Length: ". filesize(ZIP_BOMB_FILE_10G)); // 10 MB
readfile(ZIP_BOMB_FILE_10G);
exit;
}
- Le coût est que, dans certaines situations, le serveur doit transmettre un fichier de 10 Mo
- Quand un article devient viral, il abaisse à 1 Mo, et ce fichier reste selon lui efficace
Limites et périmètre d’usage
- Une Zip Bomb n’est pas une défense complète
- Elle peut être détectée facilement
- Elle peut être contournée
- Le client peut aussi ne lire qu’une partie du contenu
- Malgré cela, c’est un outil suffisant pour bloquer des bots peu sophistiqués qui crawlent le web sans discernement et perturbent le serveur
- Un exemple en fonctionnement peut être vu dans une relecture des logs serveur : this replay of my server logs
1 commentaires
Avis de Hacker News
Vers 2001, j’avais une ligne fixe à la maison et j’hébergeais diverses choses sur une machine Linux domestique.
À cause d’une mise à jour de Windows NT, beaucoup de systèmes avaient activé une fonction de chiffrement opportuniste qui se connectait d’abord à un port précis pour négocier s/wan avant d’envoyer du trafic TCP ; je voyais souvent ce trafic dans le pare-feu, donc je n’y prêtais pas attention.
Mais une machine en particulier essayait de se connecter toutes les quelques secondes, ce qui devenait vraiment pénible, et mes tentatives pour contacter l’administrateur ont échoué.
Au final, je l’ai informé en mode « j’espère que ça ne posera pas de problème si je lance un nouveau service sur ce port », et comme je n’ai pas eu de réponse, j’ai lancé sur ce port un serveur qui lisait
/dev/urandom, activaitTCP_NODELAYet autres, puis poussait des données aléatoires aussi vite que possible.La machine NT mal configurée se connectait, avalait environ 5 secondes de données aléatoires, disparaissait, puis revenait 5 minutes plus tard prendre une nouvelle dose de dépassement de tampon, et ce schéma a duré plusieurs semaines avant qu’elle disparaisse complètement d’Internet.
J’imagine parfois un administrateur se gratter la tête en se demandant pourquoi sa machine NT redémarrait sans cesse.
Chaque requête devrait avoir à la fois une limite de temps et une limite sur la quantité de données consommées.
J’ai donc créé un PDF de 100 pages où chaque page était un grand rectangle noir, puis je l’ai envoyé via une passerelle e-mail-vers-fax, nouvelle à l’époque ; moins d’une heure plus tard, j’ai reçu un appel furieux, et les fax se sont arrêtés.
Le passage « j’ai essayé de contacter l’administrateur de la machine et c’était courant » est particulièrement intéressant.
Après avoir laissé expirer le domaine, ce RPi mourait toutes les 5 minutes ; j’ai cru à un problème d’alimentation, jusqu’à ce que je me souvienne plus tard de cette tâche CRON.
Dans des milliers de cas, la raison même de faire tourner ce genre de service sur une machine NT était « pour ne pas avoir besoin d’administrateur » ; il ne faut pas sous-estimer ça.
Dans les années 90 et au début des années 2000, j’ai mis en ligne beaucoup de serveurs, et la pratique standard dans l’industrie était globalement d’utiliser NT pour se passer d’administrateur.
Quand j’étais jeune, j’ai bêtement fait une blague sur ma page perso en mettant
ln -s /dev/zero index.html.Les navigateurs de l’époque géraient très mal ça et se figeaient presque complètement ; parfois, cela plantait même le système client avec.
Plus tard, il me semble que les navigateurs ont commencé à vérifier le contenu réel et à interrompre ce genre de requêtes.
Ce n’est que plusieurs années plus tard que j’ai enfin pu l’ouvrir.
squashfs, un fichier HTML de 500 To avec les bons en-têtes, d’y mettre un contenu infini sans balise de fermeture, puis de faire en sorte que le serveur n’annonce pas la taille du fichier avant le téléchargement.Des idées ?
favicon.icoqui faisait planter les navigateurs.C’était sans doute celui-ci : https://freedomhacker.net/annoying-favicon-crash-bug-firefox...
/dev/zipbomb.Aujourd’hui, presque tous les navigateurs acceptent zstd et brotli, donc ce type de bombe pourrait être encore plus efficace maintenant.
This ancien commentaire montrait un impressionnant taux de compression de 1,2M:1, et zstd seems to be doing even better.
Cela dit, les bots ne prennent pas forcément en charge les standards de compression modernes.
À l’inverse, ça peut être une bonne méthode de blocage des bots : comme tous les navigateurs modernes prennent en charge zstd, l’imposer aux user-agents de navigateurs qui ne sont pas sur liste blanche pourrait automatiquement perturber les scrapers.
Elle repose fortement sur le streaming de la vue utilisateur complète à chaque interaction, et avec brotli par-dessus SSE, on obtient facilement des taux de compression de 200:1[2].
Le problème, c’est qu’un acteur malveillant peut demander un flux non compressé.
Comme brotli est pris en charge par 98 % des navigateurs, je n’envoie pas de données aux clients qui ne prennent pas en charge la compression brotli, et comme beaucoup de scrapers et de bots ne la prennent pas non plus en charge, cela fonctionne plutôt bien.
[1] démo checkboxes
https://checkboxes.andersmurphy.com
[2] article sur brotli SSE
https://andersmurphy.com/2025/04/15/why-you-should-use-brotl...
C’est parce que, dans la première génération gzip, le bloc de données
0compressé est lui-même à faible entropie, et du zst imbriqué réduit un fichier de 10 Go à 99 octets.Je n’ai pas envie de tester moi-même.
L’anecdote de l’ancien boulot, où un bot avait trouvé une vulnérabilité WordPress et placé un script malveillant sur le serveur, s’écarte un peu du sujet, mais elle est amusante.
Ça m’a plutôt rassuré de découvrir que je n’étais pas le seul à voir un shell PHP se déployer comme par magie sur un serveur une heure à peine après l’installation de WordPress.
Jamais moins de 3, c’est toujours garanti.
Même si ce n’est pas dans la première heure, le jour où vous oublierez un patch, ça finira par exploser.
/wp-loginarrivent.C’est aussi un bon moyen de repérer les bots : si je vois une IP demander des chemins liés à des CMS connus, je l’envoie directement dans un trou iptables.
Quand on dit « déployez votre premier serveur nginx hello world », on commence aussitôt à voir des requêtes bizarres dans les logs.
J’ai fait quelque chose de similaire avec ssh : j’avais trouvé un moyen de tuer les clients ssh qui tentaient de deviner le mot de passe root.
En contrepartie, plusieurs script kiddies ont lancé des DDoS contre mon petit serveur, et j’ai fini par passer à une approche consistant à identifier les acteurs manifestement malveillants et à bloquer leurs IP avec des règles de pare-feu.
Cela dit, avec IPv6, ça devient plus difficile.
Si vous créez vos propres pages web, vous pouvez aussi y mettre une bombe zip via un lien invisible à l’œil humain.
Par exemple une ancre en texte blanc sur fond blanc, sans mise en évidence au survol ni au clic : les bots la téléchargeront et l’inspecteront, tout comme les crawlers et les scrapers d’IA.
Le problème venait de bots très simples qui parcouraient le web et soumettaient du spam grossier à tous les formulaires qui semblaient pouvoir être publiés.
Au début, j’ai ajouté un CAPTCHA simple avec des caractères déformés, ce qui a bloqué beaucoup de bots, mais pas tous.
En regardant les logs du serveur, j’ai vu que ces bots n’envoyaient rapidement que trois requêtes : la page contenant le formulaire, l’image du CAPTCHA, puis la requête POST des données du formulaire, sans jamais charger le CSS ni le JS.
J’ai donc ajouté quelques champs supplémentaires au formulaire, masqués via CSS, puis fait échouer la requête et bloqué la session si quoi que ce soit était envoyé dans ces champs.
J’ai aussi transformé l’image du CAPTCHA en arrière-plan CSS et remplacé
srcpar une image transparente : le spam s’est complètement arrêté, et les vrais utilisateurs n’ont rien remarqué.https://github.com/skeeto/endlessh
Entre les deux, ça me paraît plutôt plus simple.
Les bombes zip sont amusantes.
J’ai déjà trouvé, dans un produit de sécurité, une vulnérabilité qui faisait qu’il n’effectuait pas correctement l’analyse antimalware sur les archives zip dépassant une certaine taille, ou sur les fichiers qui en contenaient.
En pratique, en mettant une bombe zip dans un document Office XML, le produit pouvait laisser passer le fichier OOXML même s’il contenait un malware facilement identifiable.
J’ai essayé de déployer ça à la place de mon script de honeypot habituel, mais ça ne semble pas très bien fonctionner.
Dans les logs du serveur web, je vois que les bots ne téléchargent pas tout le poison de 10 Mo : ils coupent à différentes longueurs.
Jusqu’ici, je n’en ai vu aucun récupérer plus d’environ 1,5 Mo.
Ou alors est-ce que ça fonctionne quand même ? Ils sont peut-être en train de décoder le flux à la volée et de mourir.
Par exemple, si le log indique qu’ils ont lu 1,5 Mo, ils ont peut-être planté en le décodant à la volée en 1,5 Go en mémoire.
Impossible de le vérifier.
Un contenu généré à l’infini, avec plein de références vers d’autres pages générées, par exemple.
Ça peut aider contre un simple
wgetet contre les bots, jusqu’à ce qu’ils s’adaptent.À noter que je suis plutôt du côté des bots, mais ça ne me dérange pas d’aider.
Certains bots ont probablement une limite stricte sur la taille des ressources qu’ils téléchargent.
Comme beaucoup sont des bots pénibles d’entraînement/scraping pour LLM, même une bombe zip de 800 Ko ne les tuera peut-être pas, mais elle peut quand même leur faire gaspiller des ressources de calcul.
Il vaut la peine de préciser qu’il ne s’agit pas d’un fichier zip classique, mais d’une bombe gzip.
Ce n’est pas une méthode qui fait tomber un antivirus avec des zips imbriqués : ça se comporte comme une page web compressée ordinaire.
Il y a quelque temps, une partie de l’infrastructure de contournement de la censure du Tor Project était hébergée sur le même site que l’article de blog sur les bombes zip[0].
L’un de ces fichiers zip a été crawlé par Google et s’est retrouvé dans une liste de domaines malveillants, ce qui a cassé une partie assez importante de l’outil Snowflake de Tor.
Il a fallu plusieurs semaines pour corriger le problème[1].
[0] https://www.bamsoftware.com/hacks/zipbomb/
[1] https://www.bamsoftware.com/hacks/zipbomb/#safebrowsing
Pour protéger les uploads de mon application, je créais des partitions temporaires de disque à taille fixe d’environ 10 Mo chacune, puis j’y décompressais les fichiers.
Si quelqu’un envoyait un fichier trop gros, les dégâts restaient confinés à cet endroit.
unzip -p | head -c 10MB