system command won't run with -T option on

R

rallabs

Hello: I have a series of cgi scripts which I use to set up an input
file for a compiled C program. I use cookies extensively to keep track
of what parameters the users have chosen or typed into the forms they
see as they negotiate the site. I have been worrying a lot about
security and although I check all user input textboxes when they are
parsed, all the books I read say that using the taint mode is supposed
to be a very good idea. All the scripts I have written have been
successfully 'untainted' except for one that contains a system
command. I used the same procedure to untaint this script as I did
for all my others: I ran it through a search pattern and checked that
it's the proper format. The scripts all work fine when I do this
except the one with the system command. I pasted the script below. It
runs successfully if the -T is removed, but when -T is present I get
the famous 'Internal Server Error'. The error log says: "Insecure
$ENV{PATH} while running with -T switch"
The perl script is:

#!/usr/bin/perl -wT
use strict;
use CGI::Carp qw(fatalsToBrowser);
use CGI qw:)standard -no_xhtml);
use diagnostics;
my %cookhash=cookie('bigcook');#retrieve cookie 'bigcook'; put into
hash 'cookhash'
my $newID=$cookhash{'newID'};
if ($newID =~ /([\w][\w][\w][\w][\d][\d][\d][\d])/){ #untainting
$newID
my $good=$1;
$newID=$good;
}else { die("Bad data: $newID");
}
system "~/runsgood.exe<hold.$newID >/dev/null"; #execute the compiled
program 'runsgood.exe'
print STDOUT redirect('done.cgi');

I don't understand what to do about the problem if I've untainted the
one piece of external data used.
perlsec says I've got to supply a good path for the script to use, but
I don't know how to do it. I can't figure out how to print out the
environment variable $ENV{PATH} anywhere.

I've been pulling out my hair all day long with this problem, and I'm
about to just give up and turn off the $%*! taint switch.
Mike
 
P

Paul Lalli

All the scripts I have written have been
successfully 'untainted' except for one that contains a system
command. I used the same procedure to untaint this script as I did
for all my others: I ran it through a search pattern and checked that
it's the proper format. The scripts all work fine when I do this
except the one with the system command. I pasted the script below. It
runs successfully if the -T is removed, but when -T is present I get
the famous 'Internal Server Error'. The error log says: "Insecure
$ENV{PATH} while running with -T switch"

Right. The error has nothing to do with the command itself. It has to
do with what other commands that command might run.
perlsec says I've got to supply a good path for the script to use, but
I don't know how to do it. I can't figure out how to print out the
environment variable $ENV{PATH} anywhere.

You do not need to print $ENV{PATH} anywhere, but if you wanted to, you
would print it the same way you print anything else. Regardless, you
need to *set* $ENV{PATH}. You need to set the path to be a sequence of
directories from which you want to allow commands to be run. So if
your executable that you're calling via system calls the program
"mycmd.exe", which directories should be searched for mycmd.exe?

Paul Lalli
 
M

Mumia W. (on aioe)

[...]
I don't understand what to do about the problem if I've untainted the
one piece of external data used.

By default, $ENV{PATH} is tainted, so any command that uses the PATH,
such as system(), is insecure.
perlsec says I've got to supply a good path for the script to use, but
I don't know how to do it. I can't figure out how to print out the
environment variable $ENV{PATH} anywhere.
[...]

print "PATH = $ENV{PATH}\n";
$ENV{PATH} = '/bin:/usr/bin:/usr/local/bin';
system('whatever');
 
R

rallabs

Paul said:
Right. The error has nothing to do with the command itself. It has to
do with what other commands that command might run.


You do not need to print $ENV{PATH} anywhere, but if you wanted to, you
would print it the same way you print anything else. Regardless, you
need to *set* $ENV{PATH}. You need to set the path to be a sequence of
directories from which you want to allow commands to be run. So if
your executable that you're calling via system calls the program
"mycmd.exe", which directories should be searched for mycmd.exe?

Paul Lalli

Paul:
Thanks for the advice. I printed out $ENV{PATH} and it said
'/usr/local/bin:/usr/bin:/bin'
which doesn't have anything in it about any of my variables, but i then
tried:

$ENV{PATH}='/usr/local/bin:/usr/bin:/bin';

in the script and it seems to have done the job, because it runs now.
After 4 hrs. messing around with it I still don't understand why it
happened but I guess it's another of the very many Perl mysteries I'll
never get but I'll remember it always for when it happens again. I
also wish I would have posted a lot earlier but my ego's weak and I
hate the criticism. Thanks again.
Mike
 
R

rallabs

Mumia said:
[...]
I don't understand what to do about the problem if I've untainted the
one piece of external data used.

By default, $ENV{PATH} is tainted, so any command that uses the PATH,
such as system(), is insecure.
perlsec says I've got to supply a good path for the script to use, but
I don't know how to do it. I can't figure out how to print out the
environment variable $ENV{PATH} anywhere.
[...]

print "PATH = $ENV{PATH}\n";
$ENV{PATH} = '/bin:/usr/bin:/usr/local/bin';
system('whatever');


Mumia W.:
Thanks very much for the answer and the advice. It's now running under
taint mode.
Mike
 
P

Paul Lalli

Thanks for the advice. I printed out $ENV{PATH} and it said
'/usr/local/bin:/usr/bin:/bin'
which doesn't have anything in it about any of my variables,

Correct. The "taintedness" of the PATH has nothing to do with
variables. It has to do with the fact that the PATH, by default, comes
from the environment - that is, it comes from outside your script. It
is tainted because it is theoretically possible for someone in the
environment to set a "bad" PATH before launching your script. And if
they do that, you're screwed. If your program calls 'mycmd.exe', and
the malicious user has set PATH to be "/my/really/nasty/viruses/" and
puts a very bad program named mycmd.exe in that PATH, you're in
trouble. By defining the PATH within the script itself, you eliminate
that possibility.

but i then tried:

$ENV{PATH}='/usr/local/bin:/usr/bin:/bin';

in the script and it seems to have done the job, because it runs now.
After 4 hrs. messing around with it I still don't understand why it
happened but I guess it's another of the very many Perl mysteries I'll
never get

It's really not mysterious. The -T flag simply insures that nothing
created or assigned outside of your program can influence your
program's execution. The PATH is defined by the environment, unless
you specifically define it within your script.

Please let us know if you still don't understand.

Paul Lalli
 
X

xhoster

Paul Lalli said:
Correct. The "taintedness" of the PATH has nothing to do with
variables. It has to do with the fact that the PATH, by default, comes
from the environment - that is, it comes from outside your script. It
is tainted because it is theoretically possible for someone in the
environment to set a "bad" PATH before launching your script. And if
they do that, you're screwed.

Well, most likely *they* are screwed, not you.
If your program calls 'mycmd.exe', and
the malicious user has set PATH to be "/my/really/nasty/viruses/" and
puts a very bad program named mycmd.exe in that PATH, you're in
trouble. By defining the PATH within the script itself, you eliminate
that possibility.

What are the ways for another party to change *my* PATH environment,
without already having the system completely under their control anyway?
I'm not really worried about someone else tricking Perl code (that I wrote,
but which they, not I, am running) into running some nasty code within
their own account, when they could have run the code in their own account
directly anyway.

The only one I can think of is setuid. In perhaps the most common
situation in which -T is used, CGI, I think mistrusting PATH might be
excessive, as anyone who can hack apache to change the PATH under which
your script executes probably is already in the driver seat. Am I wrong on
that? Is there a way to run "taint-light" in which only things coming from
the http client is tainted, instead of everything coming from outside the
script being tainted?

It's really not mysterious. The -T flag simply insures that nothing
created or assigned outside of your program can influence your
program's execution. The PATH is defined by the environment, unless
you specifically define it within your script.

Please let us know if you still don't understand.

Indeed, when I first ran into the problem I found it irritating, but
hardly mysterious. I thought the error was self-explanatory.

Xho
 
P

Peter J. Holzer

Well, most likely *they* are screwed, not you.

The -T switch is for situations where the person (or entity) controlling
the environment is not the same as the person (or entity) with whose
privileges the script is executing. So if the script is executing with
"your" privileges and "they" control the environment, "you" are screwed.

What are the ways for another party to change *my* PATH environment,
without already having the system completely under their control anyway?
I'm not really worried about someone else tricking Perl code (that I wrote,
but which they, not I, am running) into running some nasty code within
their own account, when they could have run the code in their own account
directly anyway.

The only one I can think of is setuid.

Right. That's the situation where the (potential) attacker has complete
control of the environment, and therefore also the PATH. In other
situations (CGI, sudo, etc.) the attacker may control only part of the
environment, which may or may not include PATH.
In perhaps the most common situation in which -T is used, CGI, I think
mistrusting PATH might be excessive, as anyone who can hack apache to
change the PATH under which your script executes probably is already
in the driver seat.

Probably, yes. However, perl doesn't know it is being run from Apache,
and it knew that, it would probably not be trivial to determine which
environment variables are always safe and which are potentially unsafe.
So while you as a sysadmin may determine that, yes, when this particular
script is run from this particular instance of apache, this environment
variable has a known value which cannot be influenced by an attacker,
perl in general cannot do that and has to treat the whole environment as
suspect.

hp
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,995
Messages
2,570,230
Members
46,819
Latest member
masterdaster

Latest Threads

Top