2 pontos por GN⁺ 2025-04-30 | 1 comentários | Compartilhar no WhatsApp
  • Um operador de blog pessoal envia um Zip Bomb baseado em gzip como resposta HTTP para bots maliciosos, a fim de reduzir varreduras de vulnerabilidades, spam e raspagem de conteúdo
  • Aproveitando o fluxo de Accept-Encoding: gzip, deflate usado por navegadores e crawlers legítimos, ele retorna 200 OK e Content-Encoding: gzip para requisições suspeitas
  • Um arquivo gzip de 1 MB se expande para cerca de 1 GB ao ser descompactado, e um de 10 MB para cerca de 10 GB, fazendo muitos bots esgotarem a memória ou interromperem a requisição
  • O middleware do servidor verifica IPs em blacklist e padrões de spam e, quando encontra uma correspondência, envia um arquivo Zip Bomb pré-gerado e encerra o processamento da requisição
  • Não é uma defesa completa, porque pode ser facilmente detectada e contornada, mas é suficiente para bloquear bots simples que atrapalham o servidor com crawling indiscriminado

Tráfego de bots e o contexto do uso de Zip Bomb

  • A maior parte do tráfego web vem de bots, e há usos legítimos como leitores de RSS, crawlers de mecanismos de busca e bots de IA em busca de conteúdo novo
  • O problema são os bots maliciosos operados por spammers, raspadores de conteúdo e hackers
    • Em um antigo emprego, bots encontraram vulnerabilidades no WordPress e inseriram scripts maliciosos no servidor
    • Esse servidor depois passou a fazer parte de uma botnet usada para DDoS
    • Um dos primeiros sites foi completamente removido da busca do Google por causa de spam gerado por bots
  • Depois dessas experiências, ele passou a usar Zip Bombs para proteger o servidor contra bots maliciosos

Como transformar compressão gzip em mecanismo de defesa

  • Um Zip Bomb é um arquivo compactado pequeno que, durante a descompactação, se expande para um arquivo muito grande e sobrecarrega a máquina
  • No início da web, a compressão gzip foi adotada para reduzir o volume de dados transmitidos em conexões lentas
    • Reduzir um arquivo HTML de 50 KB para 10 KB economizava 40 KB de transferência
    • Na internet discada, isso podia reduzir o tempo de download da página de 12 para 3 segundos
  • Ao fazer uma requisição, o navegador informa por cabeçalhos quais métodos de compressão ele suporta
Accept-Encoding: gzip, deflate
  • Se o servidor também oferecer suporte à compressão, ele retorna a versão compactada dos dados esperados
  • Bots de web crawling também suportam compressão como gzip para coletar grandes volumes de dados, e essa característica é usada como defesa

Resposta enviada para requisições maliciosas

  • Bots que varrem vulnerabilidades de segurança aparecem com frequência no blog, e a maioria é simplesmente ignorada
  • Quando uma requisição parece tentar injetar entrada maliciosa ou sondar respostas, ele envia uma resposta gzip junto com 200 OK
Content-Encoding: gzip
  • O tamanho do arquivo enviado varia entre 1 MB e 10 MB, dependendo da situação
    • Um arquivo de 1 MB cresce para cerca de 1 GB ao ser descompactado
    • Um arquivo de 10 MB cresce para cerca de 10 GB ao ser descompactado
  • O bot vê o cabeçalho, conclui que é um arquivo compactado e tenta descompactá-lo para inspecionar o conteúdo
  • À medida que o arquivo continua se expandindo, ele esgota a memória e o servidor ou script pode travar
  • Para scripts persistentes em que 1 MB não basta, ele envia um arquivo de 10 MB, e afirma que nesse caso o script encerra imediatamente

Exemplo de criação do Zip Bomb e aplicação no servidor

  • Ao criar um Zip Bomb, é preciso assumir o risco de travar ou danificar o próprio dispositivo
  • Um arquivo gzip que se descompacta em 10 GB pode ser gerado com o seguinte comando
dd if=/dev/zero bs=1G count=10 | gzip -c > 10GB.gz
  • A composição do comando é a seguinte
    • dd: comando para copiar ou converter dados
    • if=/dev/zero: usa como entrada um arquivo especial que gera um fluxo infinito de bytes zero
    • bs=1G: define o tamanho do bloco como 1 GB
    • count=10: processa 10 blocos de 1 GB para gerar 10 GB de dados zero
    • gzip -c > 10GB.gz: compacta os dados de saída com gzip e salva no arquivo 10GB.gz
  • Nesse caso, o arquivo resultante tem cerca de 10 MB
  • No servidor, foi adicionado um middleware que verifica se a requisição atual é maliciosa
    • É mantida uma blacklist de IPs que fazem varreduras repetidas em todo o site
    • Também são usados para detecção padrões em que alguém deixa spam e depois volta para verificar se ele apareceu na 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;
}
  • O custo é que, em certas situações, o servidor precisa transmitir um arquivo de 10 MB
  • Quando um texto viraliza, ele reduz para um arquivo de 1 MB, que segundo ele também funciona

Limitações e escopo de uso

  • Zip Bomb não é uma defesa completa
    • Pode ser facilmente detectado
    • Também pode ser contornado
    • O cliente pode ler apenas parte do conteúdo
  • Ainda assim, é suficiente como ferramenta para bloquear bots pouco sofisticados que fazem crawling sem critério e atrapalham o servidor
  • Um exemplo do funcionamento pode ser visto em um replay dos logs do servidor: this replay of my server logs

1 comentários

 
GN⁺ 2025-04-30
Opiniões do Hacker News
  • Por volta de 2001, eu tinha uma linha fixa em casa e hospedava várias coisas em uma máquina Linux doméstica
    Por causa de uma atualização do Windows NT, muitos sistemas passaram a ativar um recurso de criptografia oportunista que primeiro se conectava a uma determinada porta para negociar s/wan e depois tentava enviar tráfego TCP; eu via esse tipo de tráfego com frequência no firewall, então não dei muita importância
    Mas uma máquina específica continuava tentando se conectar a cada poucos segundos, o que ficou muito irritante, e tentei entrar em contato com o administrador, sem sucesso
    No fim, avisei algo como “vou iniciar um novo serviço nessa porta e espero que isso não cause problemas”; como não houve resposta, subi nessa porta um servidor que lia de /dev/urandom, ativava TCP_NODELAY e afins, e empurrava dados aleatórios o mais rápido possível
    A máquina NT mal configurada se conectava, bebia dados aleatórios por uns 5 segundos e sumia; 5 minutos depois voltava, tomava outra dose de buffer overflow e sumia de novo. Esse padrão se repetiu por algumas semanas, até ela desaparecer completamente da internet
    Às vezes imagino algum administrador coçando a cabeça, tentando entender por que a máquina NT não parava de reiniciar

    • Se você é programador, deve sempre impor um limite superior à quantidade de dados que recebe de terceiros
      Toda requisição deve ter tanto um limite de tempo quanto um limite para a quantidade de dados a consumir
    • Na mesma época, uma empresa enviava fax de spam toda sexta-feira e ignorou várias mensagens de voz educadas que deixei
      Então criei um PDF de 100 páginas em que todas as páginas eram um grande retângulo preto e o enviei pelo então novo gateway de e-mail para fax; recebi uma ligação furiosa em menos de uma hora, e os faxes pararam
    • Fico curioso sobre como, naquela época, normalmente se encontravam os contatos dos administradores de clientes arbitrários
      A parte “tentei falar com o administrador da máquina e isso era comum” é especialmente interessante
    • Uma vez fiz uma correção meia-boca na detecção de queda do meu servidor RPi em casa: ele dava ping em um domínio meu e, se falhasse, considerava que a rede tinha caído e reiniciava
      Depois que deixei o domínio expirar, esse RPi morria a cada 5 minutos e achei que fosse problema de energia; só mais tarde lembrei daquela tarefa CRON
    • Talvez você se surpreenda ao saber que, naquela época, na maioria das instalações NT que prestavam serviços, quase não havia administrador que percebesse o que estava acontecendo
      Em milhares de casos, o próprio motivo de rodar esse tipo de serviço em uma máquina NT era “para não precisar de administrador”, e isso não deve ser subestimado
      Nos anos 90 e início dos anos 2000, coloquei muitos servidores na internet, e a prática padrão em todo o setor era usar NT para funcionar sem administrador
  • Quando eu era criança, fiz uma bobagem de brincadeira e coloquei ln -s /dev/zero index.html no meu site
    Os navegadores da época não lidavam bem com isso e praticamente travavam; às vezes derrubavam até o sistema do cliente junto
    Mais tarde, acho que os navegadores começaram a verificar o conteúdo real e a interromper essas requisições

    • Uma vez alimentei um codificador repetidamente com a mesma linha de macroblocos e gerei um JPEG de 64k×64k
      Só consegui abri-lo finalmente anos depois
    • Fico imaginando se daria para criar um arquivo HTML de 500 TB em cima de squashfs, com cabeçalhos adequados, colocar um conteúdo infinito sem tags de fechamento e fazer o servidor não informar o tamanho do arquivo antes do download
      Alguma ideia?
    • Lembro de um favicon.ico que derrubava navegadores
      Acho que era este: https://freedomhacker.net/annoying-favicon-crash-bug-firefox...
    • Espero que não fosse uma situação em que se pagava banda por KiB
    • Talvez esteja na hora de criar um dispositivo /dev/zipbomb
  • Hoje em dia, quase todos os navegadores aceitam zstd e brotli, então esse tipo de bomba pode ser ainda mais eficaz agora
    This comentário antigo mostrava uma taxa de compressão impressionante de 1,2M:1, e zstd seems to be doing even better
    Só que bots talvez não suportem padrões modernos de compressão
    Por outro lado, isso pode ser uma boa forma de bloquear bots: como todos os navegadores modernos suportam zstd, aplicar isso à força a user agents de navegadores que não estejam na lista de permissões pode confundir scrapers automaticamente

    • Na prática, no meu demo Datastar de one million checkboxes[1], uso compressão para filtrar bots
      Ele depende muito de fazer streaming da visão completa do usuário a cada interação, e com brotli sobre SSE é fácil obter taxa de compressão de 200:1[2]
      O problema é que um agente malicioso pode solicitar um stream sem compressão
      Como brotli é suportado por 98% dos navegadores, não envio dados para clientes que não suportem compressão brotli; muitos scrapers e bots também não a suportam, então isso funciona bastante bem
      [1] demo checkboxes
      https://checkboxes.andersmurphy.com
      [2] artigo sobre brotli SSE
      https://andersmurphy.com/2025/04/15/why-you-should-use-brotl...
    • Se você aninhar gzip dentro de gzip, fica ainda menor
      Isso acontece porque, na primeira geração de gzip, o próprio bloco de dados 0 comprimido tem baixa entropia, e zst aninhado reduz um arquivo de 10G para 99 bytes
    • Fico curioso para saber como meu navegador reagiria ao receber uma bomba dessas
      Não quero testar pessoalmente
    • gzip está em toda parte e pode atormentar todos os crawlers
  • Embora a parte sobre bots encontrando vulnerabilidades no WordPress e colocando scripts maliciosos no servidor fuja um pouco do tema, é divertida
    Fiquei até mais tranquilo ao descobrir que não sou o único a ver um shell PHP ser implantado magicamente no servidor 1 hora depois de instalar o WordPress

    • Quando você assume o site WordPress de um cliente, vira um “olha só, temos 3 shells PHP com nomes de strings aleatórias”
      Nunca são menos de 3; é sempre garantido
    • Se quiser preservar a sanidade, não hospede WordPress por conta própria
      Mesmo que não seja na primeira hora, no momento em que você esquecer um patch, uma hora vai estourar
    • Nunca hospedei WordPress, mas, no instante em que você expõe um servidor HTTP à internet, começam a chegar requisições como /wp-login
      Isso também acaba sendo uma boa forma de encontrar bots; se vejo um IP pedindo caminhos relacionados a CMS famosos, jogo direto no buraco do iptables
    • WordPress é um excelente backdoor, e ainda vem com funções de CMS embutidas
    • Já usei isso ao ensinar DevOps
      Quando eu dizia “implante seu primeiro servidor nginx hello world”, logo começavam a aparecer requisições estranhas nos logs
  • Já fiz algo parecido com ssh: descobri uma forma de matar clientes ssh que tentavam adivinhar a senha do root
    O preço foi que vários script kiddies passaram a lançar DDoS contra meu pequeno servidor, então acabei mudando para uma abordagem de identificar agentes claramente mal-intencionados e bloquear seus IPs com regras de firewall
    Só que, no IPv6, isso está ficando mais difícil
    Se você cria suas próprias páginas web, também pode colocar uma zip bomb na página por meio de um link invisível aos olhos humanos
    Algo como texto branco em fundo branco, um anchor sem destaque em hover/click; o bot vai baixar e verificar, e crawlers e scrapers de IA também

    • Usei uma variação desse método no formulário de solicitação de conta do meu servidor fediverse
      O problema eram bots muito simples que vagavam pela web enviando spam tosco para todos os formulários que parecessem poder ser publicados
      No começo, adicionei um CAPTCHA simples com letras distorcidas, o que bloqueou muitos bots, mas não todos
      Pelos logs do servidor, vi que esses bots faziam rapidamente só três requisições: a página com o formulário, a imagem do CAPTCHA e o POST dos dados do formulário; não carregavam CSS nem JS
      Então coloquei mais alguns campos no formulário e os escondi com CSS; se qualquer coisa fosse enviada nesses campos, a requisição falhava e a sessão era bloqueada
      Além disso, transformei a imagem do CAPTCHA em um fundo CSS e troquei o src por uma imagem transparente; o spam parou completamente e usuários reais não perceberam nada
    • Se quiser impedir esse tipo de comportamento, vale dar uma olhada nisto
      https://github.com/skeeto/endlessh
    • Se o link é invisível aos olhos humanos, fico preocupado com o que acontece com usuários de leitores de tela
    • Não sei por que o bloqueio por firewall seria mais difícil no IPv6
      Entre os dois, parece até mais fácil
    • Links assim podem ficar visíveis para quem usa navegadores em modo texto, leitores de tela, bookmarklets que listam links da página etc.
  • Zip bombs são divertidas
    Certa vez encontrei uma vulnerabilidade em um produto de segurança que fazia com que ele não realizasse corretamente a varredura de malware em arquivos zip acima de certo tamanho, ou em arquivos que os contivessem
    Na prática, se você colocasse uma zip bomb dentro de um documento Office XML, esse produto podia deixar passar o arquivo OOXML mesmo que ele contivesse malware facilmente identificável

    • O problema de tamanho de arquivo ainda permanece em muitos EDRs conhecidos
  • Implantei isso no lugar do script de honeypot que eu costumava usar, mas não parece estar funcionando bem
    Pelos logs do servidor web, os bots não baixam todo o veneno de 10 MB; eles interrompem em vários tamanhos
    Até agora, não vi nenhum pegar mais do que cerca de 1,5 MB
    Ou será que está funcionando? Talvez eles estejam decodificando em streaming na hora e morrendo
    Por exemplo, se o log registrou que ele leu 1,5 MB, pode ter travado ao decodificar isso na memória, na hora, para 1,5 GB
    Não há como confirmar

    • Vale tentar um labirinto de conteúdo
      Algo como conteúdo gerado infinitamente, com um monte de referências para outras páginas geradas
      Pode ajudar contra wget simples e bots até eles se adaptarem
      Só acrescentando: eu estou do lado dos bots, mas não me importo de ajudar
    • Talvez seja preciso randomizar um pouco o tamanho do arquivo
      Imagino que alguns bots tenham limites rígidos para o tamanho dos recursos que baixam
      Como muitos deles são bots irritantes de treinamento/raspagem para LLM, mesmo que uma zip bomb de 800 KB não os mate, ainda pode desperdiçar os recursos computacionais deles
    • Se ele voltar, é porque detectou e evitou; se não voltar, é porque crashou. Missão cumprida
  • Vale apontar que isso não é um arquivo zip clássico, e sim uma gzip bomb
    Não é o método de derrubar antivírus com zips aninhados; funciona como uma página web comum compactada

  • Há algum tempo, parte da infraestrutura de circumvenção de censura do Tor Project era operada no mesmo site do post de blog sobre zip bombs[0]
    Um daqueles arquivos zip foi rastreado pelo Google e entrou em uma lista de domínios maliciosos, o que quebrou uma parte bem importante da ferramenta Snowflake do Tor
    Levou semanas para resolver[1]
    [0] https://www.bamsoftware.com/hacks/zipbomb/
    [1] https://www.bamsoftware.com/hacks/zipbomb/#safebrowsing

  • Para proteger os uploads da minha aplicação, criei partições temporárias de disco de tamanho fixo, com cerca de 10 MB cada, e descompactava os arquivos nelas
    Se alguém enviasse algo grande demais, o dano ficava confinado ali dentro

    • unzip -p | head -c 10MB
    • Você particionou o disco de propósito, quando bastava não descompactar arquivos absurdamente grandes?