in reply to Re: Re: Using doublequotes in a system call
in thread Using doublequotes in a system call

sure, i can give you an example. but the best examples are in perlsec. you're running AS ROOT, and not checking your variables for taintedness. if i can get you to your web page, i can do VERY EVIL THINGS to your system. of course, i'd never do that ;-)

use -T as well as strict and warnings. don't use the PATH environment, unless you've cleaned it. when you execute a system call, use the full path to the executable, and pass an array, so the shell is bypassed. these and many other good practices can be learned by reading the perlsec documentation. i highly recommend reading Ovid's "Web Programming Using Perl" Course as well. it's helped me tremendously.

here's some code...

#!/usr/bin/perl -wT use strict; use CGI; # clean your environment BEGIN { $ENV{PATH} = '/usr/bin:/usr/local/bin'; } my $useradd = '/full/path/to/useradd'; my( $site_count, $username ); # and so on... # get input, which will be tainted... # my $username = $CGI->param('username'); # untaint input # for instance, username is 1 to 12 word characters if( $username =~ /^(\w{1,12})$/ ) { $username = $1 } # and so on... # now call system, with list of arguments to bypass shell system( $useradd, qq|-c "fullname"|, qq|-d /home/sites/site$site_count/users/$username|, qq|-g site$site_count|, qq|and so on...|, ) and error( "oh, i didn't expect that! $!" );

~Particle *accelerates*

Replies are listed 'Best First'.
Re: Re: Re: Re: Using doublequotes in a system call
by kjherron (Pilgrim) on May 19, 2002 at 05:39 UTC
    This is the right idea, but your system() call isn't quite correct. When you run something like:
    system("$useradd -c \"$fullname\" ...");
    then system() runs the command by way of the a shell. The shell splits the command string up into words--removing the quotes in the process--and ends up passing the '-c' and the $fullname to useradd as two separate arguments.

    However, when you call:

    system( $useradd, qq|-c "fullname"|, ...
    then the shell doesn't get involved, and useradd receives the exact argument list you passed to system(). In this case you've constructed a single string
    -c "value-of-$fullname"
    which useradd will percieve as a single argument, quotes and all. This probably isn't what useradd is expecting.

    If you're going to use the list form of system, you really have to pass each argument as a separate list element, eg:

    system ($useradd, '-c', $fullname, '-d', "/home/sites/site$site_count/users/$username", '-g', "site$site_count", '-G', "site-adm$site_count", '-p', $password, '-s', '/bin/false', '-u', $uid, $username);
    This way, the shell isn't involved, because you're using the list form of system(). But useradd receives each command-line argument as a separate element (with no extraneous quotes) just like it expects.

    If you have trouble understanding the difference, then try running each of the following:

    system('cat -n /etc/group'); system('cat', '-n /etc/group'); system('cat', '-n', '/etc/group');
    Use the q{} or qq{} quote form if you like; it shouldn't matter. The first and third lines should work; the second should give you an error of some sort.
      you are, of course, correct. my 'in-head-interpreter' still doesn't parse perfectly, so my on-the-fly example was flawed.

      your clear and detailed response will now be the place i point anyone who wants to understand using system.

      ~Particle *accelerates*