Apache Security - Ivan Ristic [83]
> $ ./configure \
> --enable-suexec \
> --with-suexec-bin=/usr/local/apache/bin/suexec \
> --with-suexec-caller=httpd \
> --with-suexec-userdir=public_html \
> --with-suexec-docroot=/home \
> --with-suexec-uidmin=100 \
> --with-suexec-gidmin=100 \
> --with-suexec-logfile=/var/www/logs/suexec_log \
> --with-suexec-safepath=/usr/local/bin:/usr/bin:/bin \
> --with-suexec-umask=022
Compile and install as usual. Due to high security expectations, suEXEC is known to be rigid. Sometimes you will find yourself compiling Apache several times until you configure the suEXEC mechanism correctly. To verify suEXEC works, look into the error log after starting Apache. You should see suEXEC report:
[notice] suEXEC mechanism enabled (wrapper: /usr/local/apache/bin/suexec)
If you do not see the message, that probably means Apache did not find the suexec binary (the --with-suexec-bin option is not configured correctly). If you need to check the parameters used to compile suEXEC, invoke it with the -V option, as in the following (this works only if done as root or as the user who is supposed to run suEXEC):
# /usr/local/apache/bin/suexec -V
-D AP_DOC_ROOT="/home"
-D AP_GID_MIN=100
-D AP_HTTPD_USER="httpd"
-D AP_LOG_EXEC="/var/www/logs/suexec_log"
-D AP_SAFE_PATH="/usr/local/bin:/usr/bin:/bin"
-D AP_SUEXEC_UMASK=022
-D AP_UID_MIN=100
-D AP_USERDIR_SUFFIX="public_html"
Once compiled correctly, suEXEC usage is pretty straightforward. The following is a minimal example of using suEXEC in a virtual host configuration. (The syntax is correct for Apache 2. To do the same for Apache 1, you need to replace SuexecUserGroup ivanr ivanr with User ivanr and Group ivanr.) This example also demonstrates the use of CGI script limit configuration:
ServerName ivanr.example.com DocumentRoot /home/ivanr/public_html # Execute all scripts as user ivanr, group ivanr SuexecUserGroup ivanr ivanr # Maximum 1 CPU second to be used by a process RLimitCPU 1 1 # Maximum of 25 processes at any one time RLimitNPROC 25 25 # Allow 10 MB to be used per-process RLimitMEM 10000000 10000000 Options +ExecCGI SetHandler cgi-script
A CGI script with the following content comes in handy to verify everything is configured correctly:
#!/bin/sh
echo "Content-Type: text/html"
echo
echo "Hello world from user `whoami`! "
Placed in the cgi-bin/ folder of the above virtual host, the script should display a welcome message from user ivanr (or whatever user you specified). If you wish, you can experiment with the CGI resource limits now, changing them to very low values until all CGI scripts stop working.
* * *
Tip
Because of its thorough checks, suEXEC makes it difficult to execute binaries using the SSI mechanism: command line parameters are not allowed, and the script must reside in the same directory as the SSI script. What this means is that users must have copies of all binaries they intend to use. (Previously, they could use any binary that was on the system path.)
* * *
Unless you have used suEXEC before, the above script is not likely to work on your first attempt. Instead, one of many suEXEC security checks is likely to fail, causing suEXEC to refuse execution. For example, you probably did not know that the script and the folder in which the script resides must be owned by the same user and group as specified in the Apache configuration. There are many checks like this and each of them contributes to security slightly. Whenever you get an "Internal Server Error" instead of script output, look into the suexec_log file to determine what is wrong. The full list of suEXEC checks can be found on the reference page http://httpd.apache.org/docs-2.0/suexec.html. Instead of replicating the list here I have decided to do something more useful. Table 6-2 contains a list of suEXEC error messages with explanations. Some error messages are clear, but many