Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery
 
PerlMonks  

Untainting system calls correctly

by c (Hermit)
on Apr 10, 2002 at 16:12 UTC ( [id://158057]=perlquestion: print w/replies, xml ) Need Help??

c has asked for the wisdom of the Perl Monks concerning the following question:

I'm reading through perldoc perlsec in the hopes of getting a system() call to work with taint checking enabled. In particular, I have been staring at:

system "echo $arg"; # Insecure system "/bin/echo", $arg; # Secure (doesn't use sh) system "echo $hid"; # Insecure system "echo $data"; # Insecure until PATH set $path = $ENV{'PATH'}; # $path now tainted $ENV{'PATH'} = '/bin:/usr/bin'; delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'}; $path = $ENV{'PATH'}; # $path now NOT tainted system "echo $data"; # Is secure now!

my system call is:

system "/usr/sbin/useradd $cli";

I have the following in my script which I had hoped would allow for this command to be used:

## taint environmentals $ENV{'PATH'} = "/bin:/usr/sbin"; delete @ENV{qw(IFS CDPATH ENV BASH_ENV)}; ## clean up user's name $formdata{username} =~ s/ //g; $formdata{username} =~ s/[^A-Za-z0-9]//g; $formdata{username} =~ /^([A-Za-z0-9]{1,8}).*$/; $formdata{username} = $1; my $cli = "-s $shell -d $home -G $group $formdata{username}"; $cli =~ /^(\-s \"\/bin\/false\" \-d \"\/home\/clients\/(?:stage\.)?( +?:[\w\-]+\.)(?:\w{2,3}\.)?(?:\w{2,4})\/[A-Za-z0-9]+\" \-G \"hosting\, +[\w\-]+\" [A-Za-z0-9]+)$/; $cli = $1; print "CLI is $cli"; system("/usr/sbin/useradd $cli");

I stuck in that  print "CLI is $cli" to see just what I was getting out of it. Sure enough, it is as i expected it to be.
In my situation, that turns out to be:

-s "/bin/false" -d "/home/clients/stage.domain.com/testcjm" -G "hostin +g,domain" testcjm

In the course of my testing, I've also untainted the $shell $home $group and $formdata{username} variables.

When I dont use $cli and instead just pass the $formdata{username} variable to the system call, it works. It seems like the problem is only when I pass all the command line flags as part of $cli.

this has become my white whale for the day's chasing.

thanks -c

Replies are listed 'Best First'.
Re: untainting system calls correctly
by dws (Chancellor) on Apr 10, 2002 at 16:37 UTC
    I'm curious. First, you identify that the single argument form of system() is a potential problem, but then you proceed on to use it. If you're going to use   system("/usr/sbin/useradd $cli"); then you need to prevent $cli from having as it's trailing substring something day-ruining like   "... ; /bin/rm -rf *" You don't have this problem with the multiple argument form, since you're bypassing the shell entirely. Here's a simple reworking:
    my $username = ... untaint $formdata{'username'}; ... etc. for other form variables my @cli = ("-s", $shell, "-d", $home, "-G", $group $usrname); ... system("/usr/sbin/useradd", @cli);

    Edit: s/training/trailing/

      Not to meniton preventing someone from slipping in a username of `-u 0 I0wNj00'.

      Update: As a clarification, I mean that by using the multiple arugment form rather than letting the shell split you prevent the user from submitting extra arguments (in the example I gave they could specify that their new account would get a uid of 0).

      Sorry if I am just missing the nomenclature you're using, but what do you mean by "training substring"?

      thanks! -c

Re: tainting system calls correctly
by Zaxo (Archbishop) on Apr 10, 2002 at 16:39 UTC

    As a security measure, I think taint is a little beside the point if you are handing out shell accounts via a web form.

    Please say you have some layers of approval, authorization and authentication above this! :)

    After Compline,
    Zaxo

      Not really shell accounts. If you notice the shell is set to /bin/false. Plus the script is only available to clients that have signed off on a lengthy contract agreement. To boot, its available through a strictly ssl connection that requires user/pass authorization.

      There are additional checks within the script to restrict touching UID less than 500, passing a group to a GID that is greater than 500.

      I know that there are plenty of issues that still need to be addressed, but I was just curious to see exactly *why* i am seeing it fail in my current situation.

      thanks -c

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://158057]
Approved by dws
Front-paged by Maclir
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others meditating upon the Monastery: (7)
As of 2024-04-19 15:54 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found