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
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 ^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^
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: require'ing data files under mod_perl
On Thu, Jul 03, 2003 at 05:15:31PM -0400, Perrin Harkins wrote: On Thu, 2003-07-03 at 16:59, Peter Ensch wrote: OK. Thanks. Well, yes it is being reloaded whenever the form is submitted and w/out restarting the server. Here's some of the output (error_log): [Thu Jul 3 15:52:00 2003] users.dat: users.dat loaded by process 18294 at /opt/a... Just a guess, but maybe this is because you're passing a variable to the require function. Try hard-coding it and see if it changes. This sounded like a good explanation but it wasn't. Hard-coding the require'd file didn't make any difference; nor did the assignment to a variable. In each case the require'd file was reloaded each time the script was invoked. It's a mystery! P -- ^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^ Peter Ensch, [EMAIL PROTECTED] A-1140 (214) 480 2333 ^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^
Re: require'ing data files under mod_perl
On Mon, Jun 30, 2003 at 05:28:43PM -0400, Perrin Harkins wrote: On Sat, 2003-06-28 at 15:08, Peter B. Ensch wrote: Coding in plain CGI I've often require'd files containing data in perl data-structures. The script may write to the file (via Data::Dumper for example) allowing subsequent invokations of the script to have access to the revised data. It would be simpler and faster to use MLDBM::Sync for this. Not familiar w/ this module and it's not on our system; I'll certainly look into it. I was expecting this methodology to break under mod_perl thinking that the require would only happen once (the first time the script runs after server startup); however, it seems to be working the way it always did. Why is this? Am I missing something? Can't tell without seeing some code. Your require'd files with not be reloaded unless you are using Apache::Reload or Apache::StatINC to force them. I'm NOT using A::Reload or A::StatINC. My script appears to be require'ing the data file on each user transaction, just like under plain CGI. I'm using CGI::Application and this part of the code happens inside the cgiapp_init() method which I'm overriding: our $USERS : unique = /path/to/users.dat; sub cgiapp_init { my $self = shift; $self-param('users' = require ${\$USERS}); } So, to reiterate, I may write to users.dat on one transaction and read on another; the file contents is always up-to-date. I still can't understand why this is because I did not think it would be reloaded unless the server was restarted. BTW - it doesn't have anything to do with the 'unique' our attribute; same behavour with or without. I'm new to apache and I'm not running in single-process mode; this shouldn't have a bearing should it? Thanks, P -- ^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^ Peter Ensch, [EMAIL PROTECTED] A-1140 (214) 480 2333 ^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^
Re: require'ing data files under mod_perl
On Thu, Jul 03, 2003 at 02:51:23PM -0400, Perrin Harkins wrote: On Thu, 2003-07-03 at 13:38, Peter Ensch wrote: I'm using CGI::Application and this part of the code happens inside the cgiapp_init() method which I'm overriding: our $USERS : unique = /path/to/users.dat; sub cgiapp_init { my $self = shift; $self-param('users' = require ${\$USERS}); } That's confusing code. Your users.dat file is a chunk of code that returns a value that you use? A little obscure, in my opinion. And what's that stuff with the ref/de-ref syntax for? The file contains a simple hash ref. like { duck = 'quack', dog = 'woof', cat = 'meow', } The ref/de-ref was a mistake; a hold over from when USERS was a constant (and which didn't interpolate in a require). Now it's $self-param('users' = require $USERS); So, to reiterate, I may write to users.dat on one transaction and read on another; the file contents is always up-to-date. The file is up-to-date, or the param 'users' is? The file is. IE. it gets written and and the new stuff is available by simply reloading the page. Why don't you debug it a little by putting a warn statement in your users.dat file that prints the process ID? Then you can tell if it is truly being executed more than once by the same process. Hmm. Not sure how to do that w/out messing w/ the headers and making the app. crash. How would I do that? P -- ^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^ Peter Ensch, [EMAIL PROTECTED] A-1140 (214) 480 2333 ^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^
Re: require'ing data files under mod_perl
On Thu, Jul 03, 2003 at 04:24:35PM -0400, Perrin Harkins wrote: On Thu, 2003-07-03 at 16:16, Peter Ensch wrote: So, to reiterate, I may write to users.dat on one transaction and read on another; the file contents is always up-to-date. The file is up-to-date, or the param 'users' is? The file is. IE. it gets written and and the new stuff is available by simply reloading the page. Well, the file getting written is not related to require loading each time or not. The thing that I would not expect to change is the in-memory data. Why don't you debug it a little by putting a warn statement in your users.dat file that prints the process ID? Then you can tell if it is truly being executed more than once by the same process. Hmm. Not sure how to do that w/out messing w/ the headers and making the app. crash. How would I do that? Before the hash stuff in the file, put in a statement like this: warn users.dat loaded by process $$; OK. Thanks. Well, yes it is being reloaded whenever the form is submitted and w/out restarting the server. Here's some of the output (error_log): [Thu Jul 3 15:52:00 2003] users.dat: users.dat loaded by process 18294 at /opt/a... [Thu Jul 3 15:52:00 2003] users.dat: users.dat loaded by process 18294 at /opt/a... [Thu Jul 3 15:52:00 2003] users.dat: users.dat loaded by process 18294 at /opt/a... [Thu Jul 3 15:52:03 2003] users.dat: users.dat loaded by process 18294 at /opt/a... [Thu Jul 3 15:52:04 2003] users.dat: users.dat loaded by process 18294 at /opt/a... [Thu Jul 3 15:52:06 2003] users.dat: users.dat loaded by process 18294 at /opt/a... [Thu Jul 3 15:52:32 2003] users.dat: users.dat loaded by process 18294 at /opt/a... [Thu Jul 3 15:52:33 2003] users.dat: users.dat loaded by process 18338 at /opt/a... [Thu Jul 3 15:52:34 2003] users.dat: users.dat loaded by process 18338 at /opt/a... [Thu Jul 3 15:53:00 2003] users.dat: users.dat loaded by process 18338 at /opt/a... [Thu Jul 3 15:53:03 2003] users.dat: users.dat loaded by process 18338 at /opt/a... [Thu Jul 3 15:53:05 2003] users.dat: users.dat loaded by process 18338 at /opt/a... [Thu Jul 3 15:53:22 2003] users.dat: users.dat loaded by process 18338 at /opt/a... [Thu Jul 3 15:53:25 2003] users.dat: users.dat loaded by process 18338 at /opt/a... [Thu Jul 3 15:53:28 2003] users.dat: users.dat loaded by process 18338 at /opt/a... [Thu Jul 3 15:53:28 2003] users.dat: users.dat loaded by process 18338 at /opt/a... Here are the httpd process: [490] % ps -Alf |grep apache 8 S root 17921 ... /apps/apache/http/2.0.46/worker/bin 8 S apache 18338 ... /apps/apache/http/2.0.46/worker/bin 8 S apache 18336 ... /apps/apache/http/2.0.46/worker/bin 8 S apache 18337 ... /apps/apache/http/2.0.46/worker/bin So. What's going on? I'm not using A::Reload. P -- ^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^ Peter Ensch, [EMAIL PROTECTED] A-1140 (214) 480 2333 ^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^~^