Re: untainting PATH in mod_perl
Dominique Quatravaux wrote: Sorry, getting out of good ideas.. Surprise, surprise: I found out that my code does not work under mod_perl 1.23 either! And I found the real solution: one has to add PerlSetupEnv Off to the Apache configuration file. Now the untainting mumbo-jumbo in perl section works. Warning: this has the consequence of breaking the part of the CGI environment emulation that deals with environment (e.g. instead of $ENV{HTTP_USER_AGENT}, you now have to check Apache-request()-subprocess_env(HTTP_USER_AGENT)). Glancing at its source code, I don't think CGI.pm will survive that... BTW, I finally got around to reading mod_perl's source, and it is now clear to me that the environment, when being copied from -subprocess_env() into %ENV, gets tainted (around line 704 in src/modules/perl/mod_perl.c). The whole %ENV gets tainted, not just the HTTP_USER_AGENT and such from the CGI context, so PATH is tainted as well. This explains our now common problem - and also guarantees that there is no easy way out of it if you use CGI.pm yourself :-(. You need to untaint the variables before you use them. Since they get reset on every request, you need to untaint them inside your script/handler's run time, not the BEGIN block...: http://perl.apache.org/docs/1.0/guide/porting.html#BEGIN_blocks it should work just fine with mp1 and mp2. Relying on 'PerlSetupEnv Off' is not a very good idea, since if you want to release your code for others to use, they may not be able to turn it off, since it'll break their CGI-legacy code as you have observed. FWIW, I use the following code when I need to use ``|qx: local $ENV{PATH} = /bin:/usr/bin; local @ENV{ qw(IFS CDPATH ENV BASH_ENV) }; __ Stas BekmanJAm_pH -- Just Another mod_perl Hacker http://stason.org/ mod_perl Guide --- http://perl.apache.org mailto:[EMAIL PROTECTED] http://use.perl.org http://apacheweek.com http://modperlbook.org http://apache.org http://ticketmaster.com
Re: untainting PATH in mod_perl
On Tue, Jul 15, 2003 at 12:19:14PM +0300, Stas Bekman wrote: Dominique Quatravaux wrote: Sorry, getting out of good ideas.. Surprise, surprise: I found out that my code does not work under mod_perl 1.23 either! And I found the real solution: one has to add PerlSetupEnv Off to the Apache configuration file. Now the untainting mumbo-jumbo in perl section works. Warning: this has the consequence of breaking the part of the CGI environment emulation that deals with environment (e.g. instead of $ENV{HTTP_USER_AGENT}, you now have to check Apache-request()-subprocess_env(HTTP_USER_AGENT)). Glancing at its source code, I don't think CGI.pm will survive that... BTW, I finally got around to reading mod_perl's source, and it is now clear to me that the environment, when being copied from -subprocess_env() into %ENV, gets tainted (around line 704 in src/modules/perl/mod_perl.c). The whole %ENV gets tainted, not just the HTTP_USER_AGENT and such from the CGI context, so PATH is tainted as well. This explains our now common problem - and also guarantees that there is no easy way out of it if you use CGI.pm yourself :-(. You need to untaint the variables before you use them. Since they get reset on every request, you need to untaint them inside your script/handler's run time, not the BEGIN block...: http://perl.apache.org/docs/1.0/guide/porting.html#BEGIN_blocks it should work just fine with mp1 and mp2. Relying on 'PerlSetupEnv Off' is not a very good idea, since if you want to release your code for others to use, they may not be able to turn it off, since it'll break their CGI-legacy code as you have observed. FWIW, I use the following code when I need to use ``|qx: local $ENV{PATH} = /bin:/usr/bin; local @ENV{ qw(IFS CDPATH ENV BASH_ENV) }; But this code must be used in each scope where you intend to use backticks, a system call Etc. Is there no way to untaint your PATH environment one time for the script or handler? P -- ^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^ Peter B. Ensch ([EMAIL PROTECTED]) Linux 2.4.20-4GB 5:47am Up 2 days 18:47 ^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^
Re: untainting PATH in mod_perl
Peter B. Ensch wrote: FWIW, I use the following code when I need to use ``|qx: local $ENV{PATH} = /bin:/usr/bin; local @ENV{ qw(IFS CDPATH ENV BASH_ENV) }; But this code must be used in each scope where you intend to use backticks, a system call Etc. Is there no way to untaint your PATH environment one time for the script or handler? If you write code used by other people this is probably the only way to go. This is because you want to control the setting. What if PATH gets untainted at the server startup, but then some other module sets a new tainted value to $ENV{PATH}? So it's a good habit to have it local to the code that you run. Besides helps to avoid forking external processes. If you can rewrite your code: foreach(`/bin/ls $path`) { do something } (which is probably not the real code), not to `` but to read the file in, and process it, you eliminate the whole problem altogether. I realize that this is not always possible. How about abstracting untaint and `` into a single function: sub backticks { local $ENV{PATH} = /bin:/usr/bin; local @ENV{ qw(IFS CDPATH ENV BASH_ENV) }; qx(@_); } __ Stas BekmanJAm_pH -- Just Another mod_perl Hacker http://stason.org/ mod_perl Guide --- http://perl.apache.org mailto:[EMAIL PROTECTED] http://use.perl.org http://apacheweek.com http://modperlbook.org http://apache.org http://ticketmaster.com
Re: untainting PATH in mod_perl
On Tue, Jul 15, 2003 at 04:30:35PM +0300, Stas Bekman wrote: Peter B. Ensch wrote: FWIW, I use the following code when I need to use ``|qx: local $ENV{PATH} = /bin:/usr/bin; local @ENV{ qw(IFS CDPATH ENV BASH_ENV) }; But this code must be used in each scope where you intend to use backticks, a system call Etc. Is there no way to untaint your PATH environment one time for the script or handler? If you write code used by other people this is probably the only way to go. This is because you want to control the setting. What if PATH gets untainted at the server startup, but then some other module sets a new tainted value to $ENV{PATH}? So it's a good habit to have it local to the code that you run. Besides helps to avoid forking external processes. If you can rewrite your code: foreach(`/bin/ls $path`) { do something } (which is probably not the real code), not to `` but to read the file in, and process it, you eliminate the whole problem altogether. I realize that this is not always possible. How about abstracting untaint and `` into a single function: sub backticks { local $ENV{PATH} = /bin:/usr/bin; local @ENV{ qw(IFS CDPATH ENV BASH_ENV) }; qx(@_); } Stas, Thanks for your explanation and suggestion. I'm a lot clearer on this issue now. P. -- ^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^ Peter Ensch, [EMAIL PROTECTED] A-1140 (214) 480 2333 ^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^
Re: untainting PATH in mod_perl
Sorry, getting out of good ideas.. Surprise, surprise: I found out that my code does not work under mod_perl 1.23 either! And I found the real solution: one has to add PerlSetupEnv Off to the Apache configuration file. Now the untainting mumbo-jumbo in perl section works. Warning: this has the consequence of breaking the part of the CGI environment emulation that deals with environment (e.g. instead of $ENV{HTTP_USER_AGENT}, you now have to check Apache-request()-subprocess_env(HTTP_USER_AGENT)). Glancing at its source code, I don't think CGI.pm will survive that... BTW, I finally got around to reading mod_perl's source, and it is now clear to me that the environment, when being copied from -subprocess_env() into %ENV, gets tainted (around line 704 in src/modules/perl/mod_perl.c). The whole %ENV gets tainted, not just the HTTP_USER_AGENT and such from the CGI context, so PATH is tainted as well. This explains our now common problem - and also guarantees that there is no easy way out of it if you use CGI.pm yourself :-(. Hope I'm being helpful at last, -- Dominique QUATRAVAUX Ingénieur senior 01 44 42 00 08 IDEALX
Re: untainting PATH in mod_perl
I need some help with this. Can you share the code you use w/in your Perl section? Sure! Here is how I untaint a selected range of variables from the WWW server's %ENV, and discard all the others (good move to ease debugging anyway): # From httpd.conf PerlTaintCheck On perl BEGIN { # Untaint environment. Those variables come from # Apache; even if they didn't, they would come from the root # user who launched Apache. No security problems here. my %cleanenv; foreach my $var (qw(PATH GATEWAY_INTERFACE MOD_PERL)) { ($cleanenv{$var})=($ENV{$var} =~ m/^(.*)$/g); } %ENV=%cleanenv; } /perl I'm pretty confused because I was able to untaint my PATH var. by putting $ENV{PATH} = '/bin'; in the ***same scope*** where I was getting the error. Makes sense to me: if you are using Apache::Registry (for example), your script only gets compiled once and the BEGIN blocks run at that time. In fact Apache::Registry reads your cgi, then cooks it into something like this: package Some::Name::Made::Up::By::Apache::Registry::To::Isolate::Your::cgi; sub handler { # Your script here } Then it evals that (by that time, the BEGIN blocks run), then calls Some::Name::...::handler(). The purpose of these steps is caching: the next time the CGI is hit, the evalling needs not be redone, only the handler call. Now, my guess was that %ENV gets reset between the eval and the handler call. As you mention, putting the untainter in the same scope solves the problem, because you now circumvent the cleaning. Putting it in the perl section should also solve the problem once for all, because the perl section runs before the default %ENV value is stashed (even before Apache forks, in fact). -- Dominique QUATRAVAUX Ingénieur senior 01 44 42 00 08 IDEALX
Re: untainting PATH in mod_perl
On Thu, Jul 10, 2003 at 10:25:59AM +0200, Dominique Quatravaux wrote: I need some help with this. Can you share the code you use w/in your Perl section? Sure! Here is how I untaint a selected range of variables from the WWW server's %ENV, and discard all the others (good move to ease debugging anyway): # From httpd.conf PerlTaintCheck On perl BEGIN { # Untaint environment. Those variables come from # Apache; even if they didn't, they would come from the root # user who launched Apache. No security problems here. my %cleanenv; foreach my $var (qw(PATH GATEWAY_INTERFACE MOD_PERL)) { ($cleanenv{$var})=($ENV{$var} =~ m/^(.*)$/g); } %ENV=%cleanenv; } /perl I'm pretty confused because I was able to untaint my PATH var. by putting $ENV{PATH} = '/bin'; in the ***same scope*** where I was getting the error. Makes sense to me: if you are using Apache::Registry (for example), your script only gets compiled once and the BEGIN blocks run at that time. In fact Apache::Registry reads your cgi, then cooks it into something like this: package Some::Name::Made::Up::By::Apache::Registry::To::Isolate::Your::cgi; sub handler { # Your script here } Then it evals that (by that time, the BEGIN blocks run), then calls Some::Name::...::handler(). The purpose of these steps is caching: the next time the CGI is hit, the evalling needs not be redone, only the handler call. Now, my guess was that %ENV gets reset between the eval and the handler call. As you mention, putting the untainter in the same scope solves the problem, because you now circumvent the cleaning. Putting it in the perl section should also solve the problem once for all, because the perl section runs before the default %ENV value is stashed (even before Apache forks, in fact). Dominique, Thanks for sharing your code; unfortunately, it's not working for me. I copied it into my httpd.conf file, stopped/started the server and I still get the same error: [Thu Jul 10 11:10:38 2003] [error] 19156: ModPerl::Registry: Error executing run mode 'getlib': \ Insecure $ENV{PATH} while running setgid at /opt/asic/http/2.0.46/worker/perl-lib/Webace/Art.pm line 386 where line #386 is: foreach my $release (`/bin/ls $path`) { # $path is already untainted do stuff } Any other ideas? Thanks and regards, P -- ^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^ Peter Ensch, [EMAIL PROTECTED] A-1140 (214) 480 2333 ^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^
Re: untainting PATH in mod_perl
Thanks for sharing your code; unfortunately, it's not working for me. I copied it into my httpd.conf file, stopped/started the server and I still get the same error: Sorry, getting out of good ideas.. I'm not using mod_perl 1.99, this probably explains why my code does not work, and also it prevents me from further investigating your problem. There was a thread recently on the list about perl ... /perl section only being implemented recently, do you run the latest version of mod_perl? Insecure $ENV{PATH} while running setgid While running setgid? That's odd (although I don't think this nterfers with your problem in any way) foreach my $release (`/bin/ls $path`) { # $path is already untainted do stuff } TI (still) MTOWTDI: why not try use IO::Pipe; my $pipe = new IO::Pipe()-reader(/bin/ls,$path); while($pipe) { } (although this will not save you from having to review all your codebase) -- Dominique QUATRAVAUX Ingénieur senior 01 44 42 00 08 IDEALX
untainting PATH in mod_perl
perlsec says that to untaint the PATH env one should do: $ENV{'PATH'} = '/bin:/usr/bin'; delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'}; In plain CGI, I normally do this inside a BEGIN block; in mod_perl however, this doesn't work. A print of $ENV{PATH} returns the original tainted PATH. In my script I'm doing something like foreach(`/bin/ls $path`) { do something } $path is already untainted but I'm still getting an 'Insecure $ENV{PATH}' error. What am I missing here? Thanks, P -- ^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^ Peter Ensch, [EMAIL PROTECTED] A-1140 (214) 480 2333 ^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^
Re: untainting PATH in mod_perl
In plain CGI, I normally do this inside a BEGIN block; in mod_perl however, this doesn't work. This would work if this was done in a Perl section of the httpd.conf file (this is what I do). I am not sure why the BEGIN block is not executed, but my guess is that the environment gets automatically restored at the end of every script run under Apache::Registry, including the tainted PATH. -- Dominique QUATRAVAUX Ingénieur senior 01 44 42 00 08 IDEALX
Re: untainting PATH in mod_perl
On Wed, Jul 09, 2003 at 05:40:32PM +0200, Dominique Quatravaux wrote: In plain CGI, I normally do this inside a BEGIN block; in mod_perl however, this doesn't work. This would work if this was done in a Perl section of the httpd.conf file (this is what I do). I am not sure why the BEGIN block is not executed, but my guess is that the environment gets automatically restored at the end of every script run under Apache::Registry, including the tainted PATH. I need some help with this. Can you share the code you use w/in your Perl section? I'm pretty confused because I was able to untaint my PATH var. by putting $ENV{PATH} = '/bin'; in the ***same scope*** where I was getting the error. For example $ENV{PATH} = '/bin'; my @files = `/bin/ls $path`; # $path is already untainted was OK; leave out the $ENV line and I get an Insecure $ENV{PATH} error. This works (don't know why) but I would prefer to fix the PATH in one place rather than having to do so everywhere I shell out or use backticks. Thanks, P -- ^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^ Peter B. Ensch ([EMAIL PROTECTED]) Linux 2.4.20-4GB 8:21pm Up 18 days 2:55 ^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^