2 Punkte von GN⁺ 2025-04-30 | 1 Kommentare | Auf WhatsApp teilen
  • Der Betreiber eines persönlichen Blogs schickt bösartigen Bots eine gzip-basierte Zip Bomb als HTTP-Antwort, um Schwachstellen-Scans, Spam und Content-Scraping zu reduzieren
  • Dabei wird der von normalen Browsern und Crawlern genutzte Ablauf mit Accept-Encoding: gzip, deflate ausgenutzt: Verdächtige Anfragen erhalten 200 OK und Content-Encoding: gzip
  • Eine 1-MB-gzip-Datei wächst beim Entpacken auf etwa 1 GB, eine 10-MB-Datei auf etwa 10 GB an, wodurch viele Bots ihren Speicher erschöpfen oder die Anfrage abbrechen
  • Die Server-Middleware prüft Blacklist-IPs und Spam-Muster; wenn eine Bedingung zutrifft, sendet sie eine vorab erzeugte Zip-Bomb-Datei und beendet anschließend die Verarbeitung der Anfrage
  • Da sie leicht erkannt und umgangen werden kann, ist sie keine vollständige Abwehrmaßnahme, reicht aber aus, um einfache Bots zu stoppen, die den Server durch wahlloses Crawling belasten

Hintergrund: Bot-Traffic und der Einsatz von Zip Bombs

  • Ein Großteil des Web-Traffics stammt von Bots, darunter auch legitime Anwendungsfälle wie RSS-Reader, Suchmaschinen-Crawler und KI-Bots, die neue Inhalte finden
  • Das Problem sind bösartige Bots, die von Spammern, Content-Scrapern und Hackern betrieben werden
    • Bei einem früheren Arbeitgeber fanden Bots eine WordPress-Schwachstelle und schleusten ein bösartiges Skript auf den Server ein
    • Dieser Server wurde später Teil eines Botnetzes, das für DDoS-Angriffe genutzt wurde
    • Eine der frühen Websites wurde wegen von Bots erzeugtem Spam vollständig aus der Google-Suche entfernt
  • Nach diesen Erfahrungen begann der Autor, Zip Bombs einzusetzen, um Server vor bösartigen Bots zu schützen

Wie gzip-Kompression zum Abwehrmittel wird

  • Eine Zip Bomb ist eine kleine komprimierte Datei, die sich beim Entpacken zu einer sehr großen Datei ausdehnt und dadurch eine Maschine belastet
  • In den frühen Tagen des Webs wurde gzip-Kompression eingeführt, um bei langsamen Internetverbindungen das Übertragungsvolumen zu reduzieren
    • Wenn eine 50-KB-HTML-Datei auf 10 KB schrumpft, spart das 40 KB Datenübertragung
    • Bei Einwahl-Internet konnte sich die Downloadzeit einer Seite dadurch von 12 Sekunden auf 3 Sekunden verringern
  • Browser teilen bei Anfragen per Header mit, welche Kompressionsverfahren sie unterstützen
Accept-Encoding: gzip, deflate
  • Wenn auch der Server Kompression unterstützt, gibt er die komprimierte Version der erwarteten Daten zurück
  • Web-Crawling-Bots unterstützen ebenfalls Kompression wie gzip, um große Datenmengen zu sammeln; diese Eigenschaft wird zur Abwehr genutzt

Antwort auf bösartige Anfragen

  • Im Blog tauchen häufig Bots auf, die nach Sicherheitslücken scannen; die meisten werden ignoriert
  • Wenn eine Anfrage als Versuch erkannt wird, bösartige Eingaben einzuschleusen oder Antworten auszukundschaften, wird zusammen mit 200 OK eine gzip-Antwort gesendet
Content-Encoding: gzip
  • Die Größe der übertragenen Datei liegt je nach Situation bei 1 MB bis 10 MB
    • Eine 1-MB-Datei wächst beim Entpacken auf etwa 1 GB an
    • Eine 10-MB-Datei wächst beim Entpacken auf etwa 10 GB an
  • Der Bot sieht den Header, erkennt die Datei als komprimiert und versucht, sie zu entpacken, um den Inhalt zu finden
  • Während die Datei immer weiter expandiert, kann der Speicher erschöpft werden und der Server oder das Skript abstürzen
  • Hartnäckige Skripte, bei denen eine 1-MB-Datei nicht ausreicht, erhalten eine 10-MB-Datei; in diesem Fall soll sich das Skript sofort beenden

Erzeugung einer Zip Bomb und Beispiel für den Servereinsatz

  • Beim Erstellen einer Zip Bomb muss man das Risiko in Kauf nehmen, das eigene Gerät zum Absturz zu bringen oder zu beschädigen
  • Eine gzip-Datei, die sich auf 10 GB entpackt, wird mit folgendem Befehl erzeugt
dd if=/dev/zero bs=1G count=10 | gzip -c > 10GB.gz
  • Der Befehl ist wie folgt aufgebaut
    • dd: Befehl zum Kopieren oder Konvertieren von Daten
    • if=/dev/zero: verwendet als Eingabe eine spezielle Datei, die einen unendlichen Strom von Null-Bytes erzeugt
    • bs=1G: setzt die Blockgröße auf 1 GB
    • count=10: verarbeitet zehn 1-GB-Blöcke und erzeugt so 10 GB Nulldaten
    • gzip -c > 10GB.gz: komprimiert die Ausgabedaten mit gzip und speichert sie als Datei 10GB.gz
  • In diesem Fall ist die resultierende Datei etwa 10 MB groß
  • Auf dem Server wird Middleware hinzugefügt, die prüft, ob die aktuelle Anfrage bösartig ist
    • Eine Blacklist von IPs, die die gesamte Website wiederholt scannen, wird gepflegt
    • Auch Muster, bei denen nach dem Hinterlassen von Spam erneut geprüft wird, ob dieser Spam auf der Seite erschienen ist, werden zur Erkennung genutzt
if (ipIsBlackListed() || isMalicious()) {
    header("Content-Encoding: gzip");
    header("Content-Length: ". filesize(ZIP_BOMB_FILE_10G)); // 10 MB
    readfile(ZIP_BOMB_FILE_10G);
    exit;
}
  • Der Kostenpunkt ist, dass der Server in bestimmten Situationen eine 10-MB-Datei übertragen muss
  • Wenn ein Beitrag viral geht, wird auf eine 1-MB-Datei heruntergeschaltet; auch diese Datei soll wirksam sein

Grenzen und Einsatzbereich

  • Eine Zip Bomb ist keine vollständige Abwehrmaßnahme
    • Sie kann leicht erkannt werden
    • Sie lässt sich auch umgehen
    • Der Client kann den Inhalt auch nur teilweise lesen
  • Dennoch reicht sie als Werkzeug aus, um weniger ausgefeilte Bots aufzuhalten, die wahllos das Web crawlen und den Server belasten
  • Ein Beispiel für das Verhalten ist in einem Replay der Server-Logs zu sehen: this replay of my server logs

1 Kommentare

 
GN⁺ 2025-04-30
Meinungen auf Hacker News
  • Um 2001 herum hatte ich zu Hause eine Standleitung und hostete allerlei Dinge auf einer Linux-Kiste zu Hause.
    Wegen eines Windows-NT-Updates aktivierten viele Systeme eine optimistische Verschlüsselungsfunktion, bei der sie sich zuerst mit einem bestimmten Port verbanden, s/wan aushandelten und danach TCP-Traffic senden wollten; ich sah solchen Traffic oft in der Firewall und hielt das nicht für weiter bemerkenswert.
    Aber eine bestimmte Maschine versuchte alle paar Sekunden immer wieder, sich zu verbinden, was extrem nervig war; ich versuchte, den Administrator zu kontaktieren, scheiterte aber.
    Schließlich schrieb ich sinngemäß: „Ich hoffe, es gibt keine Probleme, wenn ich auf diesem Port einen neuen Dienst starte“, und als keine Antwort kam, setzte ich auf diesem Port einen Server auf, der /dev/urandom las, TCP_NODELAY usw. aktivierte und so schnell wie möglich Zufallsdaten hinausschob.
    Die falsch konfigurierte NT-Kiste verband sich, trank etwa fünf Sekunden lang Zufallsdaten, verschwand, kam fünf Minuten später wieder, schluckte erneut Buffer-Overflow-Medizin und verschwand wieder; dieses Muster wiederholte sich einige Wochen lang, bis sie vollständig aus dem Internet verschwand.
    Ich stelle mir manchmal vor, wie irgendein Administrator sich am Kopf kratzte und sich fragte, warum die NT-Kiste ständig neu startete.

    • Als Programmierer sollte man für die Datenmenge, die man von anderen annimmt, immer eine Obergrenze setzen.
      Jede Anfrage sollte sowohl ein Zeitlimit als auch ein Limit für die zu verbrauchende Datenmenge haben.
    • Etwa zur selben Zeit schickte irgendeine Firma jeden Freitag Spam-Faxe, und mehrere höfliche Sprachnachrichten wurden ignoriert.
      Also erstellte ich ein 100-seitiges PDF, bei dem jede Seite ein großes schwarzes Rechteck war, und schickte es über eines der damals neuen E-Mail-zu-Fax-Gateways; innerhalb einer Stunde kam ein wütender Anruf, und die Faxe hörten auf.
    • Ich frage mich, wie man damals üblicherweise die Kontaktdaten des Administrators eines beliebigen Clients gefunden hat.
      Besonders interessant ist die Stelle „ich versuchte, den Administrator der Kiste zu kontaktieren, und das war üblich“.
    • Ich habe einmal die Down-Erkennung meines RPi-Heimservers schlampig repariert: Er pingte eine Domain, die mir gehörte, und wenn das fehlschlug, nahm er an, das Netzwerk sei weg, und startete neu.
      Nachdem ich die Domain hatte auslaufen lassen, starb dieser RPi alle fünf Minuten, und ich dachte, es sei ein Stromproblem; später fiel mir dieser CRON-Job wieder ein.
    • Es mag überraschen, aber bei den meisten NT-Installationen, die damals Dienste bereitstellten, gab es kaum einen Administrator, der bemerkt hätte, was vor sich ging.
      Der eigentliche Grund, solche Dienste auf NT-Kisten laufen zu lassen, war in Tausenden Fällen gerade „damit man keinen Administrator braucht“, und das sollte man nicht unterschätzen.
      In den 90ern und frühen 2000ern habe ich viele Server ins Internet gestellt, und die branchenweite Standardpraxis war: Man nutzte NT, um ohne Administrator auszukommen.
  • Als Kind habe ich aus dummem Spaß einmal auf meiner Homepage ln -s /dev/zero index.html gesetzt.
    Die Browser damals kamen damit nicht gut zurecht und blieben fast stehen; manchmal riss es sogar das Client-System mit.
    Später begannen Browser anscheinend, den tatsächlichen Inhalt zu prüfen und solche Anfragen abzubrechen.

    • Einmal habe ich einem Encoder immer wieder dieselbe Makroblock-Zeile gefüttert und daraus ein 64k×64k-JPEG gemacht.
      Erst Jahre später konnte ich es schließlich öffnen.
    • Ich frage mich, ob man auf squashfs eine 500-TB-HTML-Datei mit passenden Headern erstellen kann, endlosen Inhalt ohne schließende Tags hineinlegt und den Server dazu bringt, vor dem Download keine Dateigröße zu melden.
      Irgendwelche Ideen?
    • Mir fällt ein favicon.ico ein, das Browser zum Absturz brachte.
      Vermutlich war es dieses hier: https://freedomhacker.net/annoying-favicon-crash-bug-firefox...
    • Ich hoffe, das war keine Situation, in der Bandbreite pro KiB abgerechnet wurde.
    • Vielleicht ist es jetzt an der Zeit, ein /dev/zipbomb-Device zu bauen.
  • Heutzutage akzeptieren fast alle Browser zstd und brotli, also könnten solche Bomben heute sogar effektiver sein.
    Dieser frühere Kommentar zeigte ein beeindruckendes Kompressionsverhältnis von 1,2M:1, und zstd seems to be doing even better
    Allerdings unterstützen Bots moderne Kompressionsstandards möglicherweise nicht.
    Umgekehrt könnte genau das eine gute Methode zum Blockieren von Bots sein: Da alle modernen Browser zstd unterstützen, könnte man es für nicht auf der Allowlist stehende Browser-Agents erzwingen und Scraper damit automatisch durcheinanderbringen.

    • Tatsächlich filtere ich in meiner one million checkboxes Datastar demo[1] Bots per Kompression heraus.
      Sie hängt stark davon ab, bei jeder Interaktion die komplette Benutzeransicht zu streamen; mit brotli über SSE erreicht man leicht auch ein Kompressionsverhältnis von 200:1[2].
      Das Problem ist, dass ein böswilliger Akteur einen Stream ohne Kompression anfordern kann.
      Da brotli von 98 % der Browser unterstützt wird, sende ich keine Daten an Clients, die brotli-Kompression nicht unterstützen; viele Scraper und Bots unterstützen sie ebenfalls nicht, und das funktioniert ziemlich gut.
      [1] checkboxes demo
      https://checkboxes.andersmurphy.com
      [2] article on brotli SSE
      https://andersmurphy.com/2025/04/15/why-you-should-use-brotl...
    • Wenn man gzip noch einmal in gzip verschachtelt, wird es kleiner.
      Das liegt daran, dass der im ersten gzip-Durchlauf komprimierte 0-Datenblock selbst niedrige Entropie hat; verschachteltes zst reduziert eine 10G-Datei auf 99 Byte.
    • Ich frage mich, wie mein Browser reagieren würde, wenn er so eine Bombe bekäme.
      Selbst ausprobieren möchte ich es nicht.
    • gzip ist überall und kann jedem Crawler das Leben schwer machen.
  • Der Teil darüber, dass bei einem früheren Arbeitgeber ein Bot WordPress-Schwachstellen fand und ein bösartiges Skript auf dem Server platzierte, ist zwar leicht off-topic, aber interessant
    Es beruhigt mich fast, zu wissen, dass nicht nur mir passiert, dass innerhalb einer Stunde nach der Installation von WordPress wie von Zauberhand eine PHP-Shell auf dem Server ausgerollt wird

    • Wenn man eine WordPress-Site eines Kunden übernimmt, heißt es dann: „Oh, da sind ja drei PHP-Shells mit zufälligen String-Namen“
      Weniger als drei sind es nie, das ist immer garantiert
    • Wenn man bei Verstand bleiben will, sollte man WordPress nicht selbst hosten
      Selbst wenn es nicht in der ersten Stunde passiert: Irgendwann vergisst man einen Patch, und dann knallt es
    • Ich habe nie WordPress gehostet, aber sobald man einen HTTP-Server ins Internet stellt, kommen Anfragen wie /wp-login rein
      Das ist auch eine gute Methode, Bots zu finden: Wenn ich IPs sehe, die Pfade bekannter CMS anfragen, werfe ich sie direkt in ein iptables-Loch
    • WordPress ist eine hervorragende Backdoor und hat sogar CMS-Funktionen eingebaut
    • Ich habe das schon einmal im DevOps-Unterricht genutzt
      Wenn man sagt: „Deployt euren ersten hello-world-nginx-Server“, tauchen sofort seltsame Anfragen in den Logs auf
  • Bei ssh habe ich etwas Ähnliches gemacht: Ich fand heraus, wie man ssh-Clients lahmlegt, die das root-Passwort erraten wollten
    Als Preis dafür haben mehrere Script-Kiddies meinen kleinen Server mit DDoS angegriffen, und am Ende bin ich dazu übergegangen, eindeutig böswillige Akteure zu identifizieren und ihre IPs per Firewall-Regel zu blockieren
    Bei IPv6 wird das allerdings schwieriger
    Wer eigene Webseiten baut, könnte auch eine Zip-Bombe über einen Link in die Seite einbauen, der für menschliche Augen unsichtbar ist
    Zum Beispiel weißer Text auf weißem Hintergrund, ein Anchor ohne Hover-/Click-Hervorhebung; Bots laden ihn herunter und prüfen ihn, Crawler und AI-Scraper ebenso

    • Auf dem Account-Antragsformular meines Fediverse-Servers habe ich eine Variante davon verwendet
      Das Problem waren sehr einfache Bots, die durchs Web streifen und groben Spam in jedes Formular kippen, das so aussieht, als würde es veröffentlicht
      Zunächst fügte ich ein einfaches CAPTCHA mit verzerrten Zeichen hinzu, was viele Bots blockierte, aber nicht alle
      In den Server-Logs sah ich, dass diese Bots schnell nur drei Requests absetzten: die Seite mit dem Formular, das CAPTCHA-Bild und den POST-Request mit den Formulardaten; CSS oder JS luden sie gar nicht
      Also fügte ich dem Formular ein paar weitere Felder hinzu, versteckte sie per CSS und ließ den Request fehlschlagen sowie die Session sperren, wenn in diesen Feldern irgendetwas übermittelt wurde
      Außerdem machte ich das CAPTCHA-Bild zu einem CSS-Hintergrund und ersetzte src durch ein transparentes Bild; danach hörte der Spam komplett auf, und echte Nutzer bemerkten nichts
    • Wenn man so etwas unterbinden will, lohnt sich ein Blick hierauf
      https://github.com/skeeto/endlessh
    • Bei Links, die für menschliche Augen nicht sichtbar sind, frage ich mich, was mit Screenreader-Nutzern passiert
    • Ich weiß nicht, warum Firewall-Blocking bei IPv6 schwieriger sein soll
      Von den beiden wirkt es eher einfacher
    • Solche Links können für Menschen sichtbar sein, die Textbrowser, Screenreader, Bookmarklets zum Auflisten von Seitenlinks usw. verwenden
  • Zip-Bomben sind interessant
    Ich habe einmal in einem Sicherheitsprodukt eine Schwachstelle gefunden, bei der es Dateien nicht richtig auf Malware prüfte, wenn es sich um ein Zip-Archiv über einer bestimmten Größe handelte oder wenn sie ein solches enthielten
    In der Praxis konnte man eine Zip-Bombe in ein Office-XML-Dokument packen, und das Produkt ließ die OOXML-Datei durch, selbst wenn sie leicht erkennbare Malware enthielt

    • Bei vielen bekannten EDR-Produkten bestehen Probleme mit der Dateigröße immer noch
  • Ich habe das anstelle meines üblichen Honeypot-Skripts ausgerollt, aber es scheint nicht gut zu funktionieren
    In den Webserver-Logs sehe ich, dass die Bots das 10-MB-Gift nicht vollständig herunterladen, sondern bei verschiedenen Längen abbrechen
    Bisher habe ich nicht gesehen, dass mehr als etwa 1,5 MB geholt wurden
    Oder funktioniert es vielleicht doch? Möglicherweise decodieren sie den Stream on the fly und sterben dabei
    Wenn zum Beispiel protokolliert wurde, dass 1,5 MB gelesen wurden, könnte es sein, dass sie diese im Speicher on the fly zu 1,5 GB decodiert haben und dabei gecrasht sind
    Nachprüfen kann man es nicht

    • Ein Content-Labyrinth könnte einen Versuch wert sein
      Etwa unendlich generierter Content mit vielen Verweisen auf andere generierte Seiten
      Das kann gegen simples wget und Bots helfen, bis sie sich angepasst haben
      Nebenbei: Ich bin zwar eher auf der Bot-Seite, aber beim Helfen habe ich kein Problem
    • Vielleicht müsste man die Dateigröße halbwegs randomisieren
      Manche Bots haben vermutlich harte Limits für die Größe von Ressourcen, die sie herunterladen
      Da viele davon lästige LLM-Trainings-/Scraping-Bots sind, kann man mit einer 800-KB-Zip-Bombe ihre Rechenressourcen verschwenden, selbst wenn man sie nicht abschießen kann
    • Wenn sie wiederkommen, haben sie es erkannt und umgehen es; wenn sie nicht wiederkommen, sind sie gecrasht – Mission erfüllt
  • Es ist erwähnenswert, dass das hier keine klassische Zip-Datei ist, sondern eine Gzip-Bombe
    Sie bringt nicht per verschachteltem Zip einen Virenscanner zu Fall, sondern verhält sich wie eine normale komprimierte Webseite

  • Vor einiger Zeit lief ein Teil der Zensurumgehungs-Infrastruktur des Tor Project auf derselben Site wie der Blogpost über Zip-Bomben[0]
    Eine dieser Zip-Dateien wurde von Google gecrawlt und landete auf der Liste bösartiger Domains, was einen ziemlich wichtigen Teil von Tors Snowflake-Tool kaputtmachte
    Die Behebung dauerte Wochen[1]
    [0] https://www.bamsoftware.com/hacks/zipbomb/
    [1] https://www.bamsoftware.com/hacks/zipbomb/#safebrowsing

  • Um Uploads meiner Anwendung zu schützen, habe ich jeweils etwa 10 MB große temporäre Festplattenpartitionen fester Größe angelegt und dort hinein entpackt
    Wenn jemand etwas zu Großes hochlädt, bleibt der Schaden darin eingeschlossen

    • unzip -p | head -c 10MB
    • Hast du wirklich die Platte partitioniert, statt einfach keine absurd großen Dateien zu entpacken?