PHP - - By Christian Haschek

How to Defend Your Website with Zip Bombs

This article was originally published on Christian’s blog and republished here with his permission. Check out the rest of his very interesting writing over there if you’d like to learn about IoT, cryptocurrencies, PHP, and more!


If you have ever hosted a website or even administrated a server, you’ll be very well aware of bad people trying bad things with your stuff.

When I first hosted my own little linux box with SSH access at age 13, I read through the logs daily and reported the IPs (mostly from China and Russia) who tried to connect to my sweet little box (which was actually an old ThinkPad T21 with a broken display running under my bed) to their ISPs.

Actually, if you have a linux server with SSH exposed you can see how many connection attempts are made every day:

grep 'authentication failures' /var/log/auth.log

Hundreds of failed login attempts even though this server has disabled password authentication and runs on a non-standard port

WordPress Has Doomed Us All

OK, to be honest, web vulnerability scanners have existed before WordPress, but since WP is so widely deployed most web vulnerability scanners include scans for some misconfigured wp-admin folders or unpatched plugins.

So if a small, new hacking group wants to gain some hot cred they’ll download one of these scanner things and start testing against many websites in hopes of gaining access to a site and defacing it.

Sample of a log file during a scan using the tool Nikto

This is why all server or website admins have to deal with gigabytes of logs full with scanning attempts. So I was wondering..

Read Better PHP Development

Tools and techniques to make you a better developer

Is there a way to strike back?

After going through some potential implementations with IDS or Fail2ban I remembered the ZIP bombs from the old days.

WTH is a ZIP bomb?

So it turns out ZIP compression is really good with repetitive data so if you have a really huge text file which consists of repetitive data like all zeroes, it will compress it really good. Like REALLY good.

As 42.zip shows us, it can compress a 4.5 peta byte (4.500.000 giga bytes) file down to 42 bytes. When you try to actually look at the content (extract or decompress it) then you’ll most likely run out of disk space or RAM.

How can I ZIP bomb a vuln scanner?

Sadly, web browsers don’t understand ZIP, but they do understand GZIP.

So firstly we’ll have to create the 10 gigabyte GZIP file filled with zeroes. We could make multiple compressions but let’s keep it simple for now.

dd if=/dev/zero bs=1M count=10240 | gzip > 10G.gzip

Creating the bomb and checking its size

As you can see, it’s 10 MB large. We could do better but good enough for now.

Now that we have created this thing, let’s set up a PHP script that will deliver it to a client.

<?php
//prepare the client to recieve GZIP data. This will not be suspicious
//since most web servers use GZIP by default
header('Content-Encoding: gzip');
header('Content-Length: '.filesize('10G.gzip'));
//Turn off output buffering
if (ob_get_level()) ob_end_clean();
//send the gzipped file to the client
readfile('10G.gzip');

That’s it!

We could use this as a simple defense like this:

<?php
$agent = lower($_SERVER['HTTP_USER_AGENT']);

//check for nikto, sql map or "bad" subfolders which only exist on wordpress
if (strpos($agent, 'nikto') !== false || strpos($agent, 'sqlmap') !== false || startswith($url,'wp-') || startswith($url,'wordpress') || startswith($url,'wp/'))
{
      sendBomb();
      exit();
}

function sendBomb(){
        //prepare the client to recieve GZIP data. This will not be suspicious
        //since most web servers use GZIP by default
        header("Content-Encoding: gzip");
        header("Content-Length: ".filesize('10G.gzip'));
        //Turn off output buffering
        if (ob_get_level()) ob_end_clean();
        //send the gzipped file to the client
        readfile('10G.gzip');
}

function startsWith($haystack,$needle){
    return (substr($haystack,0,strlen($needle)) === $needle);
}

This script obviously is not – as we say in Austria – the yellow of the egg, but it can defend from script kiddies I mentioned earlier who have no idea that all these tools have parameters to change the user agent.

What happens when the script is called?

Client Result
IE 11 Memory rises, IE crashes
Chrome Memory rises, error shown
Edge Memory rises, then dripps and loads forever
Nikto Seems to scan fine but no output is reported
SQLmap High memory usage until crash

(if you have tested it with other devices/browsers/scripts, please let me know and I’ll add it here)

Reaction of the script called in Chrome

If you’re a risk taker: try it yourself