- 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 OK và Content-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
Ý 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ậtTCP_NODELAYvà 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
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ụ
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
Đ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ị
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 đó
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.htmltrên homepage của mìnhTrì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
Mãi vài năm sau cuối cùng tôi mới mở được 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ôngCó ý tưởng nào không?
favicon.icotừng làm sập trình duyệtChắc là cái này: https://freedomhacker.net/annoying-favicon-crash-bug-firefox...
/dev/zipbombNgày nay hầu như mọi trình duyệt đều chấp nhận zstd và brotli, 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
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...
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 byteNhưng tôi không muốn tự thử
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
Chưa bao giờ ít hơn 3 cái, lúc nào cũng được đảm bảo
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ổ
/wp-logingửi tớiNó 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
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
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
srcthà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ảhttps://github.com/skeeto/endlessh
Trong hai cái thì trông nó còn dễ hơn
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
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
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 đượcNói thêm thì tôi đứng về phía bot, nhưng giúp cũng không sao
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
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