[2089] in bugtraq
Re: PERL (was: Re: SECURITY HOLE: FormMail)
daemon@ATHENA.MIT.EDU (Philip Guenther)
Tue Aug 8 11:33:55 1995
Date: Mon, 7 Aug 1995 22:37:44 -0500
Reply-To: Bugtraq List <BUGTRAQ@CRIMELAB.COM>
From: Philip Guenther <guenther@gac.edu>
X-To: Bugtraq List <BUGTRAQ@CRIMELAB.COM>
To: Multiple recipients of list BUGTRAQ <BUGTRAQ@CRIMELAB.COM>
In-Reply-To: Your message of "Mon, 07 Aug 1995 03:43:58 CDT."
<199508070843.DAA11355@slip-1-12.ots.utexas.edu>
vax@ccwf.cc.utexas.edu writes:
>PERL's open(), btw, needs to be SERIOUSLY redone.
>For example, what if you open(FOO,">$filename") and $filename happens to
>be ">bar"? Unexpected, eh? And yet, there appears to be no way to seperate
>the control data (">" in this example) from the data data (">bar").
>Bad programming practice, esp. if you can't restrict the format of the data
>to be orthogonal from the control.
>I think PERL relies too much on magic characters (like it's ancestors) to be
>used casually as script backends.
Check out the perl FAQ question 5.26, "How can I open a file with a
leading ">" or trailing blanks?" The answer is to use the following
function to 'bury' the problem characters:
sub safe_filename {
local($_) = shift;
m#^/# ? "$_\0" : "./$_\0";
}
There, you can now say:
open(FOO, ">" . &safe_filename('>bar')) || die "....";
open() will see a second arg of ">./>bar\0". That also handles trailing
pipes, leading ampersands, and all the other possible evil gibberish.
>sub safe_mv
>{ local($file,$dir) = @_;
> -d $dir || &safe_sys('mkdir','-p',$dir) || die;
> &safe_sys('mv',$file,$dir) || die;
>}
>
>sub safe_sys
>{ local($pid);
>FORK: {
> if ($pid = fork) {
> # parent here
> # child process pid is available in $pid
> waitpid($pid,0);
> } elsif (defined $pid) { # $pid is zero here if defined
> # child here
> # parent process pid is available with getppid
> exec @_;
> die "Could not exec: $!\n";
> } elsif ($! =~ /No more process/) {
> # EAGAIN, supposedly recoverable fork error
> sleep 5;
> redo FORK;
> } else {
> # weird fork error
> die "Can't fork: $!\n";
> }
>}
>}
Umm, I see no differance between your safe_sys and the builitin system()
call except what happens on errors. If you check the system() function
description, it refers you to the exec() description, which says:
exec LIST
The exec() function executes a system command AND
NEVER RETURNS. Use the system() function if you
want it to return.
If there is more than one argument in LIST, or if
LIST is an array with more than one value, calls
execvp(3) with the arguments in LIST. If there is
only one scalar argument, the argument is checked
for shell metacharacters. If there are any, the
entire argument is passed to /bin/sh -c for parsing.
If there are none, the argument is split into words
and passed directly to execvp(), which is more
efficient.
...
In other words, system() and exec() ONLY use the shell if
a) you pass them exactly one argument
b) there are any meta characters in that string
Using doing the fork yourself and calling exec() yourself doesn't get
you anything unless you've already split the args, in which case you
could have called system() to start with. Exec() doesn't contain any
extra magic over system().
Philip Guenther
----------------------------------------------------------------
Philip Guenther UNIX Systems and Network Administrator
Internet: guenther@gac.edu Phonenet: (507) 933-7596
Gustavus Adolphus College St. Peter, MN 56082-1498