Section 8.2. Build Time: Installing Apache

A secure web service starts with a secure web server, which in turn, starts with good code ? no buffer overflows, race conditions, or other problems that could be exploited to gain root privileges. It should be immune to remote root exploits by the swarming script kiddies. By any criteria, Apache is pretty good. No serious exploit has been reported since January 1997; security patches have addressed minor vulnerabilities.

Apache's main competition among web servers, Microsoft's Internet Information Server (IIS), has had many critical and ongoing security problems. A Microsoft Security Bulletin issued in April 2002 describes ten critical problems in IIS 4 and 5. These include vulnerabilities to buffer overruns, denial of service, and cross-site scripting; a number of these provide full-system privileges to the attacker.

In practice, most Apache security problems are caused by configuration errors, and I'll talk about how to avoid these shortly. Still, there are always bug fixes, new features, and performance enhancements, along with the occasional security fix, so it's best to start from the most recent stable release.

As this was written, Apache 2.0 was released for general availability after years of development and testing. It will take a while for this to settle down and percolate into Linux distributions and existing systems, so the 1.3 family is still maintained. I'll cover 1.3 configuration here, with mentions of 2.x where it differs.

See http://www.apacheweek.com/security/ for Apache security news.

8.2.1 Starting Installation

Attacks are so frequent on today's Internet that you don't want to leave a window for attack, even for the few minutes it takes to set up a secure server. This section covers setting up your environment and obtaining the right version of Apache.

8.2.1.1 Setting up Your firewall

A public web server is commonly located with email and name servers in a DMZ, between outer and inner firewalls. If you're doing your own hosting, you need at least one layer of protection between your public web server and your internal network.

Web servers normally listen on TCP ports 80 (http:) and 443 (secure HTTP, https:). While you're installing Apache and the pieces are lying all around, block external access to these ports at your firewall (with iptables or other open source or commercial tools). If you're installing remotely, open only port 22 and use ssh. After you've configured Apache, tightened your CGI scripts (as described in this chapter), and tested the server locally, you should then reopen access to the world.

8.2.1.2 Checking Your Apache version

If you have Linux, you almost certainly already have Apache somewhere. Check your version with the following command:

httpd -v

Check the Apache mirrors (http://www.apache.org/mirrors/) or your favorite Linux distribution site for the most recent stable release of Apache, and keep up with security updates as they're released. Red Hat publishes overall security updates at http://www.redhat.com/apps/support/errata/.

If you're running an older version of Apache, you can build a new version and test it with another port, then install it when ready. If you plan to replace any older version, first see if another copy of Apache (or another web server) is running:

service httpd status

or:

ps -ef | grep httpd

If Apache is running, halt it by entering the following:

apachectl stop

or (Red Hat only):

service httpd stop

or:

/etc/init.d/apache stop

Make sure there aren't any other web servers running on port 80:

netstat -an |  grep ':80'

If you see one, kill -9 its process ID, and check that it's really most sincerely dead. You can also prevent it from starting at the next reboot with this command:

chkconfig httpd off

8.2.2 Installation Methods

Should you get a binary installation or source? A binary installation is usually quicker, while a source installation is more flexible and current. I'll look at both, but emphasize source, since security updates usually should not wait.

8.2.2.1 RPM installation

Of the many Linux package managers, RPM may be the most familiar, so I'll use it for this example. Grab the most current stable version of Apache from http://www.apache.org, your favorite Linux distribution, or any RPM site. Here's an example of obtaining and installing an older Apache RPM from Red Hat's site:

# wget ftp://ftp.redhat.com/pub/redhat/linux/updates/7.0/en/\

os/i386/apache-1.3.22-1.7.1.i386.rpm

# rpm -Uvh apache-1.3.22-1.7.1.i386.rpm

Depending on whose RPM package you use, Apache's files and directories will be installed in different places. This command prints where the package's files will be installed:

rpm -qpil apache-1.3.22-1.7.1.i386.rpm

We'll soon see how to make Apache's file hierarchy more secure, no matter what it looks like.

8.2.2.2 Source installation

Get the latest stable tarball:

# wget http://www.apache.org/dist/httpd/apache_1.3.24.tar.gz

# tar xvzf apache_1.3.24.tar.gz

# cd apache_1.3.24

If the file has an MD5 or GPG signature, check it (with md5sum or gpgv) to ensure you don't have a bogus distribution or a corrupted download file.

Then, run the GNU configure script. A bare:

# ./configure

will install everything in directories under /usr/local/apache (Apache 2 uses /usr/local/apache2). To use another directory, use --prefix:

# ./configure --prefix=/usr/other/apache

Apache includes some standard layouts (directory hierarchies). To see these and other script options, enter the following:

# ./configure --help

Next, run good old make:

# make

This will print pages of results, eventually creating a copy of Apache called httpd in the src subdirectory. We'll look at what's actually there in the next section. When you're ready to install Apache to the target directory, enter the following:

# make install
8.2.2.3 Linking methods

Does the preceding method produce a statically linked or dynamically linked executable? What modules are included? By including fewer modules, you use less memory and have fewer potential problems. "Simplify, simplify," say Thoreau, the least privilege principle, and the Web Server Diet Council.

Dynamic linking provides more flexibility and a smaller memory footprint. Your copy of Apache is dynamically linked if you see something like this:

# httpd -l

Compiled-in modules:

  http_core.c

  mod_so.c

Dynamically linked versions of Apache are easy to extend with some configuration options and an Apache restart. Recompilation is not needed. I prefer this method, especially when using the Perl or PHP modules. See http://httpd.apache.org/docs/dso.html for details on these Dynamic Shared Objects (DSOs).

A statically linked Apache puts the modules into one binary file, and it looks something like this:

# httpd -l

Compiled-in modules:

  http_core.c

  mod_env.c

  mod_log_config.c

  mod_mime.c

  mod_negotiation.c

  mod_status.c

  mod_include.c

  mod_autoindex.c

  mod_dir.c

  mod_cgi.c

  mod_asis.c

  mod_imap.c

  mod_actions.c

  mod_userdir.c

  mod_alias.c

  mod_access.c

  mod_auth.c

  mod_setenvif.c

suexec: disabled; invalid wrapper /usr/local/apache/bin/suexec

Specify --activate-module and --add-module to modify the module list. Changing any of the modules requires recompilation and relinking.

8.2.3 Securing Apache's File Hierarchy

Wherever your installation scattered Apache's files, it's time to make sure they're secure at runtime. Loose ownership and permission settings are a common cause of security problems.

We want the following:

  • A user ID and group ID for Apache to use

  • User IDs for people who will provide content to the server

Least privilege suggests we create an Apache user ID with as little power as possible. You will often see use of user ID nobody and group ID nobody. However, these IDs are also used by NFS, so it's better to use dedicated IDs. Red Hat uses user ID apache and group ID apache. The apache user has no shell and few permissions ? just the kind of guy we want, and the one we'll use here.

There are different philosophies on how to assign permissions for web user IDs. Here are some solutions for content files (HTML and such):

  • Add each person who will be modifying content on the web site to the group apache. Make sure that others in the group (including the user ID apache) can read but not write one another's files (run umask 137; chmod 640 for each content file and directory). These settings allow developers to edit their own files and let others in the group view them. The web server (running as user apache) can read and serve them. Other users on the web server can't access the files at all. This is important because scripts may contain passwords and other sensitive data. The apache user can't overwrite files, which is also useful in case of a lapse.

  • The previous settings may be too extreme if you need to let web developers overwrite each other's files. In this case, consider mode 660. This is a little less secure because now the apache user can also overwrite content files.

  • A common approach (especially for those who recommend user ID nobody and group ID nobody) is to use the other permissions for the apache user (mode 644). I think this is less safe, since it also gives read access to other accounts on the server.

Table 8-2 lists the main types of files in an Apache distribution, where they end up in a default RPM installation or a source installation, and recommended ownership and permissions.

Table 8-2. File locations for apache installations

File types

Notable files

Red Hat RPM directories

Source directories

Owner/modes

Initialization script

Httpd

/etc/init.d

(no standard)

Should be owned by root, with directory mode 755 and file mode 755

Configuration files

httpd.confaccess.confsrm.conf

/etc/httpd/conf

/usr/local/apache/conf

Should be owned by root, with directory mode 755 and file mode 644

Logs

access_logerror_log

/etc/httpd/logs

/usr/local/apache/logs

Should be owned by root, with directory mode 755 and file mode 644

Apache programs

httpdapachectl

/usr/sbin

/usr/local/apache/bin

Should be owned by root, with directory mode 755 and file mode 511

Apache utilities

htpasswdapxsrotatelogs

/usr/sbin

/usr/local/apache/bin

Should be owned by root, with directory mode 755 and file mode 755

Modules

mod_perl.so

/usr/lib/apache

/usr/local/apache/libexec

Should be owned by root, with directory mode 755 and file mode 755

CGI programs

(CGI scripts)

/var/www/cgi-bin

/usr/local/apache/cgi-bin

Directory should be owned by user root with mode 755; files should be owned by users in group apache, with mode 750

Static content

(HTML files)

/var/www/html

/usr/local/apache/htdocs

Directories should be owned by user apache with mode 470; files should be owned by users in group apache, with mode 640

Password/data files

(Varies)

(No standard)

(No standard)

Directories should be owned by user apache with mode 470; files should be owned by users in group apache, with mode 640