19.6. Executing Commands Without Shell EscapesProblem
You need to use a user's input as part of a command, but you don't want to allow the user to make the shell run other commands or look at other files. If you just blindly call the Solution
Unlike its single-argument version, the list form of the
system("command $input @files"); # UNSAFE
Write it this way instead:
system("command", $input, @files); # safer
DiscussionBecause Perl was designed as a glue language, it's easy to use it to call other programs - too easy, in some cases.
If you're merely trying to run a shell command but don't need to capture its output, it's easy enough to call It's safe to use backticks in a CGI script only if the arguments you give the program are purely internally generated, as in: chomp($now = `date`); But if the command within the backticks contains user-supplied input, perhaps like this: @output = `grep $input @files`; you have to be much more careful.
die "cannot fork: $!" unless defined ($pid = open(SAFE_KID, "|-"));
if ($pid == 0) {
exec('grep', $input, @files) or die "can't exec grep: $!";
} else {
@output = <SAFE_KID>;
close SAFE_KID; # $? contains status
}
This works because
Similar circumlocutions are needed when using open(KID_TO_READ, "$program @options @args |"); # UNSAFE Use this more complicated but safer code:
# add error processing as above
die "cannot fork: $!" unless defined($pid = open(KID_TO_READ, "-|"));
if ($pid) { # parent
while (<KID_TO_READ>) {
# do something interesting
}
close(KID_TO_READ) or warn "kid exited $?";
} else { # child
# reconfigure, then
exec($program, @options, @args) or die "can't exec program: $!";
}
Here's a safe piped open for writing. Instead of using this unsafe code: open(KID_TO_WRITE, "|$program $options @args"); # UNSAFE Use this more complicated but safer code:
$pid = open(KID_TO_WRITE, "|-");
die "cannot fork: $!" unless defined($pid = open(KID_TO_WRITE, "|-"));
$SIG{ALRM} = sub { die "whoops, $program pipe broke" };
if ($pid) { # parent
for (@data) { print KID_TO_WRITE $_ }
close(KID_TO_WRITE) or warn "kid exited $?";
} else { # child
# reconfigure, then
exec($program, @options, @args) or die "can't exec program: $!";
}
At the point where the comment in the code says
All this doesn't help you, of course, if your See Also
The ![]() Copyright © 2002 O'Reilly & Associates. All rights reserved. |
|