June 15, 2011, 5:39 a.m.
posted by unixgeek
Install Apache with SSL and suEXEC
Help secure your web applications with mod_ssl and suEXEC.
Web server security is a very important issue these days, especially since people are always finding new and creative ways to put the Web to use. If you're using any sort of web application that needs to handle authentication or provides some sort of restricted information, you should seriously consider installing a web server with SSL capabilities. Without SSL, any authentication information your users send to the web server is sent over the network in the clear, and anyone with a sniffer can view any information that clients can access. If you are already using Apache 2.x, you can easily rebuild it to add SSL capabilities. If you're using Apache 1.x, you can do this with mod_ssl (http://www.modssl.org).
In addition, if your web server serves up dynamic content for multiple users, you might want to enable Apache's suEXEC functionality. suEXEC allows your web server to execute server-side scripts as the user that owns them, rather than as the account under which the web server is running. Otherwise, any user could create a script and run code as the account under which the web server is running. This is a bad thing, particularly on a multiuser web server. If you don't review the scripts that your users write before allowing them to be run, they could very well write code that allows them to access other users' data or other sensitive information, such as database accounts and passwords.
After you've done that, unpack the mod_ssl distribution and go into the directory that it creates. Then, run a command like this:
$ ./configure \ --with-apache=../apache_1.3.36 \ --with-ssl=SYSTEM \ --prefix=/usr/local/apache \ --enable-module=most \ --enable-module=mmap_static \ --enable-module=so \ --enable-shared=ssl \ --disable-rule=SSL_COMPAT \ --server-uid=www \ --server-gid=www \ --enable-suexec \ --suexec-caller=www \ --suexec-uidmin=500 \ --suexec-gidmin=500
This both patches the Apache source tree with extensions provided with mod_ssl and configures Apache for the build process.
You will probably need to change a number of options in order to build Apache. The directory specified in the --with-apache switch should point to the directory that contains the Apache source code for the version you are building. In addition, if you want to use a version of OpenSSL that has not been installed yet, specify the location of its build tree with the --with-ssl switch.
If you elect to do that, you should configure and build OpenSSL in the specified directory before attempting to build Apache and mod_ssl. The --server-uid and --server-gid switches specify the user and group under which the web server will run. Apache defaults to the nobody account. However, many programs that can be configured to drop their privileges also default to the nobody account; if you end up accepting these defaults with every program, the nobody account can become quite privileged. So, it is recommended that you create a separate account for every program that provides this option.
The remaining options enable and configure Apache's suEXEC. To provide the suEXEC functionality, Apache uses a SUID wrapper program to execute users' scripts. This wrapper program makes several checks before it allows a program to execute. One thing that the wrapper checks is the UID of the process that invoked it. If it is not the account that was specified with the --suexec-caller option, execution of the user's script will abort. Since the web server will call the suEXEC wrapper, set this option to the same value as --server-uid.
Additionally, since most privileged accounts and groups on a system usually all have a UID and GID beneath a certain value, the suEXEC wrapper will check to see if the UID or GID of the process invoking it is below this threshold. For this to work, you must specify the appropriate value for your system. In this example, Apache and mod_ssl are being built on a Red Hat system, which starts regular user accounts and groups at UID and GID 500. In addition to these checks, suEXEC performs a multitude of other checks, such as ensuring that the script is writable only by the owner, that the owner is not root, and that the script is not SUID or SGID.
After the configure script completes, change to the directory that contains the Apache source code and run make and make install. You can run make certificates if you would like to generate an SSL certificate to test out your installation. You can also run make certificate TYPE=custom to generate a certificate signing request to be signed by either a commercial Certificate Authority or your own CA [Hack #69].
After installing Apache, you can start it by running this command:
# /usr/local/apache/bin/apachectl startssl
If you want to start out by testing it without SSL, run this:
# /usr/local/apache/bin/apacectl start
You can then run this command to verify that suEXEC support is enabled:
# grep suexec /usr/local/apache/logs/error_log [Thu Jan 1 16:48:17 2004] [notice] suEXEC mechanism enabled (wrapper: /usr/local/apache/bin/suexec)
<Directory /home/*/public_html> AllowOverride FileInfo AuthConfig Limit Options MultiViews Indexes SymLinksIfOwnerMatch Includes ExecCGI <Limit GET POST OPTIONS PROPFIND> Order allow,deny Allow from all </Limit> <LimitExcept GET POST OPTIONS PROPFIND> Order deny,allow Deny from all </LimitExcept> </Directory>
In addition, add this line to enable CGI scripts outside of the ScriptAlias directories:
AddHandler cgi-script .cgi
After you've done that, you can restart Apache by running this command:
# /usr/local/apache/bin/apachectl restart
#!/bin/sh echo -e "Content-Type: text/plain\r\n\r\n" /usr/bin/id
Put this script in a directory such as /usr/local/apache/cgi-bin, name it suexec-test.cgi, and make it executable. Now, enter the URL for the script (e.g., http://webserver/cgi-bin/suexec-test.cgi) into your favorite web browser. You should see something like this:
uid=80(www) gid=80(www) groups=80(www)
As you can see, it is being executed under the same UID as the web server.
Now, copy the script into a user's public_html directory:
$ mkdir public_html && chmod 711 ~/ ~/public_html $ cp /usr/local/apache/cgi-bin/suexec-test.cgi ~/public_html
After you've done that, enter the URL for the script (e.g., http://webserver/~user/suexec-test.cgi) in your web browser. You should see something similar to this:
uid=500(andrew) gid=500(andrew) groups=500(andrew)
In addition to handling scripts in users' private HTML directories, suEXEC can execute scripts as another user within a virtual host. However, to enable this, you will need to create all of your virtual host's directories beneath the web server's document root (e.g., /usr/local/apache/htdocs). When doing this, you can configure what user and group the script will execute as by using the User and Group configuration directives within the VirtualHost statement:
<VirtualHost> User myuser Group mygroup DocumentRoot /usr/local/apache/htdocs/mysite ... </VirtualHost>
Setting up Apache 2.x isn't very different from setting up Apache 1.x. The main difference is that SSL functionality is already included and just needs to be enabled. The options used to enable suEXEC are also slightly different:
$ ./configure \ --with-ssl=SYSTEM \ --prefix=/usr/local/apache2 \ --enable-module=most \ --enable-module=mmap_static \ --enable-module=so \ --enable-ssl \ --enable-suexec \ --with-suexec-caller=daemon \ --with-suexec-uidmin=500 \ --with-suexec-gidmin=500
One thing that you'll notice is absent is the ability to specify the user and group under which the server executes. Apache 2 defaults to the daemon user and group, which you can change later by modifying the User and Group lines in the configuration file, httpd.conf. If you use the --prefix option the way it's shown in this example, httpd.conf will be in /usr/local/apache2/conf. When you change these lines you'll also need to rebuild the daemon and tell the configure script the new user with the --with-suexec-caller option.
After the configure script completes, build and install the daemon by running make and then changing to root and running make install. Once that has finished, you'll need to edit the configuration file to set up SSL. Do this by uncommenting the line that includes the SSL-specific configuration options:
Now, you need to tell Apache where to find your certificate and key by editing the file specified in the Include enTRy. By default, it looks for server.crt and server.key in the same directory as httpd.conf:
SSLCertificateFile /usr/local/apache2/conf/server.crt SSLCertificateKeyFile /usr/local/apache2/conf/server.key
Once you have your certificate and key configured, start Apache by using apachectl:
# /usr/local/apache2/bin/apachectl start
The difference between Apache 1.x and 2.x here is that apachectl no longer differentiates between SSL and non-SSL configurations, so the startssl argument isn't accepted anymore. Aside from these differences, you can follow the same steps used for Apache 1.x.
Unfortunately, suEXEC is incompatible with mod_perl and mod_php, because the modules run within the Apache process itself instead of in a separate program. Since the Apache process is running as a nonroot user, it cannot change the UID under which the scripts execute. suEXEC works by having Apache call a special SUID wrapper (e.g., /usr/local/apache/bin/suexec) that can only be invoked by Apache processes.
If you care to make the security/performance trade-off by using suEXEC but still need to run Perl scripts, you can do so through the standard CGI interface. You can also run PHP programs through the CGI interface, but you'll have to create a php binary and specify it as the interpreter in all the PHP scripts you wish to execute through suEXEC. Alternatively, you can execute your scripts through mod_perl or mod_php by locating them outside the directories where suEXEC will work.