FutureQuest, Inc. FutureQuest, Inc. FutureQuest, Inc.

FutureQuest, Inc.
Go Back   FutureQuest Community > FutureQuest Site Owners (All may read - Only Site Owners May Respond) > Server FAQ
User Name
Password  Lost PW

Reply
 
Thread Tools Search this Thread Display Modes
Old 02-25-1999, 01:50 PM   Postid: 38010
Stephen
Registered User

Forum Notability:
89 pts: Helpful Contributor
[Post Feedback]
 
Join Date: Feb 1999
Location: L.A.
Posts: 671
Passing arguments to system commands

Although this is not a major problem I would be interested in knowing why I seem to be forced to go through a shell when supplying arguments to my system commands. For example, I can do this:

system ("$command @args");

where $command is some command like "perl some_program" and @args are the arguments the program takes.

On the other hand, the following innvocation, which supplies a list to system() instead of a single string (and is supposed to be safer in general because it avoids shell metacharacters that may be lurking in the @args) doesn't seem to work for me at FQ:

system ($command, @args);

Is there a simple explanation for this? I have to confess I really don't have a clue about what a shell really is--I'm just trying to be as safe as I can in the execution of my CGI scripts, so I tend to follow Lincoln Stein's advice
Stephen is offline   Reply With Quote
Old 02-25-1999, 05:54 PM   Postid: 38011
meikel
 
Posts: n/a
Hmm... maybe this question is better placed in "Advanced Development" Forum

Anyway. I never understood this section of documentation, but Terra sent me a sample

Quote:
unless (system("zip -j many other parameters") == 0) {
die "a sensless death: $?\n";
}
It seems to be just a string that's executed as if typed at the telnet prompt.

Greetings from someone being in good mood today
  Meikel Weber
www.meikel.com

  Reply With Quote
Old 02-26-1999, 12:14 AM   Postid: 38012
ChrisH
Registered User

Forum Notability:
10 pts: User-friendly
[Post Feedback]
 
Join Date: Jan 1999
Location: Long Island, New York
Posts: 75
Hi Stephen,

It works for me. Here is a simple
perl script. The first time it calls
the command "ls *" all as one string,
the next time as a list of strings:
==========================

#!/usr/local/bin/perl -w

print "As one stringn";
system ("ls *");

print "As a listn";
system ("ls", "*");

=============================

When I run this, I get the following
output (edited):

==============================

As one string:

bar.pl cadence linker.java
baz.pl dat foo.pl refLink.java

As a list:

ls: *: No such file or directory

=================================

So you see, when you do the command as
one string, you get a listing, as if you
had typed it at the command line. If you
do it as a list, the command doesn't go
throught the shell so the * is not expanded
by the shell, and the ls command actually
sees the star. There is no file called "*".

Lincoln Stein is correct. Imagine that
you actually do the system call as

system ("ls $foo")

where $foo comes from the user. Then, if
the $foo is "; rm -rf *" you could be in
bigggggg trouble since you execute

system ("ls ; rm *");

DO NOT DO EXECUTE THAT! IT'S VERY BAD!
If you use a list, you will be executing
for example

system ("ls", ";", "rm", "*");

and everything is an argument to the ls
executable. No shell involved. Should be
a bit faster, too.


Chris
ChrisH is offline   Reply With Quote
Old 02-26-1999, 11:17 PM   Postid: 38013
jenili
Site Owner

Forum Notability:
10 pts: User-friendly
[Post Feedback]
 
Join Date: Feb 1999
Location: Tempe, AZ, USA
Posts: 132
Chris' explanation is about the best I've ever read! When you pass the command and argument as one big string, it's an argument to the shell. When you break it up, you pass the arguments to the command program instead of to the shell, so you're safer that way.

One caution... some programs you would pass arguments to might in turn pass *their* arguments to another program via shell -- and they might do it the unsafe way. So passing user input as system command arguments doesn't exempt you from qualifying the input first.

jeni
jenili is offline   Reply With Quote
Old 02-26-1999, 11:53 PM   Postid: 38014
ChrisH
Registered User

Forum Notability:
10 pts: User-friendly
[Post Feedback]
 
Join Date: Jan 1999
Location: Long Island, New York
Posts: 75

Yes, that is what I do too -- check
all the input anyway. The real suggestion
is to do

use taint;

I think, but I have never really done
that. I think it forces you to massage
the input in some way, probably via
regular expressions, so that it has
been validated to some extent.


ch
ChrisH is offline   Reply With Quote
Old 02-27-1999, 02:52 AM   Postid: 38015
Del
Registered User

Forum Notability:
0 pts:
[Post Feedback]
 
Join Date: Nov 1998
Location: San Bernardino, CA, USA
Posts: 367
Indeed, you use regular expressions to untaint data. I don't remember it exactly, probably cause I haven't used it yet, but it's similar to below;

use Taint;
# parse form data
$bob =~ /($formdata{'bob'})/;
$bob = $1;

__END__

or something like that.

Del

Del is offline   Reply With Quote
Old 02-28-1999, 01:50 PM   Postid: 38016
jenili
Site Owner

Forum Notability:
10 pts: User-friendly
[Post Feedback]
 
Join Date: Feb 1999
Location: Tempe, AZ, USA
Posts: 132
(I'm using quote and /quote here because code and /code don't seem to be working.)

Quote:
use taint
or
Quote:
#!/usr/local/bin/perl -T
or
Quote:
#!/usr/local/bin/taintperl
depending on your version of perl.

There's more to qualifying input than Del's example, though.
Quote:
if ($bob =~ /$formdata{'bob'}/) {$bob = $1;}
untaints the variable, but doesn't qualify the input. You might as well not even bother with taintperl if this is what you're going to do, because you're not making your script any more secure.

The idea behind taintperl is to make sure that the user input is of a form you expect; e.g., an email address passed to the finger command really looks like an email address and not like something evil. F'rinstance, you might ensure that an email address contains only letters, numbers, underscores, hyphens, dots, and @ signs with this kind of statement:
Quote:
if ($email =~ /^([.-\@\w]+)$/ {
$email = $1;
}
else {die "Can't touch dis.";}
Another way to untaint a variable would be to substitute out everything that doesn't look like what you expected. I'm not being too careful about my syntax here.
Quote:
$wordcharsonly =~ s/\W//g;
The other major thing taintperl does is to prevent you from using unsecure path references. The simplest way to deal with this is to always specify the complete path to a file or a system command (e.g., "/usr/lib/sendmail" instead of "sendmail"). Alternatively, you can set $ENV{'PATH'} before invoking any system commands (and later versions of perl might even require this).

Oodles more information about this and other perl topics is available online at
www.perl.org/perl.html

HTH.
jeni


[This message has been edited by jenili (edited 02-28-99).]

[This message has been edited by jenili (edited 02-28-99).]
jenili is offline   Reply With Quote
Old 03-02-1999, 06:43 PM   Postid: 38017
Stephen
Registered User

Forum Notability:
89 pts: Helpful Contributor
[Post Feedback]
 
Join Date: Feb 1999
Location: L.A.
Posts: 671
Winding the thread back here.

Initially I posted about my inability to run a system command by providing it with a list of arguments. What I discovered today (I'm still supplying a single string, by the way) is that if any of the arguments happen to be a string with braces () somewhere in it the system command fails. That doesn't happen on my home server so it took me a while to cotton on.

I don't know what this means, but I thought I'd point it out since it can drive you nuts wondering what you're doing wrong.
Stephen is offline   Reply With Quote
Old 03-02-1999, 10:32 PM   Postid: 38018
ChrisH
Registered User

Forum Notability:
10 pts: User-friendly
[Post Feedback]
 
Join Date: Jan 1999
Location: Long Island, New York
Posts: 75

If you are sending a string, think
of it as typing the same thing at the
command prompt to the shell.

If you type

./bar.pl a b d()

at the prompt you get

bash: syntax error near unexpected token `d()'

If you type

./bar.pl a b 'd()'

then the single quotes protect the d()
from the shell interpretation. In a quick
test, the same exact thing happened with
system:

system ("./bar.pl a b d()");

gave the same shell error while

system ("./bar.pl", "a", "b", "d()");

and

system ("./bar.pl a b 'd()'");

both work. The latter is the same as the
command that worked at the shell. The
former is a list so the shell never sees
the parentheses.

Does this help?


ch

ChrisH is offline   Reply With Quote
Old 03-02-1999, 11:12 PM   Postid: 38019
Stephen
Registered User

Forum Notability:
89 pts: Helpful Contributor
[Post Feedback]
 
Join Date: Feb 1999
Location: L.A.
Posts: 671
Hey Chris,

Thanks for trying that argument stuff out at the command line. I haven't got around to telneting into FQ yet and testing things that way. I usually assume that whatever I can get running under my Xitami server should run when I upload it, but obviously that's not the case.

I appreciate the pointers. When it comes to system programming, I'm the pits! However, I'm now starting to see the difference between shells, metacharacters and so on. Thanks!

--Stephen
Stephen is offline   Reply With Quote
Reply


Currently Active Users Viewing This Thread: 1 (0 members and 1 visitors)
 

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump


All times are GMT -4. The time now is 12:24 AM.


Running on vBulletin®
Copyright © 2000 - 2019, Jelsoft Enterprises Ltd.
Hosted & Administrated by FutureQuest, Inc.
Images & content copyright © 1998-2019 FutureQuest, Inc.
FutureQuest, Inc.