Overview
suEXEC (switch user execution) is a feature that allows Apache users to run CGI and SSI scripts as various users. It significantly decreases the security risks associated with allowing users to design and operate private CGI or SSI programs when utilized appropriately.
Security
Script permissions
All CGI scripts and the directories in which they live must only be writable by the owner, according to suEXEC. A 500 Internal Server Error is triggered if permissions are not specified correctly.
The script must also be able to be run. You can change permissions by using SSH to connect to your server and using the chmod command. Consider the following scenario:
chmod 755 script.cgi [server]$
Environment variable checking
In the examples below, username is your Shell user, and example.com is your website.
suEXEC is a good example.
The directives given by mod env, such as SetEnv, PassEnv, and SetEnvIf, do not work as expected since suEXEC only accepts variables judged safe by the server’s setup.
The instructions below demonstrate how suEXEC works at GreggHost in a basic example.
Step 1 — Add a file to your site
Make a foobar.cgi file with the following content.
#!/usr/bin/perl
Use CGI if you want to be rigorous.
my $q = CGI->new; print $q->header(); print $ENVFOOBAR; $ENVFOOBAR ||= ‘default’; $ENVFOOBAR ||= ‘default’; $ENVFOOBAR ||= ‘default’; $ENVFOOBAR ||= ‘default’; $ENVFOOBAR ||= ‘default
Use the same username on two different websites to upload this file. Consider the following scenario:
/home/username/example.com \s/home/username/example2.com
Step 2 — Add an .htaccess file to each directory
Add the following directive to the.htaccess file in the example.com directory:
SetEnv FOOBAR foo SetEnv FOOBAR foo SetEnv FOOBAR fo
Add the following directive to the.htaccess file in the example2.com directory:
SetEnv FOOBAR bar SetEnv FOOBAR bar SetEnv FOOBAR bar
Step 3 — Visit the files in a browser
In your browser, go to example.com/foobar.cgi. It should print foo, right?
In your browser, go to example2.com/foobar.cgi. You’d think it’d print a bar.
Default is printed on both pages instead.
Explanation
SetEnv is properly setting the environment variable. SuEXEC isn’t providing it to your CGI script, which is the issue.
Workarounds The parts that follow will show you how to make your environment variables to work as they should.
Option 1: Prepend HTTP_ to the variable name
SuEXEC on GreggHost allows any environment variable beginning with HTTP_ to be sent through.
Replace the following in your.htaccess file:
Use the following in your CGI script after setting the environment variable HTTP FOOBAR foobar.
$ENV{HTTP FOOBAR}
As a result, it performs as planned.
When should you utilize this option?
This solution is best suited for self-developed applications.
Digging through the source code of third-party applications (especially large applications with hundreds of thousands of lines) and changing each instance of $ENVFOOBAR to $ENVHTTP FOOBAR would be prohibitively complex and time-consuming, not to mention that you’d have to repeat the process every time the application was upgraded.
Option 2: Edit the CGI script to set the variable itself
At the top of your script, put $ENVFOOBAR = ‘foo’; Consider the following scenario:
#!/usr/bin/perl
Use CGI if you want to be rigorous.
$ENVFOOBAR = ‘foo’; $ENVFOOBAR = ‘foo’; $ENVFOOBAR = ‘fo
my $q = CGI->new; print $q->header(); print $ENVFOOBAR; $ENVFOOBAR ||= ‘default’; $ENVFOOBAR ||= ‘default’; $ENVFOOBAR ||= ‘default’; $ENVFOOBAR ||= ‘default’; $ENVFOOBAR ||= ‘default
When should you utilize this option?
This solution, like Option 1, is best suited to self-developed apps.
Keep in mind that the aim of utilizing environment variables is to change the behavior of your script depending on the context (or environment) in which it is run. If you set the variable from within the script, the script behaves the same regardless of the environment in which it is run.
Option 3: Create a wrapper script
Make a wrapper.cgi file with the following content:
#!/bin/sh
exec /home/username/example.com/foobar.cgi export FOOBAR=foo
Then, in your.htaccess file, add the following to redirect script requests to wrapper.cgi:
Script.cgi /wrapper.cgi Script.cgi /wrapper.cgi Script.cgi /wrapper.cgi Script.cgi /wrap