Professional Documents
Culture Documents
Overview
This document is a guide to installing and hardening an Apache 2.0 web server to common security standards. It will
guide you through practical measures to harden your Apache server, by way of example.
Because a web server is often placed at the edge of the network, it is one of the most vulnerable services to attack.
Therefore, it’s vital that you follow this guide to ensure that:
Follow the hardening guidelines in the The Center for Internet Security. Hardening the host O/S ensures that,
should someone compromise the security of your web server, the amount of damage that they could inflict will
be minimized.
It’s important to separate the binaries /bin, docs (/htdocs), and logs (/logs) into separate partitions on the
system. You can choose whatever root you want, but this example will use /opt/apache2 as the root directory
for the Apache web server.
1.3 Create the host groups for administering and running the server.
Create a distinct group for all the users who will have permission to change the configuration, start, and stop
the web server. For example, if you want to call the group “webadmin”, create it like this:
# groupadd webadmin
Create a distinct group for the web server user – no one will actually log into this group, but it will only be used
to hold the userid which will run the web server. For example, if you want to call that group “webserv”, create
it like this:
# groupadd webserv
Take note that you should not create a “web developer” group on this host. Since this is a hardened production
host you must not provide web developers login accounts on this system. Instead, developers should deploy
documents and code to the server using your code/content deployment system, such as Kintana’s Apps*Integrity.
Never run the web server as root; if the web server is ever compromised, the attacker will have complete
control over the system. Instead, the best way to reduce your exposure to attack when running a web server is
to create a unique unprivileged userid for the server application. The userid nobody is often used for this
purpose, but a userid and group that are unique to the web server is a more secure solution.
By default the web server uses privileged ports (port 80 and 443) and, when configured for secure operation,
must have root privileges to open its log files and start the dæmon. (Therefore, the web server daemon will
have to be started as “root”, unless you configure it to use a port higher than 1024.) Once the server's startup
tasks are complete, all active instances can run as the unprivileged user.
2 of 11
Use the following command line entries as patterns for creating a group and user for the web server. Here’s an
example if you were to use “webserv” as the user:
It’s important that no one can successfully execute a password guessing attack against this account, so in this
step, we’ll restrict this account so that no one can log into it.
1.5.1 Issue this command to lock the password for the web server account:
# passwd –l webserv
Password changed.
…a :!: at the beginning of the line indicates that the password is locked.
1.5.3 Issue this command to remove the shell for this account:
…/bin/false at the end of the line indicates that the shell is set to a non-existent shell.
1.5.5 Test the web server account to be sure you can’t login. Issue this command to try to log in:
By default, web servers return information about the product and version they are running in the Server variable of the
HTTP header. This information can be very useful to hackers, enabling them to target attacks to that specific server.
To prevent that information from being returned from the web server, this step shows you how to modify that header
and build your own copy of the web server.
Because web servers often host sensitive information, or allow users to log in with plain-text passwords, it’s important
to encrypt the HTTP traffic. Therefore, this section will show you how to configure mod_ssl on your web server.
Note: Don’t build the web server on your production, hardened host. Build it on a staging or development server
(with identical O/S), and then copy it to your production host.
These steps will guide you through downloading Apache source code, validating it, compiling it, and installing it. We
don’t recommend use of pre-compiled or DSO versions. DSO versions may allow a hacker to introduce new “features”
without having to recompile the code.
If you intend to add other module to your Apache web server installation, repeat the validation steps below for each
module you add.
Ensure that you retrieve the latest copy, so that you have cumulative bug fixes and security patches. You can
download it from the Apache site.
3 of 11
wget http://www.apache.org/dist/httpd/httpd-2.0.45.tar.gz
wget http://www.apache.org/dist/httpd/KEYS
wget http://www.apache.org/dist/httpd/httpd-2.0.45.tar.gz.asc
wget http://www.apache.org/dist/httpd/httpd-2.0.45.tar.gz.md5
To ensure that you have an authentic version from the Apache Group, and that it’s not been tampered with
(remember, there are many mirrors from which you can download the Apache source), you should check the PGP
signature. If you don’t have PGP installed on this server, you can validate these files on another machine.
a) If you don’t already have them in your PGP keyring, import the public keys from the Apache Group into
your keyring:
…if the signature is correct, you should get something similar to this:
-- CUT --
File 'httpd-2.0.45.tar.gz.asc' has signature, but with no text.
Text is assumed to be in file 'httpd-2.0.45.tar.gz'.
Good signature from user "Justin R. Erenkrantz <justin@erenkrantz.com>".
Signature made 2003/03/31 07:49 GMT
WARNING: Because this public key is not certified with a trusted signature, it
is not known with high confidence that this public key actually belongs to:
"Justin R. Erenkrantz <justin@erenkrantz.com>".
The fact that it says, “Good Signature from…” is what we’re looking for here. The WARNING statement
indicates that we’ve not verified this signature with a 3rd party, which is ok here.
MD5 is a way to validate the integrity of the file itself, much more reliable than checksum and similar methods.
Normally, mismatches in the MD5 checksum from the Apache source are the result of download errors or file
corruption. If you don’t have MD5 on your system, you can download it from here.
Compare the results of these two commands – visually inspect them to ensure they match (if they don’t,
download it again):
~> pwd
/usr/local/build
~> /pwd
/usr/local/build
This will create a new directory under your current one, named “httpd-2.0.45”.
SSL support requires an SSL library on your system, such as OpenSSL. If you’re not sure how to find and install it,
look at the Apache 1.3 hardening guide. This section will walk you through configuring your SSL certificate for
encrypting your HTTP traffic. It will help you build a validated certificate and install it on your web server. We’ll
add the configured certificates to the Apache configuration in the next step.
3.1 Create a key and certificate request for your web server
Using OpenSSL, the following command will create a 1024-bit private key named, “private.key” and generate a
certificate signing request (CSR). You need to have the CSR signed by a Certificate Authority (CA) who can
validate your identity. When prompted to input information, note the answers in bold print below. (Answer the
prompts with the information relevant for your server, of course).
Note: If you provide a challenge password, you will be unable to start the web server unattended. We don’t
recommend providing a challenge password, just leave it blank.
~> pwd
/usr/local/build
Most importantly, make sure your “Common Name” above matches the DNS name of your server. The locale
information is less important, but we think it’s best to use the locality of the server itself.
Next, you need to submit your CSR for signing by a CA. This will eliminate the “warning dialog” that a browser will
pop up when a user accesses your site. This is because the user’s browser has a set of trusted CAs that will
prevent you from being notified if the web server’s site certificate is signed by a CA you’ve trusted in your browser
already (such as Verisign or DST). In this example, we will submit the request to your company’s CA for signing.
(You can use another CA if you want).
Send your request for a certificate to the CA. Include your name, your web server (Apache, in this case) your
OS, and of course, the .csr (certificate signing request).
The names aren’t important, they just have to match what’s in conf/ssl.conf. You will receive 2 files
from the PKI team. The first file will be your server certificate (and will probably be named <server
name>.cer), the 2nd file is the certificate chain. Here, we’ll rename them to fit what’s specified in
conf/ssl.conf.
Since you received these certs via email, and they’re now sitting on your laptop, we need to copy both
server.crt and ca.crt to the server. We’ll copy them up to /usr/local/build. We’ll move them
both to the appropriate locations under conf/ssl.conf later.
In this section, we’ll configure Apache with SSL and mod_ldap support. As of Apache V2, these are both included
modules, and don’t require a separate download.
In order to customize Apache to the extent necessary, we need to download the source for the latest version of
Apache. Once that’s complete, we’ll configure and test it.
We want to remove/modify the default HTTP response header parameter for the “Server:” token to hide the
identity of our web server. (You’d be surprised how many vulnerability scanners are looking for specific versions
of Apache.) To do this, we must open a header file (httpd.h) prior to compiling the server. To do this, edit
the ap_release.h file located in ${ApacheSrcDir}/include
~> pwd
/usr/local/build/httpd-2.0.45/include
~> vi ap_release.h
…
These are the lines you want to change; change these to remove references to Apache. We’ll hide the actual
version using the ServerTokens directive in the httpd.conf file.
Example:
There are a few standard modules that should be disabled when you set up the Apache web server.
Modules to disable
Generally, the following modules make it easier to configure/support your web server but also give too much
information to attackers. We recommend that you disable the following default modules for your production
server:
info: gives out too much information about your web server to potential attackers.
status: gives out server stats via web pages
autoindex: provides directory listings when no index.html file is present
imap: provides server-side mapping of index files
include: provides server-side includes (.shtml files)
userdir: translates URLs to user-specific directories
auth: you won’t need it – you’ll set up authentication against LDAP via mod_ldap
Modules to enable
Here are two modules that will provide strong authentication and encryption for your web server. If you have
any protected content on your web server, it’s important that you only allow your users to access it over SSL,
otherwise your user passwords will be sent in clear text, subject to snooping.
ssl: Encrypts the traffic from the browser to the web server – an important means of protecting login
passwords and sensitive data.
auth_ldap: Allows you to validate passwords against ldap.xianco.com or other LDAP.
centrally maintained LDAP. To authenticate against an LDAP store, you need to compile Apache with support.
In order to use mod_ldap, you’ll need LDAP libraries installed on your system. You can use OpenLDAP or
Netscape Directory SDK for the LDAP client libraries.
Configuration commands
Here’s how to configure Apache with these options:
~> pwd
/usr/local/build/httpd-2.0.45
Now that the software is validated and configured, it’s time to compile it. Since you won’t have a compiler on
your production host, we’ll compile and install it on a separate server, then tar/compress it and scp it to your
production host. You’ll need to run make using “sudo” so that Apache knows it can use ports < 1000.
~> pwd
/usr/local/build/httpd-2.0.45
Do not use the htdocs directory included in the distribution as your DocumentRoot. This directory contains user
documentation that you don't want to make available to the public as it contains information a potential
attacker could use to penetrate your system. (The attacker can deduce what kind of web server you’re running,
and hone his attack accordingly.) Move these documentation files into your support directory so the
webmasters for your site can refer to them as needed.
8 of 11
You’ll need to install the Apache server using “sudo” privileges or as root.
~> pwd
/usr/local/build/httpd-2.0.45
~> pwd
/opt/apache2/conf
5.2 Copy the certificate and key to the SSL configuration directory
Configure the file permissions and runtime settings of the Apache server. It’s important that you place your htdocs,
cgi-bin, and logs directories on separately mounted filesystems.
Set the following in your httpd.conf file. You can also download an example httpd.conf with these settings
here.
AllowOverride None
will prevent developers
from overriding these
specifications in other
parts of the doc tree.
AddIcon (remove) Remove all references
IndexOptions (remove) to these directives,
AddDescription (remove) since we disabled the
ReadmeName (remove) fancy indexing
HeaderName (remove) module.
IndexIgnore (remove)
Alias /manual (remove) Don’t provide any
accessible references
to the Apache manual,
it gives attackers
too much info about
your server.
10 of 11
You should familiarize yourself with the following parameters. Unless you are running a high-volume web site,
you can safely leave the settings at their default values. If you are running a high-volume web site, you’ll want
to adjust these directives upward to better withstand denial-of-service attacks.
StartServers
MinSpareServers
MaxSpareServers
Timeout
Keepalive
MaxKeepAliveRequests
KeepAliveTimeout
MaxClients
MaxRequestsPerChild
Set the following in your ssl.conf file. You can also download an example ssl.conf with these settings here.
It’s important to remove default files such as .html files and CGI scripts (yes, even the Apache manual). This will
help obfuscate the server you’re running, targetted attacks against your web server. You’ll probably want to build
a simple index.html page to place in the htdocs directory, just so you know the web server is working when you
start it.
To test that your web server is running, you can now place this file in your htdocs directory – it’s just a simple
index.html file. Make sure you set the permissions to world-readable.
To protect the directories on your server, it’s important that you protect the directories themselves.
bin is where the executable portion of the Apache web server is. It should be readable/executable only by
members of the webadmin group, but only writable by root.
conf is where your web server configuration files are and needs to be read/writable only by the webadmin
group.
logs is where your access and error logs will go. It should be readable only by the webadmin group.
htdocs is where your HTML files are and needs to be world readable, but writable only by root (you should
11 of 11
cgi-bin is where your executable scripts are and needs to be world read/executable, but writable only by
root (you should copy content in from a staging server).
7.1 Modify Apache startup script so that it will notify you when it’s restarted.
As a failsafe measure, you should notify your webmaster alias any time this server is restarted. That way, you’ll be
notified of any unauthorized attempt.
tail /opt/apache2/logs/error_log |
/bin/mail -s 'Apache web server has restarted' <hostname>-webmaster@xianco.com
Check web sites for Apache and all modules regularly and apply important patches.
OpenSSL: http://www.openssl.org/source
OpenLDAP: http://www.openldap.org/
In this final section, we’ll configure the Apache httpd.conf file so that resources are authenticated against an LDAP
server. This step really can’t be run until you’ve installed the web server. Once you’ve got your web server installed,
just add the LDAP authentication directives to any directory (or httpd.conf file) where you want password protection
with CEC credentials. Here’s an example of protecting a directory named “Internal”
<Location "/internal">
AuthName CEC
AuthType Basic
AuthLDAPURL ldap://ldap.xianco.com:389/ou=employees,ou=people,o=xianco.com?uid?sub?
(objectclass=xiancoPerson)
require valid-user
</Location>