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

Hi dear fellow monks,

I know this may be a trivial question, but I'm having some problems of understanding the tainted mode of Perl and how to call external programs/scripts when using it. I'm having a CGI-script collecting the data from the browser and passing it via files/commandline to an external Perl-script, which does some calculations on that stuff.
The external script is called via commandline the following way:

script.pl -v -in <file> -opt1 -opt2 -opt3 <num> -optx

Right now, I'm rendering a string containing all the options (enabled/disabled by the Web-User) called '$shellstring' and call the script the following way:

my $log = `script.pl $shellstring`;

This does not work in tainted mode. I tried several variations of calling the script (using system() etc.) but I'm not able to get this working. The CGI-script tests all data for being valid and not containing illegal characters.

Thanx in advance, Michael

Replies are listed 'Best First'.
Re: How to call external scripts from a CGI-script in taint mode?
by Coruscate (Sexton) on Apr 03, 2003 at 11:30 UTC

    Have you cleanes your %ENV? Most noteable, $ENV{'PATH'} needs to be set to a value within the script. This should be set to a very limited set of directories that you (hopefully) know to be secure. Also, when calling outside programs, use the absolute path. For example, you should not execute "ping", you should execute "/bin/ping".

    People can do nasty things with the environment and will do what they can to harm you :) I'm assuming that perl is giving you the error about not running the script because your $ENV{PATH} is untrusted. So a tainted script should start something like this:

    #!/usr/bin/perl -Tw use strict; $|++; $ENV{PATH} = '/bin;/usr/bin;/home/professa'; `/bin/ping 127.0.0.1`;


    If the above content is missing any vital points or you feel that any of the information is misleading, incorrect or irrelevant, please feel free to downvote the post. At the same time, please reply to this node or /msg me to inform me as to what is wrong with the post, so that I may update the node to the best of my ability.

      I was adding something to $ENV{'PATH'}, but setting it explicitely to my "trusted" directories does not help:

      Insecure dependency in `` while running with -T switch at /v/webserver/consensus/cgi-bin/interface.pl line 171.

      Line 171 says:

      $log = `/v/webserver/consensus/cgi-bin/conss_aln.pl $shellstring`;

      But when using tainted mode, I get the error message above. Its reason is the '$shellstring', removing it from the line helps. But I can't start my external script anymore without the parameters stored in '$shellstring' ;-)

        Ah k, in this case, the content of $shellstring is tainted. This means that $shellstring obtains its value from a source outside of your script. If you are ____absolutely___ sure that this string contains what you think it does, you can do ($shellstring) = $shellstring =~ m#^(.*)$#; before sending it through the backticks. This will untaint the value. Please note that under the rarest conditions should data simply be untainted as such. This just defeats the purpose of taint, and it's rare that such a method should be used. If you cannot trust that $shellstring contains undamaging data, then you need to come up with a regex to ensure that the string is safe.

        I am telling myself that the string cannot be trusted since it appears to be coming from an outside source. Mind posting the code where $shellstring is generated?


        If the above content is missing any vital points or you feel that any of the information is misleading, incorrect or irrelevant, please feel free to downvote the post. At the same time, please reply to this node or /msg me to inform me as to what is wrong with the post, so that I may update the node to the best of my ability.

        I assume that the contents of $shellsring come from outside the program. Have you untainted it?

        --
        <http://www.dave.org.uk>

        "The first rule of Perl club is you do not talk about Perl club."
        -- Chip Salzenberg

Re: How to call external scripts from a CGI-script in taint mode?
by davorg (Chancellor) on Apr 03, 2003 at 11:52 UTC
    Coruscate has already given you the correct fix for your problem, but ir's worth pointing out the Perl tried to tell you what the problem was. If you'd have looked in the web server error log you would have seen

    Insecure $ENV{PATH} while running with -T switch

    --
    <http://www.dave.org.uk>

    "The first rule of Perl club is you do not talk about Perl club."
    -- Chip Salzenberg

Re: How to call external scripts from a CGI-script in taint mode?
by hacker (Priest) on Apr 03, 2003 at 11:15 UTC
    You could change your methodologies a bit, and enable PerlTaintCheck On in your httpd.conf (assuming an Apache server here), and then set the handler for files of type .plt to be tainted perl scripts (untainted?) and files of type .pl to be normal perl scripts.

    Or, you could do it like I do, and enforce all perl scripts to run in taint mode, with PerlTaintCheck On on globally in httpd.conf.

Re: How to call external scripts from a CGI-script in taint mode?
by Mr_Person (Hermit) on Apr 03, 2003 at 19:59 UTC

    I don't know if this would work for the environment you're in (and who developed script.pl and what it does), but have you thought about putting the functionality of the script into a Perl module and just useing that module in your CGI script? In addition to not having to worry about the taint problems you're having, it should also be a little faster as you don't have to start up another Perl interpreter every time (and if you use mod_perl, the module wouldn't even have to be loaded every time).

    I guess it just sounds kinda weird to me to call a Perl program from within a Perl program. :-)

      You're right, normally I wouldn't call a Perl program from within a Perl program. ;-)
      The background is that I have developed a tool which is normally run via commandline and this tool shall now be made available via web to users, so the easiest way to integrate the existing tool into a www-environment was to write a CGI-script fetching all the data and passing it to the tool. :-)

      Micha