Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?
 
PerlMonks  

How to safely define a CGI program's application base directory

by ddmiller (Initiate)
on Feb 10, 2013 at 20:28 UTC ( #1018072=perlquestion: print w/ replies, xml ) Need Help??
ddmiller has asked for the wisdom of the Perl Monks concerning the following question:

Hello, I am writing an application that will be hosted on several Apache webservers, which may have different directory structures. The application will reference a number of directories and files ("config", "log", "data", etc.) under an application base directory. Since each server's directory structure might be different, though, the pathnames to the base directory will vary from server to server. I thought I would define an environment variable in the Apache configuration that would tell the CGI where to find its base directory, like this:

#!\strawberry\perl\bin\perl.exe use strict; use File::Spec::Functions; my $logfile = catdir($ENV{AppBase}, "mylogfile"); print "opening $logfile ...\n"; open (LOGFILE, ">>$logfile") || die "couldn't open log file \n"; print LOGFILE "test log file line"; close(LOGFILE);

That works fine, until I turn on taint mode. When I turn on taint mode, I get this:

Insecure dependency in open while running with -T switch at MyCgiProg. +pl line 8.

I understand why taint mode doesn't like my code: a malicious (or careless) Apache admin might point that ENV variable to the wrong directory and cause something important to be overwritten.

I'm sure other more seasoned programmers have handled this problem before, and I'd love to hear how you handled it. Thanks in advance for your assistance.

Regards, Darren

Comment on How to safely define a CGI program's application base directory
Select or Download Code
Re: How to safely define a CGI program's application base directory
by choroba (Abbot) on Feb 10, 2013 at 21:17 UTC
    Just use the standard laundering technique (see perlsec):
    my $app_base = $ENV{AppBase}; if ($app_base =~ m{^(/var/www/[^/]+)$}) { $app_base = $1; # $app_base no longer tainted. } my $logfile = catdir($app_base, 'mylogfile');
    لսႽ ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ

      Thank you for taking time to reply. That might work in some environments, but it assumes that all of the servers use the same path prefix (/var/www). I don't believe that's true in our case. I suppose I could include a note in the installation instructions that the application name must be the final directory element in the AppBAse environment variable. Then I could use a regular expression something like this:

      m{^(/.+/MyApp/)$}

      That should be sufficient to satisfy the untainting requirement, but I'm not sure whether it really makes the value "safe". Thanks again for responding so quickly.

        What threat are you trying to avoid? It is upon you to tell what is safe. If you know there are three possible values, you can try something like
        m{^(/path1|/path2|/path3)/MyApp$}
        Someone can still tweak the config to point to a wrong path (valid for a different server). You can even include other conditions into the if, not only the single match.
        لսႽ ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ
Re: How to safely define a CGI program's application base directory
by Khen1950fx (Canon) on Feb 10, 2013 at 23:58 UTC

    I couldn't replicate the error. How are you turning on taint mode? Taint mode must be called with -T on the cmdline and on the shebang line.

      It should be easy. In Linux, I just tried
      AppBase=/qqq perl -T -e '#!/usr/bin/perl -T open my $FH, ">", $ENV{AppBase} or die $!;'
      لսႽ ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ
Re: How to safely define a CGI program's application base directory
by Anonymous Monk on Feb 11, 2013 at 03:49 UTC
    Don't worry about a malicious or careless admin :) don't set appbase from ENV vars

    Either set /abs/path/to/config/file or use something like use File::FindLib 'lib/MyCorp/Setup.pm'

Re: How to safely define a CGI program's application base directory
by Dallaylaen (Scribe) on Feb 11, 2013 at 13:19 UTC

    If your app is itself located under AppBase, you could use dirname() and __FILE__ which are taint-free:

    #!/usr/bin/perl -wT
    
    use strict;
    
    my $basedir;
    use File::Basename qw(dirname);
    BEGIN { $basedir = dirname(dirname(__FILE__)) };
    use lib $basedir.'/lib';
    
    use YAML; # Dummy - use fails if @INC is tainted
    print "File = ", __FILE__, "\n";
    print "Lib = @INC\n";
    If that's not the case, I would just assume AppBase is always fine and "untaint" it through some regular expression (preferably with a comment why I did so).

      BTW, on a *NIX system one can put rubbish into __FILE__ via

      % ln -s myscript.pl evil-char-sequence.pl
      Not as simple as 'SOMEVAR=evil-char-sequence ./myscript.pl', but still possible (but an unlikely attack vector, and not available to a remote attacker).
        If attacker has access to filesystem (or %ENV) the game is already over , nothing to worry about :)

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others meditating upon the Monastery: (5)
As of 2014-12-26 03:08 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    Is guessing a good strategy for surviving in the IT business?





    Results (164 votes), past polls