New users guide to securing an Apache Web Server

Last updated 05/06/03 Copyrighted 2003 flw/Dan, Jason Lambert

Why use Apache Web Server 2.x instead of 1.3? See http://httpd.apache.org/docs-2.0/new_features_2_0.html If you don’t need the new features then there is no strong reason to use 2.x except any new features in the future will be in the 2.x version and not the 1.3.27 version.

This guide is intended for new users of Apache Web Server and how to take some security steps to make it harder (or slow down) for hackers to deface your hard work. It is also based on RedHat version 7.x for default file location purposes only. Your file locations and names may vary. We also are assuming you are logged in as root or logged in with the root privileges. If you’re not sure, then from the command line type in “whoami” and press enter. The steps below are not in any priority order and you don’t have to implement all of them but every step in insuring your web servers security makes it that much harder to break in.

Step 1. Always use the most current version. If your using 1.3.26 then upgrade to 1.3.27 and the same for Version 2.44 upgrade to 2.45 which are the current versions as of this writing. It very easy for people to find out weaknesses in older version because they are listed at public locations like http://www.apacheweek.com/features/security-13 or here http://www.apacheweek.com/features/security-20 . To upgrade, copy all your web html/cgi etc… files and graphics to a temporary directory which will include a copy of the current httpd.conf and .htaccess if used. Then follow the directions for the install and copy back all your web site content and httpd.conf and .htaccess if used. Reboot your computer. Remember this is only a simplistic example.

Step 1a. Where do I get the upgrade? You can get the current versions of 1.3.27 and 2.4.x at http://httpd.apache.org/

Step 2. My opinion only, always used the current version of your Linux distribution. An example is if you’re using Redhat 7.0 then upgrade to 7.2. I don’t recommend upgrading from your 7.2 to major release like 8.0 or a 9.0 until the versions has been on the market long enough for Redhat to come out with a minor 9.1 release. There are always lots of bugs in the initial versions. To upgrade from one version of Redhat to another you'll have to choose “upgrade” to Red Hat Linux 7.2 (instead of performing a full installation). You must choose “Upgrade”.

Step 3. Change your document root (main page or starting page on your web site like /home/mywebsite, if it doesn’t exist you have to go to the cmd line and type mkdir /home/mywebsite) to a non-default location by editing the httpd conf file. You’ll be looking for “documentroot”. Feel free to use whatever text editor you prefer (VI, EMACS, etc…). In Redhat 7.0 it is in /var/www/html, in older versions it may be in /home/httpd/html or /usr/local/Apache/htdocs. If you still can’t find it, try from the command line at the / directory by using the following:

“find –name httpd.conf”

You’ll also want to check for obvious errors that Apache Web Server see’s. So from the command line use “apachectl configtest “ and any syntax errors will be reported.

Step 4. Verify and if needed correct all your files for viewing only. They should be set as read only by Apache Web Server.

Step 5. Verify only files or graphics that are used or viewed at your site are the only files in your web directories. I.e. don’t put password files or your configuration notes in the same directory as index.html or where your graphics are.

Step 6. Any temporary files created by content generators like cgi scripts be located in a single directory where they have “write” access outside your content area to protect a script from deleting your web content.

Step 7. Create visible and imbedded copyright notices. Imbedded notices should be toward the top of the web page so it is very visible. You’ll want to edit any original graphics with the same copyright notice.

Step 8. Disable directory view from displaying your web page as a view only file manager. This is done from httpd.conf. You can just comment out the “directory view” by using the # symbol.

Step 9. This is for cgi only so if your not using cgi skip ahead. CGI is a how to all by itself. So for here I’m only going to list the commonly known issue you should be aware of and look into.

User input crashes the cgi app.
User input creates system calls that are unsafe.
User sees hidden data.
User input causes denial of service (DOS). A good practice is to limit how much memory and CPU usage Apache Web Server web gets to use. This is in case you are under a DOS that you still have some memory and cpu power to start a session with the server and kill the problem process or user connection.

The commands you would use within httpd.conf to limit a DOS are “<Limit RLimitCPU > </Limit>” and “RLimitMEM”. RLimitCPU

RLimitCPU
Syntax: RLimitCPU n|max [n|max]
RLimitCPU sets the CPU resource limit for all server processes. It can have one or two values, and the values are either n or "max," where n is seconds per process "max" is the maximum resource limit allowed by the operating system. Whether this directive is given one value or two, the first value is always the soft resource limit. If there are two values, the second is the hard resource limit.

RLimitMEM
Syntax: RLimitMEM n|max [n|max]
RLimitMEM sets the memory resource limit for all server processes. It can have one or two values, and the values are either n or "max," where
n is bytes per process "max" is the maximum resource limits allowed by the operating system Whether you give this directive one value or two, the first value is always the soft resource limit. If there are two values, the second is the hard resource limit. User input gets posted to the web site.

Note: you can reduce the risks involved by the use of a cgi wrappers which runs the cgi as the user that owns the file rather than as the Apache Web Server user. Some cgi wrappers will do additional security checks as well.

Step 10. This is really just for fun. Change the authentication error message to get a unauthorized user thinking if he should really continue or not. Put the following code inside the htttpd.conf:

ErrorDocument 401 “Your message goes here”.

You can create a special page like “While you were busy trying to get into my server, I was busy tracking your ip to your ISP. “Just so you are aware, after three failed attempts to authenticate successfully, my server forwards your information with the details to your ISP under the ‘violation of the terms of service agreement’ you opted in for to get your service. Good luck and have a nice day :>”

The key to the above is they really don’t know if it true or not and will steer some away. Security is not always locks and keys. Sometimes it’s the fear of the unknown.

Step 11. Do not use Java Script or ASP to secure your web site. There are many weaknesses to these methods are not recommended. Use basic authentication instead that is part of Apache Web Server.

Step 12. If you want to require user authentication for your whole site or just a section of there are several things that must be done and if one is not right it will fail. All of the following is from the command line and assumes your logged in a root or a user with root privileges.

a. Use .htpasswd to create a username and password for each user or one for a group of people to use.

At the cmd line type: “htpasswd -c /usr/local/etc/httpd/.htpasswd martin”.

The -c argument tells htpasswd to create new .htpasswd file. When you run this command, you will be prompted to enter a password for martin, and confirm it by entering it again. Other users can be added to the existing file in the same way, except that the -c argument is not needed. The same command can also be used to modify the password of an existing user.
After adding a few users, the /usr/local/etc/.htpasswd file might look like this:

martin:WrU808BHQai36
jane:iABCQFQs40E8M
accounting:FAdHN3W753sSU

The first field is the username, and the second field is the encrypted or hashed password.

The .htpasswd file goes into the same directory as the httpd.conf file. Such as etc/httpd/conf/.htpasswd

b. To get the server to use the usernames and passwords in this file, you need to configure a realm. This is a section of your site that is to be restricted to some or all of the users listed in this file. This is typically done on a per-directory basis, with a directory (and all its subdirectories) being protected (Apache Web Server 1.2 and later also let you protect individual files). The directives to create the protected area can be placed in a httpd.conf file.

To allow a directory to be restricted within another directory you first need to ensure that the httpd.conf file allows user authentication to be set up in a .htaccess file. This is controlled by the AuthConfig override. The httpd.conf file should include AllowOverride AuthConfig to allow the authentication directives to be used in a .htaccess file.

c. To restrict a directory to any user listed in the users file just created (.htaccess), you should create a .htaccess file containing:
(The .htaccess file goes into the target dir unless changed in the httpd.conf file)

Such as /home/httpd/html/.htaccess
authname "mycompany’s secured site"
authtype basic
authuserfile /etc/httpd/conf/.htpasswd
require valid-user

Since all web content in located in /home/mywebsite all configuration and Apache Web Server application files are located outside of your sites directory and as only as secure as you Linux machine is. This is a tutorial by itself.

The first directive, AuthName, specifies a realm name for this protection. Once a user has entered a valid username and password, any other resources within the same realm name can be accessed with the same username and password. This can be used to create two areas, which share the same username and password.

The AuthType directive tells the server what protocol is to be used for authentication. At the moment, Basic is the simplest method available but also transmits username and passwords in clear text which is its security weakness.
AuthUserFile tells the server the location of the user file created by htpasswd. A similar directive, AuthGroupFile, can be used to tell the server the location of a groups file (see below).

These four directives have between them tell the server where to find the usernames and passwords and what authentication protocol to use. The server now knows that this resource is restricted to valid users. The final stage is to tell the server which usernames from the file are valid for particular access methods. This is done with the require directive. In this example, the argument valid-user tells the server that any username in the users file can be used. But it could be configured to allow only certain users in:

“require user martin jane” would only allow users martin and jane access (after they entered a correct password). If user art (or any other user) tried to access this directory, even with the correct password, they would be denied. This is useful to restrict different areas of your server to different people with the same users file. If a user is allowed to access the different areas, they only have to remember a single password.

Note that if the realm name differs in the different areas, the user will have to re-enter their password.

Step 13. Disguise or limit the information Apache “server” header gives out
When a HTTP request is sent to a webserver, the server will respond with any necessary page content, and also, depending on how the server is configured, it will provide some information about the type of server software being used. For example, what I have typed appears in bold:

jason@london:~$ telnet www.example.com 80
Trying x.x.x.x...
Connected to www.example.com.
Escape character is '^]'.
GET /filethatdoesnotexist HTTP/1.0
HOST: www.example.com

HTTP/1.1 404 Not Found
Date: Sun, 04 May 2003 15:22:53 GMT
Server: Apache/1.3.19 (Unix) FrontPage/4.0.4.3 mod_ssl/2.8.2 OpenSSL/0.9.6g Auth
MySQL/2.20
Connection: close
Content-Type: text/html; charset=iso-8859-1

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<HTML><HEAD>
<TITLE>404 Not Found</TITLE>
</HEAD><BODY>
<H1>Not Found</H1>
The requested URL /filethatdoesnotexist was not found on this server.


<HR>
<ADDRESS>Apache/1.3.19 Server at www.example.com Port 80</ADDRESS>
</BODY></HTML>
Connection closed by foreign host.
jason@london:~$

If you look closely, you can see the server has passed back some vital information about itself in the line:

Server: Apache/1.3.19 (Unix) FrontPage/4.0.4.3 mod_ssl/2.8.2 OpenSSL/0.9.6g Auth MySQL/2.20

We can see that the server is Apache, Version 1.3.19, running on a UNIX system. We can also see modules that are loaded into the server, for example Frontpage and mod_ssl. With this information an attacker can begin attacking your system, with precision.

So… How do you stop this information being divulged?

There are 2 ways, the first, ideal if you are not really comfortable with editing the Apache source, then you can use “ServerTokens” to control what level of information is sent to the client with a HTTP response. Beware that some applications can still give away free information like phpbb , mysql, ssh that Apache cannot stop. You would need to fine tune these apps or use a firewall for that.

To use server tokens, you need to edit your httpd.conf file, and, firstly see if you already have a line/section called ServerTokens. If not, you can add it. A ServerTokens directive for the server we looked at earlier will probably look like:

ServerTokens Full

If a server tokens line is not specified, it will Apache will default to “Full” setting. Depending on what you set “ServerTokens” to, will control how much information revealed. Some newer versions of Apache come in "Prod" configuration by default, you need to check and see how your httpd.conf file is setup. Here is a quick table of the settings you can use, and the response that will be shown to the client:

ServerTokens Prod
Server sends (e.g.): Server: Apache

ServerTokens Min
Server sends (e.g.): Server: Apache/1.3.0

ServerTokens OS
Server sends (e.g.): Server: Apache/1.3.0 (Unix)

ServerTokens Full
Server sends (e.g.): Server: Apache/1.3.0 (Unix) PHP/3.0 MyMod/1.2

Don’t forget, after changing your httpd.conf file to restart apache for the settings to take effect.

If you want to go to extremes, then the 2nd method is for you. What we will attempt to do is to change the Server header to impersonate a Microsoft IIS server, ie, so instead of server: apache, we now display: “Server: Microsoft-IIS/5.0”.

To make this change you will need to re-compile your apache server. At this stage, make a backup of your httpd.conf, and all of your webpages and graphics.

Download the apache source tarball from httpd.apache.org and unpack, then change to the directory that you unzipped to.

For version 1.3.27, open the file src/include/httpd.h (2.x users, edit include/ap_release.h), and change these lines:
#define SERVER_BASEPRODUCT “Apache”
#define SERVER_BASEREVISION “1.3.27”

to:

#define SERVER_BASEPRODUCT “Microsoft-IIS”
#define SERVER_BASEREVISION “5.0”

Then proceed to recompile apache, and test.

For further questions on web server security see: http://www.w3.org/Security/Faq/
http://httpd.apache.org/docs-2.0/mis...rity_tips.html
http://httpd.apache.org/docs/misc/security_tips.html

Please email any errors or omissions to fastlanwan@yahoo.com

Credits:
Lead Author: fastlanwan
Co-Author: Jason Lambert

Copyright 2003 fastlanwan, Jason Lambert
Unauthorized reproduction is strictly prohibited