- Un operador de blog personal envía una Zip Bomb basada en gzip como respuesta HTTP a bots maliciosos para reducir el escaneo de vulnerabilidades, el spam y el scraping de contenido
- Aprovecha el flujo de Accept-Encoding: gzip, deflate que usan los navegadores y crawlers legítimos, y devuelve
200 OK junto con Content-Encoding: gzip a las solicitudes sospechosas
- Un archivo gzip de 1 MB se expande a unos 1 GB al descomprimirse, y uno de 10 MB a unos 10 GB, por lo que muchos bots agotan la memoria o abandonan la solicitud
- El middleware del servidor revisa IPs en lista negra y patrones de spam, y si se cumple la condición envía un archivo Zip Bomb pregenerado y termina de procesar la solicitud
- No es una defensa completa porque puede detectarse y evitarse con facilidad, pero es suficiente para frenar bots simples que entorpecen el servidor con crawling indiscriminado
Tráfico de bots y contexto del uso de Zip Bombs
- La mayor parte del tráfico web proviene de bots, y algunos tienen usos legítimos como los lectores RSS, los crawlers de motores de búsqueda y los bots de IA que buscan contenido nuevo
- El problema son los bots maliciosos operados por spammers, scrapers de contenido y hackers
- En un trabajo anterior, bots encontraron vulnerabilidades de WordPress e insertaron scripts maliciosos en el servidor
- Ese servidor terminó siendo parte de una botnet usada para DDoS
- Uno de sus primeros sitios web fue completamente excluido de las búsquedas de Google por el spam generado por bots
- Después de esas experiencias, empezó a usar Zip Bombs para proteger el servidor de bots maliciosos
Cómo convertir la compresión gzip en un mecanismo de defensa
- Una Zip Bomb es un archivo comprimido pequeño que durante la descompresión se expande hasta convertirse en un archivo muy grande y carga la máquina
- En los inicios de la web, la compresión gzip se introdujo para reducir la cantidad de datos transferidos en conexiones lentas
- Si un archivo HTML de 50 KB se reducía a 10 KB, se ahorraban 40 KB de transferencia
- En internet por marcación telefónica, eso podía bajar el tiempo de descarga de una página de 12 a 3 segundos
- Al hacer una solicitud, el navegador informa mediante headers qué métodos de compresión soporta
Accept-Encoding: gzip, deflate
- Si el servidor también soporta compresión, devuelve una versión comprimida de los datos esperados
- Los bots de web crawling también soportan compresión como gzip para recopilar grandes volúmenes de datos, y esa característica se aprovecha como defensa
Respuesta enviada a solicitudes maliciosas
- En el blog aparecen con frecuencia bots que escanean vulnerabilidades de seguridad, y la mayoría se ignoran
- Pero si una solicitud parece intentar inyectar entradas maliciosas o explorar respuestas, se devuelve una respuesta gzip junto con
200 OK
Content-Encoding: gzip
- El tamaño del archivo enviado varía entre 1 MB y 10 MB según la situación
- Un archivo de 1 MB se expande a unos 1 GB al descomprimirse
- Un archivo de 10 MB se expande a unos 10 GB al descomprimirse
- El bot ve el header, determina que es un archivo comprimido e intenta descomprimirlo para buscar el contenido
- A medida que el archivo sigue expandiéndose, agota la memoria y el servidor o script puede colapsar
- Para scripts persistentes a los que no les basta un archivo de 1 MB, se envía uno de 10 MB, y se afirma que en ese caso el script termina de inmediato
Ejemplo de creación de una Zip Bomb y aplicación en el servidor
- Al crear una Zip Bomb hay que asumir el riesgo, porque puede colapsar o dañar tu propio dispositivo
- Un archivo gzip que se descomprime hasta 10 GB se genera con el siguiente comando
dd if=/dev/zero bs=1G count=10 | gzip -c > 10GB.gz
- La composición del comando es la siguiente
dd: comando para copiar o transformar datos
if=/dev/zero: usa como entrada un archivo especial que genera un flujo infinito de bytes en 0
bs=1G: establece el tamaño de bloque en 1 GB
count=10: procesa 10 bloques de 1 GB para generar 10 GB de datos en 0
gzip -c > 10GB.gz: comprime los datos de salida con gzip y los guarda en el archivo 10GB.gz
- En este caso, el archivo resultante mide alrededor de 10 MB
- En el servidor se agrega actualmente un middleware que verifica si la solicitud es maliciosa
- Se mantiene una lista negra de IPs que escanean repetidamente todo el sitio
- También se usan para la detección patrones en los que dejan spam y luego vuelven a comprobar si ese spam apareció en la página
if (ipIsBlackListed() || isMalicious()) {
header("Content-Encoding: gzip");
header("Content-Length: ". filesize(ZIP_BOMB_FILE_10G)); // 10 MB
readfile(ZIP_BOMB_FILE_10G);
exit;
}
- El costo es que, en ciertas situaciones, el servidor debe transferir un archivo de 10 MB
- Cuando una publicación se vuelve viral, se reduce a un archivo de 1 MB, que según el autor también funciona
Límites y alcance de uso
- Una Zip Bomb no es una defensa completa
- Puede detectarse fácilmente
- Puede evitarse
- El cliente podría leer solo parte del contenido
- Aun así, es suficiente como herramienta para frenar bots poco sofisticados que rastrean la web sin criterio y entorpecen el servidor
- Se puede ver un ejemplo de funcionamiento en una reproducción de logs del servidor: this replay of my server logs
1 comentarios
Opiniones de Hacker News
Alrededor de 2001 hubo una época en la que tenía una línea fija en casa y alojaba varias cosas en una máquina Linux doméstica.
Por una actualización de Windows NT, muchos sistemas activaron una función de cifrado oportunista que intentaba conectarse primero a cierto puerto para negociar s/wan y luego enviar tráfico TCP, y como veía seguido ese tráfico en el firewall no le di mucha importancia.
Pero había una máquina en particular que seguía intentando conectarse cada pocos segundos y era muy molesta; intenté contactar al administrador, pero no pude.
Al final avisé algo como “estoy por iniciar un nuevo servicio en ese puerto, espero que no cause problemas”, y como no hubo respuesta, levanté en ese puerto un servidor que leía de
/dev/urandomy tenía activadoTCP_NODELAY, entre otras cosas, para empujar datos aleatorios lo más rápido posible.La máquina NT mal configurada se conectaba, se tragaba datos aleatorios durante unos 5 segundos y desaparecía; 5 minutos después volvía, tomaba otra dosis de desbordamiento de búfer y desaparecía otra vez. Repitió ese patrón durante semanas hasta que desapareció por completo de Internet.
Suelo imaginar a algún administrador rascándose la cabeza, preguntándose por qué la máquina NT no dejaba de reiniciarse.
Toda solicitud debería tener tanto un límite de tiempo como un límite en la cantidad de datos que consumirá.
Así que hice un PDF de 100 páginas donde cada página era un gran rectángulo negro y lo mandé por una pasarela de email a fax, que en ese entonces era algo nuevo; en menos de una hora recibí una llamada furiosa, y los faxes se detuvieron.
La parte de “intenté contactar al administrador de la máquina, y eso era algo común” me parece especialmente interesante.
Después dejé vencer el dominio y esa RPi se moría cada 5 minutos; pensé que era un problema de energía, hasta que más tarde recordé esa tarea CRON.
En miles de casos, la razón misma para correr este tipo de servicios en una máquina NT era “para no necesitar un administrador”, y no hay que subestimarlo.
En los 90 y principios de los 2000 puse muchos servidores en Internet, y la práctica estándar en toda la industria era usar NT para no tener administrador.
Cuando era chico, hice una tontería a modo de broma en mi página web:
ln -s /dev/zero index.html.Los navegadores de la época no lo manejaban bien y casi se colgaban; a veces incluso tumbaban también el sistema del cliente.
Creo que más tarde los navegadores empezaron a revisar el contenido real y a cortar ese tipo de solicitudes.
Recién varios años después pude abrirlo finalmente.
squashfs, con encabezados adecuados y contenido interminable sin etiquetas de cierre, y hacer que el servidor no informe el tamaño del archivo antes de la descarga.¿Alguna idea?
favicon.icoque mataba navegadores.Creo que quizá era este: https://freedomhacker.net/annoying-favicon-crash-bug-firefox...
/dev/zipbomb.Hoy casi todos los navegadores aceptan zstd y brotli, así que este tipo de bombas podría ser aún más efectivo ahora.
Este comentario antiguo mostraba una impresionante relación de compresión de 1.2M:1, y zstd parece estar haciéndolo todavía mejor.
Aunque puede que los bots no soporten estándares de compresión modernos.
Por otro lado, eso podría ser una buena forma de bloquear bots: como todos los navegadores modernos soportan zstd, si lo aplicas de forma forzada a agentes de navegador que no estén en una lista permitida, puedes confundir automáticamente a los scrapers.
Depende en gran medida de transmitir la vista completa del usuario en cada interacción, y usando brotli sobre SSE se obtienen fácilmente relaciones de compresión de 200:1[2].
El problema es que un actor malicioso puede pedir un stream sin compresión.
Como brotli está soportado por el 98% de los navegadores, no envío datos a clientes que no soporten compresión brotli, y como muchos scrapers y bots tampoco la soportan, funciona bastante bien.
[1] demo de checkboxes
https://checkboxes.andersmurphy.com
[2] artículo sobre brotli SSE
https://andersmurphy.com/2025/04/15/why-you-should-use-brotl...
Es porque, en gzip de primera generación, el propio bloque de datos
0comprimidos tiene baja entropía, y zst anidado reduce un archivo de 10G a 99 bytes.No quiero probarlo personalmente.
Aunque se sale un poco del tema, me pareció divertido lo de que, en un trabajo anterior, un bot encontró una vulnerabilidad de WordPress y metió un script malicioso en el servidor
Me dio cierta tranquilidad saber que no soy el único al que, apenas 1 hora después de instalar WordPress, se le despliega mágicamente una shell PHP en el servidor
Nunca hay menos de 3; siempre está garantizado
Aunque no sea en la primera hora, en algún momento olvidarás aplicar un parche y acabará explotando
/wp-loginTambién sirve como buena forma de encontrar bots: si veo una IP pidiendo rutas relacionadas con CMS conocidos, la mando directo a un agujero de iptables
Les decía “desplieguen su primer servidor hello world con nginx” y enseguida empezaban a verse solicitudes raras en los logs
Hice algo parecido con ssh: encontré una forma de matar al cliente ssh que estaba intentando adivinar la contraseña de root
A cambio, varios script kiddies lanzaron DDoS contra mi pequeño servidor, así que terminé cambiando a identificar a los actores que claramente estaban haciendo cosas malas y bloquear sus IP con reglas de firewall
Aunque en IPv6 esto se está volviendo más difícil
Si alguien hace sus propias páginas web, también podría poner una zip bomb en la página mediante un enlace invisible para el ojo humano
Algo como texto blanco sobre fondo blanco, un anchor sin resaltado al hacer hover/click; el bot lo descarga y lo revisa, y lo mismo harían los crawlers y scrapers de IA
El problema eran bots muy simples que recorrían la web y enviaban spam burdo a cualquier formulario que pareciera publicarse
Al principio agregué un CAPTCHA simple con caracteres distorsionados, y eso bloqueó a muchos bots, pero no a todos
Al revisar los logs del servidor, vi que estos bots solo hacían tres solicitudes rápidas: la página con el formulario, la imagen del CAPTCHA y el POST de los datos del formulario; no cargaban nada de CSS ni JS
Así que agregué algunos campos más al formulario, los oculté con CSS y, si enviaban cualquier cosa en esos campos, hacía fallar la solicitud y bloqueaba la sesión
Además, hice que la imagen del CAPTCHA fuera un fondo CSS y cambié el
srcpor una imagen transparente; el spam se detuvo por completo y los usuarios reales no notaron nadahttps://github.com/skeeto/endlessh
Entre los dos, más bien parece más fácil
Las zip bombs son divertidas
Una vez encontré una vulnerabilidad en un producto de seguridad: no hacía bien el análisis de malware si era un archivo zip por encima de cierto tamaño, o si el archivo contenía uno
En la práctica, si metías una zip bomb dentro de un documento Office XML, el producto podía dejar pasar el archivo OOXML aunque contuviera malware fácilmente identificable
Probé desplegar esto en lugar del script de honeypot que usaba normalmente, pero no parece funcionar bien
En los logs del servidor web veo que los bots no descargan completo el veneno de 10 MB, sino que cortan en distintas longitudes
Hasta ahora no he visto que se lleven más de unos 1.5 MB
¿O quizá sí está funcionando? Tal vez mueren al decodificar sobre la marcha como stream
Por ejemplo, si queda registrado que leyeron 1.5 MB, quizá al decodificarlos al vuelo en memoria hasta 1.5 GB terminan crasheando
No hay forma de comprobarlo
Algo como contenido generado infinitamente, con montones de referencias a otras páginas generadas
Puede ayudar contra
wgetsimple y contra bots hasta que se adaptenDicho sea de paso, yo estoy del lado de los bots, pero no me molesta ayudar
Sospecho que algunos bots tienen un límite duro para el tamaño de los recursos que descargan
Como muchos son molestos bots de entrenamiento/scraping para LLM, incluso si enviar una zip bomb de 800 KB no los mata, al menos puede desperdiciar sus recursos de cómputo
Vale la pena señalar que esto no es un archivo zip clásico, sino una gzip bomb
No es el método de tumbar antivirus con zips anidados, sino que se comporta como una página web normal comprimida
Hace poco, parte de la infraestructura de elusión de censura de Tor Project se ejecutaba en el mismo sitio que una publicación de blog sobre zip bombs[0]
Uno de esos archivos zip fue rastreado por Google y terminó en una lista de dominios maliciosos, lo que rompió una parte bastante importante de la herramienta Snowflake de Tor
Tardaron semanas en resolverlo[1]
[0] https://www.bamsoftware.com/hacks/zipbomb/
[1] https://www.bamsoftware.com/hacks/zipbomb/#safebrowsing
Para proteger las cargas de mi aplicación, creaba particiones temporales de disco de tamaño fijo de unos 10 MB cada una y descomprimía ahí
Si alguien subía algo demasiado grande, el daño quedaba contenido ahí dentro
unzip -p | head -c 10MB