2 điểm bởi GN⁺ 2025-04-30 | 1 bình luận | Chia sẻ qua WhatsApp
  • Người vận hành blog cá nhân gửi Zip Bomb dựa trên gzip làm phản hồi HTTP tới các bot độc hại để giảm quét lỗ hổng, spam và cào nội dung
  • Tận dụng luồng Accept-Encoding: gzip, deflate mà trình duyệt và crawler bình thường sử dụng, các yêu cầu đáng ngờ sẽ nhận về 200 OKContent-Encoding: gzip
  • Tệp gzip 1MB khi giải nén sẽ phình ra khoảng 1GB, còn tệp 10MB sẽ thành khoảng 10GB, khiến nhiều bot cạn bộ nhớ hoặc dừng yêu cầu
  • Middleware của máy chủ kiểm tra IP trong danh sách đen và các mẫu spam, rồi nếu khớp điều kiện thì gửi tệp Zip Bomb được tạo sẵn và kết thúc xử lý yêu cầu
  • Dù có thể dễ bị phát hiện và né tránh nên không phải biện pháp phòng thủ hoàn hảo, cách này vẫn đủ để chặn các bot đơn giản gây cản trở máy chủ bằng cách crawl bừa bãi

Bối cảnh lưu lượng bot và lý do dùng Zip Bomb

  • Phần lớn lưu lượng web đến từ bot, trong đó có các mục đích hợp lệ như trình đọc RSS, crawler của công cụ tìm kiếm, hay bot AI đi tìm nội dung mới
  • Vấn đề là các bot độc hại do spammer, kẻ cào nội dung và hacker vận hành
    • Ở nơi làm việc trước đây, bot đã tìm lỗ hổng WordPress và chèn script độc hại vào máy chủ
    • Máy chủ đó sau này trở thành một phần của botnet dùng cho DDoS
    • Một trong những website đầu tiên đã bị loại hoàn toàn khỏi tìm kiếm Google vì spam do bot tạo ra
  • Sau những trải nghiệm đó, tác giả bắt đầu dùng Zip Bomb để bảo vệ máy chủ khỏi bot độc hại

Biến nén gzip thành công cụ phòng thủ

  • Zip Bomb là tệp nén nhỏ nhưng trong quá trình giải nén sẽ mở rộng thành tệp rất lớn, tạo gánh nặng cho máy
  • Ở thời kỳ đầu của web, nén gzip được đưa vào để giảm lượng dữ liệu truyền trên các kết nối Internet chậm
    • Tệp HTML 50KB nếu giảm xuống 10KB sẽ tiết kiệm được 40KB truyền tải
    • Với Internet quay số, thời gian tải trang có thể giảm từ 12 giây xuống 3 giây
  • Khi gửi yêu cầu, trình duyệt báo cho máy chủ biết các kiểu nén mà nó hỗ trợ qua header
Accept-Encoding: gzip, deflate
  • Nếu máy chủ cũng hỗ trợ nén, nó sẽ trả về phiên bản đã nén của dữ liệu được yêu cầu
  • Các bot crawl web cũng hỗ trợ nén như gzip để thu thập lượng dữ liệu lớn, và đặc tính này được tận dụng cho mục đích phòng thủ

Phản hồi gửi tới yêu cầu độc hại

  • Trên blog thường xuyên xuất hiện bot quét lỗ hổng bảo mật, và phần lớn bị bỏ qua
  • Nhưng nếu một yêu cầu bị đánh giá là đang cố chèn đầu vào độc hại hoặc dò xét phản hồi, máy chủ sẽ gửi phản hồi gzip kèm 200 OK
Content-Encoding: gzip
  • Kích thước tệp được gửi là 1MB~10MB tùy tình huống
    • Tệp 1MB khi giải nén sẽ tăng lên khoảng 1GB
    • Tệp 10MB khi giải nén sẽ tăng lên khoảng 10GB
  • Nhìn vào header, bot sẽ cho rằng đó là tệp nén và cố giải nén để tìm nội dung
  • Khi tệp tiếp tục phình ra, nó có thể làm cạn bộ nhớ và khiến máy chủ hoặc script bị crash
  • Với các script lì lợm mà tệp 1MB chưa đủ hiệu quả, tác giả gửi tệp 10MB; trong trường hợp đó script được cho là sẽ thoát ngay lập tức

Ví dụ tạo Zip Bomb và áp dụng trên máy chủ

  • Khi tạo Zip Bomb, bạn phải chấp nhận rủi ro vì có thể tự làm thiết bị của mình crash hoặc hỏng hóc
  • Tệp gzip giải nén thành 10GB được tạo bằng lệnh sau
dd if=/dev/zero bs=1G count=10 | gzip -c > 10GB.gz
  • Cấu trúc lệnh như sau
    • dd: lệnh sao chép hoặc chuyển đổi dữ liệu
    • if=/dev/zero: dùng tệp đặc biệt tạo ra luồng byte 0 vô hạn làm đầu vào
    • bs=1G: đặt kích thước khối là 1GB
    • count=10: xử lý 10 khối 1GB để tạo ra 10GB dữ liệu 0
    • gzip -c > 10GB.gz: nén dữ liệu đầu ra bằng gzip và lưu thành tệp 10GB.gz
  • Trong trường hợp này, kích thước tệp kết quả là khoảng 10MB
  • Trên máy chủ, tác giả thêm middleware để kiểm tra xem yêu cầu hiện tại có độc hại hay không
    • Duy trì danh sách đen các IP quét lặp đi lặp lại toàn bộ website
    • Cũng dùng các mẫu như để lại spam rồi quay lại kiểm tra xem spam đó đã xuất hiện trên trang hay chưa để phát hiện
if (ipIsBlackListed() || isMalicious()) {
    header("Content-Encoding: gzip");
    header("Content-Length: ". filesize(ZIP_BOMB_FILE_10G)); // 10 MB
    readfile(ZIP_BOMB_FILE_10G);
    exit;
}
  • Cái giá phải trả là trong một số tình huống, máy chủ phải truyền tệp 10MB
  • Khi bài viết trở nên viral, tác giả hạ xuống tệp 1MB, và cho biết tệp này cũng có hiệu quả

Giới hạn và phạm vi sử dụng

  • Zip Bomb không phải là biện pháp phòng thủ hoàn hảo
    • Có thể dễ dàng bị phát hiện
    • Cũng có thể bị né tránh
    • Client cũng có thể chỉ đọc một phần nội dung
  • Dù vậy, nó vẫn đủ tốt như một công cụ để chặn các bot không tinh vi crawl web vô tội vạ và làm phiền máy chủ
  • Có thể xem ví dụ hoạt động trong bản phát lại log máy chủ: this replay of my server logs

1 bình luận

 
GN⁺ 2025-04-30
Ý kiến trên Hacker News
  • Khoảng năm 2001, tôi từng có đường truyền cố định ở nhà và host linh tinh trên một máy Linux tại nhà
    Vì một bản cập nhật Windows NT, nhiều hệ thống đã bật một tính năng mã hóa lạc quan: trước hết kết nối tới một cổng cụ thể để thương lượng s/wan rồi mới gửi lưu lượng TCP; tôi hay thấy kiểu lưu lượng đó trong firewall nên cũng không để ý lắm
    Nhưng có riêng một máy cứ vài giây lại thử kết nối, phiền quá, tôi cố liên hệ với quản trị viên nhưng không được
    Cuối cùng tôi thông báo kiểu “tôi sắp khởi chạy một dịch vụ mới trên cổng đó, hy vọng sẽ không có vấn đề gì”, rồi khi không nhận được phản hồi, tôi dựng một server trên cổng đó đọc từ /dev/urandom, bật TCP_NODELAY và những thứ tương tự, đẩy dữ liệu ngẫu nhiên nhanh nhất có thể
    Con máy NT cấu hình sai đó kết nối vào, uống dữ liệu ngẫu nhiên chừng 5 giây rồi biến mất; 5 phút sau lại quay lại, uống thêm một liều thuốc tràn bộ đệm rồi lại biến mất. Mẫu này lặp lại trong vài tuần, rồi nó biến mất hẳn khỏi Internet
    Tôi vẫn hay tưởng tượng có quản trị viên nào đó đã vò đầu bứt tai không hiểu vì sao con máy NT cứ liên tục reboot

    • Nếu là lập trình viên, bạn luôn phải đặt giới hạn trên cho lượng dữ liệu nhận từ người khác
      Mọi request đều nên có cả giới hạn thời gian lẫn giới hạn lượng dữ liệu được tiêu thụ
    • Cũng vào khoảng thời gian đó, có một công ty cứ thứ Sáu hằng tuần gửi fax spam, và dù tôi nhiều lần lịch sự để lại tin nhắn thoại, họ vẫn phớt lờ
      Thế là tôi tạo một PDF 100 trang mà trang nào cũng là một hình chữ nhật đen lớn, rồi gửi qua một cổng email-to-fax khi đó còn mới; trong vòng một giờ đã có cuộc gọi giận dữ, và fax cũng dừng lại
    • Tôi tò mò hồi đó mọi người thường tìm thông tin liên hệ của quản trị viên một client bất kỳ như thế nào
      Đoạn “tôi đã cố liên hệ với quản trị viên của chiếc máy, và chuyện đó là phổ biến” đặc biệt thú vị
    • Tôi từng vá tạm phần phát hiện downtime cho server RPi ở nhà: nó ping một domain tôi sở hữu, nếu thất bại thì coi như mạng bị ngắt và reboot
      Sau khi để domain hết hạn, con RPi này chết mỗi 5 phút, tôi cứ tưởng là vấn đề nguồn điện, mãi sau mới nhớ ra tác vụ CRON đó
    • Bạn có thể sẽ ngạc nhiên khi biết rằng phần lớn các bản cài NT cung cấp dịch vụ thời đó gần như không có quản trị viên nào để nhận ra chuyện gì đang xảy ra
      Lý do người ta chạy những dịch vụ như vậy trên máy NT trong hàng nghìn trường hợp chính là “để khỏi cần quản trị viên”, đừng đánh giá thấp điều đó
      Tôi đã đưa nhiều server lên Internet trong thập niên 90 và đầu những năm 2000, và thực hành tiêu chuẩn trên toàn ngành là dùng NT để khỏi cần quản trị viên
  • Hồi nhỏ, tôi từng ngu ngốc nghịch bằng cách đặt ln -s /dev/zero index.html trên homepage của mình
    Trình duyệt thời đó xử lý việc này rất kém nên gần như bị đơ, thỉnh thoảng còn kéo cả hệ thống client chết theo
    Về sau có vẻ các trình duyệt bắt đầu kiểm tra nội dung thực tế và dừng những request như vậy

    • Có lần tôi nạp mãi cùng một dòng macroblock vào encoder và tạo ra một JPEG 64k×64k
      Mãi vài năm sau cuối cùng tôi mới mở được nó
    • Tôi tự hỏi liệu có thể tạo một file HTML 500TB với header phù hợp trên squashfs, nhồi nội dung vô tận không có thẻ đóng, rồi khiến server không báo kích thước file trước khi tải xuống không
      Có ý tưởng nào không?
    • Nhớ đến favicon.ico từng làm sập trình duyệt
      Chắc là cái này: https://freedomhacker.net/annoying-favicon-crash-bug-firefox...
    • Hy vọng khi đó bạn không phải trả tiền băng thông theo đơn vị KiB
    • Có lẽ đã đến lúc tạo thiết bị /dev/zipbomb
  • Ngày nay hầu như mọi trình duyệt đều chấp nhận zstdbrotli, nên kiểu bom này có khi còn hiệu quả hơn bây giờ
    Bình luận cũ này cho thấy tỷ lệ nén ấn tượng 1,2M:1, và zstd seems to be doing even better
    Tuy nhiên bot có thể không hỗ trợ các chuẩn nén hiện đại
    Ngược lại, đó cũng có thể là một cách tốt để chặn bot: vì mọi trình duyệt hiện đại đều hỗ trợ zstd, nếu cưỡng ép áp dụng nó cho các browser agent không nằm trong allowlist thì có thể tự động làm rối các scraper

    • Thực tế là tôi đang dùng nén để lọc bot trong bản demo one million checkboxes Datastar[1] của mình
      Nó phụ thuộc nhiều vào việc stream toàn bộ góc nhìn của người dùng ở mỗi tương tác; dùng brotli trên SSE thì dễ đạt tỷ lệ nén 200:1[2]
      Vấn đề là tác nhân độc hại có thể yêu cầu stream không nén
      Brotli được 98% trình duyệt hỗ trợ, nên tôi không gửi dữ liệu cho client không hỗ trợ nén brotli; nhiều scraper và bot cũng không hỗ trợ nó, nên cách này hoạt động khá tốt
      [1] checkboxes demo
      https://checkboxes.andersmurphy.com
      [2] article on brotli SSE
      https://andersmurphy.com/2025/04/15/why-you-should-use-brotl...
    • Nếu lồng gzip bên trong gzip nữa thì còn nhỏ hơn
      Vì trong thế hệ gzip đầu tiên, chính khối dữ liệu 0 đã nén lại có entropy thấp, và zst lồng nhau có thể giảm file 10G xuống còn 99 byte
    • Tôi tò mò trình duyệt của mình sẽ phản ứng thế nào khi nhận phải một quả bom như vậy
      Nhưng tôi không muốn tự thử
    • gzip có mặt ở khắp nơi, và có thể làm khổ mọi crawler
  • Dù hơi lạc đề một chút, phần kể rằng ở công ty cũ bot đã tìm lỗ hổng WordPress rồi đưa script độc hại lên máy chủ vẫn khá thú vị
    Biết rằng chuyện một PHP shell được triển khai lên máy chủ như có phép màu chỉ sau 1 giờ cài WordPress không chỉ xảy ra với riêng mình lại khiến tôi thấy yên tâm hơn

    • Khi tiếp nhận site WordPress của khách hàng thì sẽ thành kiểu: “Ồ, có 3 PHP shell với tên là chuỗi ngẫu nhiên này”
      Chưa bao giờ ít hơn 3 cái, lúc nào cũng được đảm bảo
    • Nếu muốn giữ đầu óc tỉnh táo thì đừng tự host WordPress
      Dù không phải trong giờ đầu tiên, rồi sẽ có lúc bạn quên vá lỗi và cuối cùng nó sẽ nổ
    • Tôi chưa từng host WordPress, nhưng ngay khi để lộ một HTTP server ra Internet là sẽ có các request kiểu /wp-login gửi tới
      Nó cũng trở thành một cách tốt để tìm bot, nên hễ thấy IP nào request các đường dẫn liên quan đến CMS phổ biến là tôi nhét thẳng vào lỗ iptables
    • WordPress là một backdoor tuyệt vời, lại còn tích hợp sẵn cả chức năng CMS
    • Tôi từng dùng chuyện này khi dạy DevOps
      Bảo “hãy triển khai máy chủ nginx hello world đầu tiên” là gần như lập tức trong log bắt đầu xuất hiện các request kỳ lạ
  • Tôi cũng từng làm chuyện tương tự với ssh, và đã tìm ra cách giết các ssh client đang đoán mật khẩu root
    Cái giá phải trả là vài script kiddie đã DDoS con server nhỏ của tôi, nên cuối cùng tôi chuyển sang cách nhận diện những tác nhân rõ ràng đang làm việc xấu rồi chặn IP bằng rule firewall
    Tuy nhiên với IPv6 thì việc này đang khó hơn
    Nếu bạn tự làm trang web, bạn cũng có thể đặt zip bomb vào trang bằng một liên kết mà mắt người không thấy được
    Kiểu anchor chữ trắng trên nền trắng, không có highlight khi hover/click; bot sẽ tải về kiểm tra, crawler và AI scraper cũng vậy

    • Tôi đã dùng một biến thể của cách này trong form yêu cầu tài khoản trên máy chủ fediverse của mình
      Vấn đề là những bot rất đơn giản đi khắp web và gửi spam thô sơ vào mọi form trông có vẻ sẽ được đăng công khai
      Ban đầu tôi thêm một CAPTCHA đơn giản bằng chữ bị bóp méo và chặn được nhiều bot, nhưng không phải tất cả
      Nhìn log máy chủ thì thấy các bot này chỉ gửi nhanh ba request: trang có form, ảnh CAPTCHA, và POST dữ liệu form; hoàn toàn không tải CSS hay JS
      Vì vậy tôi thêm vài field nữa vào form rồi ẩn chúng bằng CSS; nếu có bất cứ thứ gì được gửi trong các field đó thì request sẽ bị fail và session bị chặn
      Ngoài ra tôi biến ảnh CAPTCHA thành background CSS và đổi src thành ảnh trong suốt; spam dừng hẳn, còn người dùng thật thì không nhận ra gì cả
    • Nếu muốn ngăn hành vi kiểu này thì đáng xem cái này
      https://github.com/skeeto/endlessh
    • Nếu liên kết không nhìn thấy bằng mắt người thì tôi lo người dùng screen reader sẽ ra sao
    • Tôi không hiểu vì sao chặn bằng firewall trên IPv6 lại khó hơn
      Trong hai cái thì trông nó còn dễ hơn
    • Những liên kết như vậy có thể hiện ra với người dùng trình duyệt văn bản, screen reader, hoặc bookmarklet liệt kê các liên kết trên trang
  • Zip bomb rất thú vị
    Tôi từng phát hiện một lỗ hổng trong một sản phẩm bảo mật: nếu đó là file zip archive lớn hơn một kích thước nhất định, hoặc là file chứa archive như vậy, thì việc quét mã độc không được thực hiện đúng cách
    Thực tế, nếu nhét zip bomb vào bên trong tài liệu Office XML, sản phẩm đó có thể cho file OOXML đi qua dù bên trong có mã độc rất dễ nhận diện

    • Vấn đề kích thước file vẫn còn tồn tại trong nhiều EDR nổi tiếng
  • Tôi thử triển khai cái này thay cho script honeypot vẫn dùng, nhưng có vẻ không hoạt động tốt
    Nhìn log web server thì thấy bot không tải hết cục độc dược 10MB, mà ngắt ở nhiều độ dài khác nhau
    Đến giờ tôi chưa thấy cái nào lấy quá khoảng 1,5MB
    Hay là nó vẫn đang hoạt động? Có thể chúng đang giải mã tức thời theo stream rồi chết
    Ví dụ nếu log ghi là đã đọc 1,5MB, có thể nó đã giải mã tức thời thành 1,5GB trong bộ nhớ rồi crash
    Không có cách nào xác nhận

    • Có thể thử mê cung nội dung
      Kiểu nội dung sinh vô hạn với đầy tham chiếu sang các trang sinh nội dung khác
      Nó có thể hữu ích cho đến khi wget đơn giản và bot thích nghi được
      Nói thêm thì tôi đứng về phía bot, nhưng giúp cũng không sao
    • Có lẽ nên bán ngẫu nhiên hóa kích thước file
      Có vẻ một số bot có hard limit về kích thước tài nguyên sẽ tải xuống
      Phần lớn trong số đó là các bot huấn luyện/scraping LLM gây phiền, nên dù phát ra zip bomb 800KB không giết được chúng thì vẫn có thể lãng phí tài nguyên tính toán của phía bên kia
    • Nếu nó quay lại thì nghĩa là nó phát hiện và né; nếu không quay lại thì nghĩa là nó đã crash, nhiệm vụ hoàn thành
  • Cũng đáng chỉ ra rằng đây không phải file zip cổ điển mà là gzip bomb
    Nó không phải kiểu dùng zip lồng nhau để hạ gục phần mềm diệt virus, mà hoạt động giống một trang web nén thông thường

  • Một thời gian trước, một phần hạ tầng vượt kiểm duyệt của Tor Project từng được vận hành trên cùng site với bài blog liên quan đến zip bomb[0]
    Một trong các file zip đó bị Google crawl và bị đưa vào danh sách domain độc hại, khiến một phần khá quan trọng trong công cụ Snowflake của Tor bị hỏng
    Mất vài tuần mới xử lý xong[1]
    [0] https://www.bamsoftware.com/hacks/zipbomb/
    [1] https://www.bamsoftware.com/hacks/zipbomb/#safebrowsing

  • Để bảo vệ phần upload của ứng dụng, tôi tạo các phân vùng đĩa tạm thời kích thước cố định khoảng 10MB mỗi cái rồi giải nén vào đó
    Nếu ai đó upload thứ quá lớn thì thiệt hại sẽ bị nhốt trong phạm vi đó

    • unzip -p | head -c 10MB
    • Chỉ cần đừng giải nén những file to một cách vô lý là được, sao lại phải chia đĩa thành phân vùng?