Common Web Vulnerabilties: POISON NULL BYTE part 3

Our first CGI I snagged off of freecode.com. It’s a classified ad manager
script. From the CGI file:

# First version 1.1
# Dan Bloomquist dan@lakeweb.net

Now the first example…Dan parses all incoming form variables into %DATA.
He doesn’t strip ‘..’, nor NUL characters. So, let’s take a peek at a
snippet of code:

#This sets the real paths to the html and lock files.
#It is done here, after the POST data is read.
#of the classified page.
$pageurl= $realpath . $DATA{ ‘adPath’ } . “.html”;
$lockfile= $realpath . $DATA{ ‘adPath’ } . “.lock”;

Using ‘adPath=/../../../../../etc/passwd′ we can specify $pageurl to
point to the /etc/passwd file. Ditto for the $lockfile. We can’t use the
appended pipe, because he appends the “.html”/”.lock” afterwards (well,
you CAN use it, but it’s not going to work. ;)

#Read in the classified page
open( FILE,”$pageurl” ) || die “can’t open to read
$pageurl: $!\n”;
@lines= ;
close( FILE );

Here Dan reads in $pageurl, which is the file we specified. Fortunately
for Dan, he then immediately opens $pageurl for write. So whatever we
specify to read, we also need rights to write it. This does limit the
exploitation potential. But it serves as a great real-life example of
this type of problem.

Interestingly enough, Dan does go on to:

#Send your mail out.
#
open( MAIL, “|$mailprog $DATA{ ‘adEmail’ }” )
|| die “can’t open sendmail: $adEmail: $!\n”;

Hmmmmm…this is your standard no-no. And Dan doesn’t parse shell
metacharacters, so that ‘adEmail’ gets pretty scary.

Sticking around freecode.com, I then got a simple form logger:

# flexform.cgi
# Written by Leif M. Wright
# leif@conservatives.net

Leif parses form input into %contents, and doesn’t escape shell
metacharacters. Then he does

$output = $basedir . $contents{’file’};
open(RESULTS, “>>$output”);

Using our standard reverse directory transversal, we don’t even have to NUL
out an extension. Whatever file we specify is opened for append, so again, we
need to get a little lucky with our permissions. Again, our pipe bug
won’t work because he specifically set the mode to append (via the ‘>>’).

Next is LWGate, which is a WWW interface to many popular mailing list packages.

# lwgate by David W. Baker, dwb@netspace.org #
# Version 1.16 #

Dave puts parsed form variables into %CGI. Then we have

# The mail program we pipe data to
$temp = $CGI{’email’};
$temp =~ s/([;<>\*\|`&\$!#\(\)\[\]\{\}:’”])/\\$1/g;
$MAILER = “/usr/sbin/sendmail -t -f$temp”

open(MAIL,”| $MAILER”) || &ERROR(’Error Mailing Data’)

Hmmmm…Dave seems to have forgotten the backslash in his regex replacement.
Not good.

Ok, let’s switch to one of the many shopping cart applications. This one,
again, was yanked from freecode.com, Perlshop.

$PerlShop_version = 3.1;
# A product of ARPAnet Corp. -
perlshop@arpanet.com, www.arpanet.com/perlshop

The interesting part is:

open (MAIL, “|$blat_loc - -t $to -s $subject”)
|| &err_trap(”Can’t open $blat_loc!\n”)

$to is obviously the user-defined email. Blat is a NT mail program. Remember
that shell metacharacters on NT are <>&|% (maybe more?).

Remember the pesky pipe problem I mentioned? (I hope you remember it… It
was only a few paragraphs ago!). I admit, it’s a very unlikely bug, but I
did find it. Let’s head over to Matt’s Script Archive.

# File Download Version 1.0
# Copyright 1996 Matthew M. Wright mattw@worldwidemart.com

First he parses incoming user data into $Form (not escaping anything). Then
he runs the following:

$Request_File = $BASE_DIR . $Form{’s’} . ‘/’ . $Form{’f'};

if (!(-e $filename)) {
&error(’File Does Not Exist’);
}
elsif (!(-r $filename)) {
&error(’File Permissions Deny Access’);
}

open(FILE,”$Request_File”);
while () {
print;
}

This fits the criteria for the ‘pesky pipe problem’ ™. We do have the
‘-e’ check, so we don’t get to use command line args. Since he sticks
$BASE_DIR on the front, we’ll need to use reverse directory transversal.

I’m sure you looking at the above (should) see a much more simpler problem.
What if f=../../../../../../etc/passwd? Well, if it exists, and is
readable, it’ll show it to you. And yes, it does. One other note: all
accesses to download.cgi are logged by the following code:

open(LOG,”>>$LOG_FILE”);
print LOG “$Date|$Form{’s’}|$Form{’c'}|$Form{’f'}\n”;
close(LOG);

So you’ll be on candid camera for everything you do. But you shouldn’t be
doing mean stuff to other people’s servers anyways. ;)

Let’s fly over to BigNoseBird.com. Script I have in mind:

bnbform.cgi
#(c)1997 BigNoseBird.Com
# Version 2.2 Dec. 26, 1998

The code of interest is after the script opens a pipe to sendmail as MAIL:

if ($fields{’automessage’} ne “”)
{
open (AM,”< $fields{’automessage’}”); while ()
{
chop $_;
print MAIL “$_\n”;
}

This is another simple one. BNB doesn’t do any parsing of the user input
variables (in $fields), so we can specify any file we want for ‘automessage’.
Assuming it’s readable by the web server context, it will get mailed to
whatever address we put (or so the theory goes).