SANS GIAC - GCUX Practical Assignment

Ryan C. Barnett

Securing Apache: Step By Step

  1. Introduction
  2. Harden the OS Platform
  3. Create the Web Server Group/User
    1. Create Groups for Web Server Content
    2. Create a Specific User for Web Server
    3. Create Quota for Web User
    4. Verify Quota
    5. Lock Down the New Account
  4. Download the Appropriate Apache Distribution
    1. Download the Apache Source
    2. Verify the PGP Signatures
    3. Verify the MD5 Checksums
  5. Apply Latest Web Server Patches
  6. Configure/Compile/Install the Apache Distribution
    1. Configure the Apache Distribution
    2. Edit the httpd.h File
    3. Compile Apache
    4. Install the Software
  7. Edit the Apache Configuration file – httpd.conf
    1. Basic Web Server Settings
      1. ServerType
      2. HostnameLookups
      3. User & Group
      4. Port
      5. ServerAdmin
      6. ServerRoot
      7. ServerName
    2. Security Related Settings
      1. LogLevel
      2. ErrorLog
      3. CustomLog
      4. <Directory>
      5. Options
        1. AllowOverride
        2. IncludesNoExec
        3. SymLinksIfOwnerMatch
      6. Order and Allow/Deny from (Use IP)
      7. ServerSignature
      8. ServerTokens
      9. CoreDumpDirectory
      10. Error Responses
        1. 401/403 Errors
        2. Other Status Codes
      11. LimitExcept
    3. Access Control
      1. Restrict Acces to File or Directory
    4. Common Attack Signatures
      1. Mod_Rewrite Voodoo
      2. Robots
    5. CGI Bin Mischief
      1. Review CGI Files/Code
      2. Fake CGIs
        1. Foil Vulnerability Scanners
        2. Fake PHF
      3. <DirectoryMatch>
      4. <FilesMatch>
    6. Denial of Service
      1. Timeout
      2. KeepAlive
      3. KeepAliveTimeout
      4. StartServers
      5. MinSpareServers/MaxSpareServers
    7. Buffer Overflows
      1. LimitRequestBody
      2. LimitRequestFields
      3. LimitRequestFieldsize
      4. LimitRequestLine
  8. Change Ownership/Permissions on Directories and Files
    1. Server Configuration Directories
    2. Document Root Directory
    3. CGI-Bin Directory
    4. Log Files
    5. Bin Directory
  9. Clean Out Unneeded Files and Directories
    1. Src Directory
    2. Default HTML Documents
  10. Update Apache Start Script for Notification
  11. Advanced Settings - Miscellaneous Security Enhancements
    1. Worms At War
    2. Swatch
    3. Monitor Changes in Web Content
    4. Secure Index Pages
      1. Change the Default Index Page Setting
      2. Prevent Invalid Pages from Being Served
    5. Chroot
    6. Secure Socket Layer (SSL)
  12. Appendix
    1. Example httpd.conf file
    2. CGI Alert Scripts
      1. 401/403/500
      2. Robot Script
      3. Fake CGI Template
      4. Fake PHF
      5. WormTrap
    3. SWATCH Config File
    4. Index_Check Script
    5. Chroot Script
  13. References

  1. Introduction

  2. This document defines security configuration standards for the Apache 1.3.xx versions of web server, since it has the predominant market share over the new Apache 2 platform.  There will be a future release of a document which will cover the security benchmarks of the 2.0 versions due to a number of  dramatic changes to the overall API structure.  At the time of this document, Apache V.1.3.24 is the current stable version.  The platform used for the examples in this document is a Solaris 8 operating system with the Apache 1.3.24 version installed.

    This defines settings which are designed primarily to enhance the security of the webserver itself.  They may not apply in all situations. It is left to the discretion of the reader to determine the relevance of each setting as it applies to their web environment.  The settings listed in this document are recommended with a "security first" mindset.  It is that age-old battle of "Security vs. Functionality."  The resulting web server would be adequate for serving mostly static web content.  If you decide not to implement, and or, change any of these settings please read the documentation available on the Apache web site so that you are fully aware of the related security risks.

    Many of the defensive Discussion sections are referenced from my previous SANS GIAC GSEC practical paper entitled - "Preventing Web Site Defacements."  That paper focuses on defacements in general and is not application specific to any web server.  This practical assignment builds upon the security issues discussed in my defacements paper and tailors it specifically to the Apache web server.  If you would like to read more about web site defacements, please read my paper at the URL in the Reference section.

  3. Harden the OS Platform

  4. Action: (Solaris, Linux, Windows systems):

    Operating System Security is beyond the scope if this document, however, this step should not be ignored.  The undeniable symbiotic relationship between a Web server and its underlying OS cannot be overstated.  Both the Web server and the OS could potentially be used to exploit each other.  For instance, a vulnerable version of the BIND daemon could potentially give an attacker command line access to the system.  This unauthorized access could put the web site’s contents into jeopardy.  Conversely, a web server running a vulnerable version of the CGI script PHF could allow an intruder to illegally access the OS password file.  This information might eventually lead to unauthorized system access.  Addressing the security concerns of a Web server and ignoring the system OS is akin to locking the front door of a house while leaving the backdoor wide open.  Therefore, it is imperative to harden the OS to truly prevent web site intrusions.  A perfect example of failing to address this issue and how it could leave a system vulnerable to attack is explained in the following news story from Wired Magazine:  Hackers Win Security Challenge (A)

  1. Create the Web Server User/Group
    1. Action: Create Groups for the Web Server Content

    2. Execute the following commands to create the appropriate web groups:
      # groupadd webadmin
      # groupadd webdev
      # groupadd webserv
In order to segment duties and associate real users with web content, we want to create these new group accounts.  The account names will vary depending on your environment.  The goal is to create specific groups that serve certain functions: for example, the webadmin group would own and maintain the web servers configuration documents located in the /path/to/apache/conf, /bin and /logs directories.  The webdev group would own and maintain all of the actual web document root files within the /path/to/apache/htdocs directory.  The webserv group is only used as the group association that the webserv user has.  We do not want the webserv user to be a member of the users group.  We will discuss how to modify the ownership and permissions on directories and files in a later section.
    1. Action: Create a Specific User for the Web Server

    2. Execute the following commands (Solaris):
      # useradd –d “/path/to/apache/root/htdocs” –g webserv –c “Web Server” –m webserv
The best way to reduce your exposure to attack when running a web server is to create a unique unprivileged userid and group for the server application. The “nobody” userid & group that come default on Unix variants should NOT be used to run the web server.   The “nobody” account was originally introduced as a means to map the “root” account over NFS.  Due to the underlying association between the “nobody” and “root” accounts, it is best to create new accounts for the sole purpose of running the web server.
By default the web server uses a privileged port (port 80) and, when configured for secure operation, must have root privileges to open its log files and start the dæmon. Once the server’s startup tasks are complete, all active instances can run as the unprivileged user. (A)  Create an account with a name such as: webserv, which runs the web server software.  In the entry above, we designate the web document root as the webserv user's home directory.  Since this account will never be used to log into for shell access, we do not need to create the normal user account login files.
  1. Action: Create a Quota for the New Account

  2. Execute the following commands:
    # df –k
    Filesystem             eferr    used   avail capacity  Mounted on
    /dev/dsk/c0t0d0s0    6191949 5303753  826277    87%    /
    /proc                      0       0       0     0%    /proc
    fd                         0       0       0     0%    /dev/fd
    mnttab                     0       0       0     0%    /etc/mnttab
    swap                 1659688       8 1659680     1%    /var/run
    swap                 1660384     704 1659680     1%    /tmp
    /dev/dsk/c0t0d0s3    7995933  232001 7683973     3%    /space
    # touch /space/quotas
    # edquota webserv

    Within the vi session – change the settings to these:
    "/tmp/EdP.ai3aOSH" 2 lines, 127 characters
    fs /space blocks (soft = 0, hard = 0) inodes (soft = 0, hard = 0)
    fs / blocks (soft = 0, hard = 1) inodes (soft = 0, hard = 1)

    Execute more commands:
    # quotaon –v /space
    /space: quotas turned on
    # touch test /space/apache/
    # chown webserv /space/apache/test
    # repquota –v /space
    /dev/dsk/c0t0d0s3 (/space):
                          Block limits                      File limits
    User           used   soft   hard    timeleft    used   soft   hard    timeleft
    webserv   --      1      0      1                   1      0      1

    The goal of these commands are to apply a disk quota to the new system account “webserv” which will be the userid that the Apache web server runs as.  By placing a restrictive quota that will not allow the webserv user to create ANY new files on the partition which the web server document root resides, we can defend against many of the typical methods attackers use to deface a web site.  This technique would deter attacks where the web server is tricked by an insecure CGI script into executing a command such as: “/bin/echo ‘You’ve been 0wned!!!’ > /space/apache/webdocs/index.htm”.

    Important- When editing the quota for the user with the edquota utility, take care!  The fields in the edquota edit session are as follows:

      fs mount_point blocks (soft  =number,  hard  =number  )  inodes (soft =number, hard =number)
                Where a block is considered to  be  a  1024  byte  (1K) block.

    It is easy to incorrectly implement the desired effect.  Our goal is to disallow any new files to be created or owned by the webserv user.  With this thinking, one would guess that we would want the hard limits for both blocks and inodes set to 0, right?  Wrong.  Setting a quota to 0 disables that quota.  This is why we set the hard limits to 1.  We then executed the touch command to create a file for the webserv user within the /space partition.  The webserv user’s quota is now reached.  The use of the quota settings should be evaluated by each organization.  This setup may not work appropriately if the Apache web server uses more interactive application add-ons which need to create files such as PHP, MySQL, etc…

    1. Action: Verify Quota

    2. Execute the following commands to verify the quota for the new account:
      # su – webserv
      Block limit reached on /space
      File count limit reached on /space

      $ id
      uid=102(webserv) gid=1(other)
      $ touch test2 /space/apache/
      quota_ufs: over file hard limit (pid 15849, uid 102, fs /space)
      touch: test2 cannot create

Now that we have set a hard quota for the webserv account, we must test the setting.  We need to su to the webserv user to test.  Notice the status message above when we log into this account.  The system lets us know that we have reached our limit for the /space partition immediately upon entering our shell.  We then try and create a new file in the /space/apache directory and we are denied with the status message above saying that creating this file would put us over the hard quota limit.
    1. Action: Lock Down the New Account

    2. Execute the following commands to lock down the new web account –
      # passwd –l username
      # usermod –s /bin/false username
In the example above, username, is equal to the name of the web user account you created.  This would have been webserv if you used the same name as in step 2.1 above.  To make sure the user account you created cannot be logged into, you want to lock this new account by using the passwd command above.   This will lock the account within the /etc/shadow file by replacing the encrypted password hash with the locked letters.  The encrypted password field should contain the entry LK indicating that the account is locked and cannot be used to log in.   Additionally, by using the usermod command above, you are changing the default system shell for the new user to a non-valid shell.  After updating the user account to specify this non-valid shell, the password file entry should look similar to the following example:
# grep webserv /etc/shadow
# grep webserv /etc/passwd
webserv:x:102:1:Web Server:/path/to/apache/webdocs:/bin/false
  1. Download the Desired Apache Distribution

    1. Action: Download the Apache Source
Due to the fact the Apache 2.0 versions are still in BETA release and that the vast majority of Apache users are using version 1.3.XX, we will be focusing on this particular release.  In addition, we will want to download the uncompiled version.   There are numerous compiled binaries for various platforms located at <>.  While these versions do help with the ease of installation, they do not allow for some of the security changes that we will make before we compile the Apache source code.

Checking both the PGP keys and the MD5 checksum of the Apache distribution is vital to ensuring that the code you have downloaded has come from the specified Apache distribution sites.  The URLs listed above are the official locations of approved Apache distributions.  This is the location that you should obtain the Apache source files from.  This will ensure that you are getting a approved copy, whose source code can be verified by the Apache group member’s PGP keys and MD5 checksums.

    1. Action: Verify the PGP Signatures

    2. Execute the following commands to verify the PGP keys for your version:
      # pgp –ka KEYS
      # pgp apache_1.3.24.tar.gz.asc
These commands will import the public keys from the KEYS file into your local pgp keyring.  You then run pgp against the apache_1.3.24.tar.gz.asc to verify the signature against a key on your keyring.  If no match is found, you should double check that you downloaded either the correct apache distribution or the correct pgp file for that distribution.  If you do not have PGP currently available on your systems, you can download the freeware version from the web site.
    1. Action: Verify the MD5 Checksums

    2. Execute the following commands to verify the MD5 checksum of the Apache source archive:
      # cat apache_1.3.24.tar.gz.md5
      MD5 (apache_1.3.24.tar.gz) = ebea6588c3954731fcc318d29bc82409
      # md5 apache_1.3.24.tar.gz
      MD5 (apache_1.3.24.tar.gz) = ebea6588c3954731fcc318d29bc82409
The MD5 utility is a hashing function that will calculate as input a message of arbitrary length and produces as output a 128-bit “fingerprint” or “message digest” of the input. It is conjectured that it is computationally infeasible to produce two messages having the same message digest, or to produce any message having a given prespecified target message digest. The MD5 algorithm is intended for digital signature applications, where a large file must be “compressed” in a secure manner before being encrypted with a private (secret) key under a public-key cryptosystem such as RSA.  In essence, MD5 is a way to verify data integrity, and is much more reliable than checksum and many other commonly used methods.  If you run MD5 against the Apache source you downloaded and the resulting hash number does not match the MD5 check file, then you should download the entire distribution again.  These mismatches can be caused by such things as, looking at wrong MD5 file, modified source code and errors in the downloading process.  If you do not have MD5 on your system, you can download it from the following location –
  1. Apply the Latest Web Server Patches

  2. Follow these steps to check for patches:
One of the most frustrating aspects of web attacks is that most can be prevented if the appropriate patches are applied.  Both OS and web server vendors are constantly issuing patches in response to flaws found within their application’s code.  These patches fix diverse problems, including security issues, and are created from both in-house testing and user-community feedback.  Keeping abreast of new patches can be a daunting task to say the least.  Monitoring the vendor site, downloading the appropriate patch cluster, and then installing it on the specified systems are all steps that must be completed. (A)  The patch steps above will ensure that your apache source is up to date with the most current fixes available.
  1. Configure/Compile/Install the Apache Source

    1. Action: Configure the Apache Distribution

    2. Follow these steps to unpack and configure the Apache source:
    We will be changing some of the default parameters from above to specify which modules that we want to compile into the httpd executable that we are creating.  It is a good idea to confirm your sites need for each module.  An important feature to remember is that the fewer modules that are included, the smaller the compiled Apache binary is and the faster it will be.  Additionally, just because you “enable” these module and compile then into the Apache binary, these modules are not actually used until you specify some parameters within the httpd.conf file. These are the modules that we recommend due to some of the security settings that we may implement.  Let's take a closer look at some of the module we listed above and present the rationale for either enabling or disabling the module.
  1. Action: Edit the httpd.h File

  2. Execute the following commands:
    # pwd
    # ls –l httpd.h
    -rw-r—r--   1 root     other      45430 Oct  8 23:56 httpd.h
    # cp httpd.h httpd.h.orig
    # ls –l httpd.*
    -rw-r—r--   1 root     other      45430 Oct  8 23:56 httpd.h
    -rw-r—r--   1 root     other      45430 Jan 22 15:35 httpd.h.orig
    # grep BASE httpd.h
    #define SERVER_BASEVENDOR   “Apache Group”
    #define SERVER_BASEPRODUCT  “Apache”
    #define SERVER_BASEREVISION “1.3.24”
      #define SERVER_BASEPRODUCT  “Apache”
      #define SERVER_BASEREVISION “1.3.24”
    We want to remove/modify the default HTTP Response Header parameter for the “Server:” token.  This change will aid in hiding the webserver software that we are using.  In order to exploit any potential weaknesses of a web server, an attacker must first identify the target’s web server software. This can be accomplished by a number of methods.  By connecting to port 80 on the target host using either telnet or netcat, an attacker can issue an HTTP “HEAD” request to identify the web server software from the response header. In the example connection below, the bolded line shows that this host is using Netscape-Enterprise/3.5.1. With this information, an attacker can search various hacker sites for any known vulnerabilities or exploits for this version of web server software. (A)
> telnet 80
    Connected to targethost.
    Escape character is ‘^]’.
    HEAD / HTTP/1.0
    HTTP/1.1 200 OK
    Server: Netscape-Enterprise/3.5.1
    Date: Sat, 28 Apr 2001 18:43:52 GMT
    Content-type: text/html
    Content-length: 207
    Connection: close
    Connection closed by foreign host.

    It is possible to edit out and/or alter (for deception purposes) the “Server” field information displayed by a web server’s response headers. In order to accomplish this task, the web server configuration file that contains the server version information must be edited. We will therefore edit the web server information of the Apache web server’s httpd.h file.

    IMPORTANT – Consult your legal department for verification of legal issues involved with changing your web server HTTP Response Header info.  Private Sector and Government Agencies have different standards concerning public release of information.  It has been debated in legal circles if altering this parameter constitutes “Lying” to the public about which web server software you are using.  You should refer to the Request for Comment (RFC #2616) for HTTP 1.1 protocol and read the following section concerning the SERVER header info (Note the Bolded Section)-
    14.38 Server
    The Server response-header field contains information about the software used by the origin server to handle the request. The field can contain multiple product tokens (section 3.8) and comments identifying the server and any significant subproducts. The product tokens are listed in order of their significance for identifying the application.

           Server         = "Server" ":" 1*( product | comment )


           Server: CERN/3.0 libwww/2.17

    If the response is being forwarded through a proxy, the proxy application MUST NOT modify the Server response-header. Instead, it SHOULD include a Via field (as described in section 14.45).

          Note: Revealing the specific software version of the server might
          allow the server machine to become more vulnerable to attacks
          against software that is known to contain security holes. Server
          implementors are encouraged to make this field a configurable

    The full RFC 2616 document is located at the World Wide Web Consortium web site.  Legal Counsel will want to justify the security vulnerability associated with not altering this information.  Most Legal departments should approve this security measure as “Mis-Information” to protect web assets.  You can pick the name of any web server software.  If you need to have examples of how the various web servers issue their Server Banner, then go to Netcraft for some examples. (A)

  3. Action: Compile the Apache Distribution

  4. Run the following command to compile the Apache httpd binary:
    # make
    ===> src
    make[1]: Entering directory `/admin/apache_1.3.24'
    make[2]: Entering directory `/admin/apache_1.3.24/src'
    ===> src/os/unix
    gcc -c  -I../../os/unix -I../../include   -DSOLARIS2=280 -DDEV_RANDOM=/dev/random -DUSE_EXPAT -I../../lib/expat-lite -DNO_DL_NEEDED `../../apaci` os.c
    gcc -c  -I../../os/unix -I../../include   -DSOLARIS2=280 -DDEV_RANDOM=/dev/random -DUSE_EXPAT -I../../lib/expat-lite -DNO_DL_NEEDED `../../apaci` os-inline.c

    This step will compile the Apache source and create the resulting httpd binary file.  Common problems associated with compiling the source code are having an incorrect compiler and having an incorrect PATH variable set.  If you run into problems, refer to the INSTALL document in the Apache source directory.

  5. Action: Install the Software

  6. Execute the following command to install the newly compiled software:
    # make install
    make[1]: Entering directory `/admin/apache_1.3.22'
    ===> [mktree: Creating Apache installation tree]
    ./src/helpers/ /usr/local/apache/bin
    ./src/helpers/ /usr/local/apache/bin
    ./src/helpers/ /usr/local/apache/libexec
    ./src/helpers/ /usr/local/apache/man/man1
    ./src/helpers/ /usr/local/apache/man/man8
    ./src/helpers/ /usr/local/apache/conf
You should see the following message upon successful compilation -
| You now have successfully built and installed the      |
| Apache 1.3 HTTP server. To verify that Apache actually |
| works correctly you now should first check the         |
| (initially created or preserved) configuration files   |
|                                                        |
|   /usr/local/apache/conf/httpd.conf
|                                                        |
| and then you should be able to immediately fire up     |
| Apache the first time by running:                      |
|                                                        |
|   /usr/local/apache/bin/apachectl start
|                                                        |
| Thanks for using Apache.       The Apache Group        |
|                        |
By running the “make install” command, you will be copying all of the newly compiled software, files and directories into the locations that were specified within the config.layout file.  After successfully installing executing this step, it is possible to start up the apache web server.  We will not do this at this point however, since we will be changing many configurations to tighten security.
  1. Edit the Apache Configuration File - httpd.conf

  2. Unfortunately, most web server's default system settings are not adequate for deployment on today's Internet.  Usually these default settings are configured with a much too open mindset.  In actuality, the exact opposite of the aforementioned statement should be the standard.  This is known as the "Principal of least Privilege."  Access controls should start off with total restriction and then access rights should be applied appropriately.  If a production web server is bound for the Internet, various web server system settings need to be changed and/or implemented. (A)
    1. Basic Web Server Settings
      1. Action: ServerType

      2. Execute the following commands to edit the /path/to/apache/conf/httpd.conf file:
        # cd /path/to/apache/conf
        # vi httpd.conf

        While within the vi session, you will want to find the entry for specifying the ServerType.  Change this entry to the following:
        # ServerType is either inetd, or standalone.  Inetd mode is only
        # supported on Unix platforms.
        ServerType standalone

        We select the standalone type of web server since it is more efficient.   Running the Apache web server through inetd is no longer supported, although you have this option.  You should only select inetd mode if you have very limited traffic.

      3. Action: HostnameLookups

      4. Edit the HostnameLookups parameter within the httpd.conf file:
        # HostnameLookups: Log the names of clients or just their IP addresses
        # e.g., (on) or (off).
        # The default is off because it'd be overall better for the net if
        # people had to knowingly turn this feature on, since enabling it means
        # that each client request will result in AT LEAST one lookup request
        # to the nameserver.
        HostnameLookups on

        The HostnameLookups directive tells Apache to do a DNS query to verify the hostname of a requesting client’s IP address.  This information is then passed to any Access Control Lists or  CGI programs and then finally logged in the appropriate line of either the access_log or error_log files.  This feature is useful when checking log files for notorious domain names.  You should investigate further if you are receiving numerous connections from sites such as: and  These sites are normally used to conduct remote reconnaissance against web sites.  While the HostnameLookups feature is useful to the Security Administrator for identifying suspicious originating connections, it unfortunately takes longer to finish serving the request.  Sites with high traffic should consider turning this setting to “off”.

      5. Action: User & Group

      6. Edit the User & Group parameters within the httpd.conf file:
        # If you wish httpd to run as a different user or group, you must run
        # httpd as root initially and it will switch.
        # User/Group: The name (or #number) of the user/group to run httpd as.
        #  . On SCO (ODT 3) use "User nouser" and "Group nogroup".
        #  . On HPUX you may not be able to use shared memory as nobody, and
        # the suggested workaround is to create a user www and use that user.
        #  NOTE that some kernels refuse to setgid(Group) or semctl(IPC_SET)
        #  when the value of (unsigned)Group is above 60000;
        #  don't use Group "#-1" on these systems!
        User webserv
        Group webserv
        When a web server is first started, it operates with the privileges of a specified OS user.  All of the child processes that the web server then spawns will run with the privileges of this system user.  Attackers often scan various web servers searching for one running as the "root" system user. Nmap is a popular network scanning tool used to port scan systems.  Nmap has a runtime flag (-I ) that will query a server for the application owner, which is shown bolded in the following display.
          # nmap -sT -p 80 -I -O
          Starting nmap V. 2.12 by Fyodor ([email protected],
          Interesting ports on (
          Port    State       Protocol       Service       Owner
          80      open           tcp          http         root

          TCP Sequence Prediction: Class=random positive increments
                                   Difficulty=1140492 (Good luck!)
          Remote operating system guess: Linux 2.1.122 - 2.1.132; 2.2.0-pre1 - 2.2.2

          Nmap run completed -- 1 IP address (1 host up) scanned in 1 second

        Therefore, do not specify root as the User within the httpd.conf file.  You should specify the user you created in section 3.  This seems easy enough, however, there is a common misconception about "starting" versus "running" a web server as root:

          Most servers are launched as root so that they can open up the low numbered port 80 (the standard HTTP port) and write to the log files. They then wait for an incoming connection on port 80. As soon as they receive this connection, they fork a child process to handle the request and go back to listening. The child process, meanwhile, changes its effective user ID to the user "nobody" and then proceeds to process the remote request. All actions taken in response to the request, such as executing CGI scripts or parsing server-side includes, are done as the unprivileged "nobody" user. (B)

        The security issue addressed above refers to a web server that has the user "root" specified in the server's configuration file.  If the web server is configured to run as the "root" user, then all HTTP request are executed with "root" privileges.  This situation can be devastating if used in conjunction with certain HTTP attacks. (A)

      7. Action: Port

      8. Edit the Port parameter within the httpd.conf file:
        # Port: The port to which the standalone server listens. For
        # ports < 1023, you will need httpd to be run as root initially.
        Port 80

        You should use the standard HTTP port of 80.  If you change this parameter to a different port, your clients will need to know this port number and specify this alternative port in their requests.

      9. Action: ServerAdmin

      10. Edit the ServerAdmin parameter within the httpd.conf file:
        # ServerAdmin: Your address, where problems with the server should be
        # e-mailed.  This address appears on some server-generated pages, such
        # as error documents.
        ServerAdmin [email protected]

        The security vulnerabilities associated with publicly displaying an actual user's email address may seem trivial.  Do not underestimate the security implications.  Specifying a user's local email address - such as - "[email protected]" reveals that user's local OS account name.  Using an e-mail alias such as "[email protected]" instead of "[email protected]," reduces the likelihood of a successful e-mail spoofing attack, as well as. prevents attackers from determining legitimate system usernames from the e-mail addresses. (A)

      11. Action: ServerRoot

      12. Edit the ServerRoot parameter within the httpd.conf file:
        # ServerRoot: The top of the directory tree under which the server's
        # configuration, error, and log files are kept.
        # NOTE!  If you intend to place this on an NFS (or otherwise network)
        # mounted filesystem then please read the LockFile documentation
        # (available at <URL:>);
        # you will save yourself a lot of trouble.
        ServerRoot "/usr/local/apache"

        This is the directive which specifies where all of the web server's configuration and log files will reside.  It is important to set the appropriate ownership and permissions on all of the files and directories within you ServerRoot directory.  We will cover this issue in a later section.

      13. Action: ServerName

      14. Edit the ServerName parameter within the httpd.conf file:
        # ServerName allows you to set a host name which is sent back to clients for
        # your server if it's different than the one the program would get (i.e., use
        # "www" instead of the host's real name).
        # Note: You cannot just invent host names and hope they work. The name you
        # define here must be a valid DNS name for your host. If you don't understand
        # this, ask your network administrator.
        # If your host doesn't have a registered DNS name, enter its IP address here.
        # You will have to access it by its address (e.g.,
        # anyway, and this will make redirections work in a sensible way.
        # is the TCP/IP local loop-back address, often named localhost. Your
        # machine always knows itself by this address. If you use Apache strictly for
        # local testing and development, you may use as the server name.

        This directive will set the server name when sending replies to clients.  The easiest way to identify which name to put here is to find the hostname of the underlying OS host.  You can issue the following command on Unix systems to find the hostname of your system:
        # hostname
        # nslookup
        Address:  XXX.XXX.XXX.XXX

        Address: your IP address

        The commands above will identify what your local hostname is and then make a DNS query.  You should verify that the IP address that is returned for your hostname is the correct IP address.

    2. Security Related Settings
      1. LogLevel

      2. Edit the LogLevel parameter within the httpd.conf file:
        # LogLevel: Control the number of messages logged to the error_log.
        # Possible values include: debug, info, notice, warn, error, crit,
        # alert, emerg.
        LogLevel notice

        This directive controls the verbosity of information that is logged in the error log file.  This style of level warning is similar to that of the syslog facility.  The parameter above specifies that all information which is at a level of "notice" or higher will be logged.

      3. ErrorLog

      4. Edit the ErrorLog parameter within the httpd.conf file:
        # ErrorLog: The location of the error log file.
        # If you do not specify an ErrorLog directive within a <VirtualHost>
        # container, error messages relating to that virtual host will be
        # logged here.  If you *do* define an error logfile for a <VirtualHost>
        # container, that host's errors will be logged there and not here.
        ErrorLog syslog:local7

        Add or edit the /etc/syslog.conf file to add this line:


        The syslog entry above will tell the syslog daemon to log all of the Apache web server's error logs to both the local log file and to a remote syslog server.  Execute the following commands to restart the syslog daemon (use the syslogd PID that is returned by your system):
        # ps -ef | grep syslogd
        root   210     1  0   Apr 29 ?        0:02 /usr/sbin/syslogd
            root 16913  6727  0 12:36:37 pts/2    0:00 grep syslogd
        # kill -HUP 210

        This directive specifies that all of the error messages get sent through the syslog facility.  We want to ensure the integrity of your error logs in case the web server ever gets compromised.  After a compromise, the log files on the host can not be trusted, since they could have easily been altered by the attacker.  In the above steps, we have configured the syslog facility to log all of the errors locally to the normal /usr/local/apache/logs/error_log file, as well as, log remotely to the syslog facility on a secure, remote host.  This ensures that the error logs have not been altered if we are investigating a break-in.

      5. CustomLog

      6. Edit the CustomLog parameter within the httpd.conf file:
        # If you prefer a single logfile with access, agent, and referer information
        # (Combined Logfile Format) you can use the following directive.
        CustomLog /usr/local/apache/logs/access_log combined

        This directive specifies both which file to log access attempts to and what type of format the file should use.  The directive above says that the "access_log" file will be combined and will contain both "referrer" and "user_agent" information.  This information will be use in a later section when we receive alerts for malicious http requests.

      7. Action: <Directory>

      8. Edit the <Directory> parameter within the httpd.conf file:
        # Each directory to which Apache has access, can be configured with respect
        # to which services and features are allowed and/or disabled in that
        # directory (and its subdirectories).
        # First, we configure the "default" to be a very restrictive set of
        # permissions.
        <Directory />
            Order Deny,Allow
            Deny from all

        In order to prevent any form of directory traversal trying to get outside of the document root, we will specify the directive listed above.  One aspect of Apache which is occasionally misunderstood is the feature of default access. That is, unless you take steps to change it, if the server can find its way to a file through normal URL mapping rules, it can serve it to clients.

        For instance, consider the following example:

          # cd /; ln -s / public_html
        Then accessing - http://localhost/~root/ within a web browser would allow clients to walk through the entire filesystem.
      9. Action: Options

      10. Edit the Options parameter within the httpd.conf file:
        # Note that from this point forward you must specifically allow
        # particular features to be enabled - so if something's not working as
        # you might expect, make sure that you have specifically enabled it
        # below.

        # This should be changed to whatever you set DocumentRoot to.

        <Directory "/usr/local/apache/htdocs">

        # This may also be "None", "All", or any combination of "Indexes",
        # "Includes", "FollowSymLinks", "ExecCGI", or "MultiViews".
        # Note that "MultiViews" must be named *explicitly* --- "Options All"
        # doesn't give it to you.

        The Options directive controls which server features are available in a particular directory.  We are configuring the options for our document root directory and sub-directories.  The parameters we set here will effect the entire web site.  If we need extra functionality within certain directories, we can define it in a sub-directory setting.

        1. Action: AllowOverride

        2. Edit the AllowOverride parameter within the httpd.conf file:
          # This controls which options the .htaccess files in directories can
          # override. Can also be "All", or any combination of "Options", "FileInfo",
          # "AuthConfig", and "Limit"
            AllowOverride None

          This directive tells the web server how to handle any .htaccess files it might find in sub-directories.  The .htaccess files can be used to override the default access control parameters set for the entire server.  We do not want rogue .htaccess files within our web site.

        1. Action: IncludesNoExec

        2. Edit the Includes parameter within the httpd.conf file:
          # This should be changed to whatever you set DocumentRoot to.

          <Directory "/usr/local/apache/htdocs">

          # This may also be "None", "All", or any combination of "Indexes",
          # "Includes", "FollowSymLinks", "ExecCGI", or "MultiViews".
          # Note that "MultiViews" must be named *explicitly* --- "Options All"
          # doesn't give it to you.

          Server Side Includes (SSI) are OS commands located within the html code of a web page.  SSIs are executed by the web server before the page is sent to the client.  The format of a typical SSI is shown below.

            <!--#'<tag><variable set> '-->

          If an attacker downloads and then edits an html page from a web site, he/she could alter the original SSI statement to a malicious request, such as the one displayed below.

              <!--#exec cmd=`cat /etc/passwd` -->

          This command could possibly show the OS password file to the attacker.  If an attacker was able to previously determine a web server's directory structure, he/she might be able to deface the web site with the following SSI code.

            <!--#exec cmd=`echo "you've been 0wned"` > /pathto/apache/index.html -->

          If you do not need to use SSI, then you can keep the setting from the Options section above, which will not allow an SSI at all.  If you must use SSI, the it is recommended that you use the IncludesNoExec option which will allow the server to parse SSI enabled web pages but it will not execute any system commands. (A)

        3. Action: SymLinksIfOwnerMatch

        4. Edit the SymLinksIfOwnerMatch parameter within the httpd.conf file:
          # This should be changed to whatever you set DocumentRoot to.

          <Directory "/usr/local/apache/htdocs">

          # This may also be "None", "All", or any combination of "Indexes",
          # "Includes", "FollowSymLinks", "ExecCGI", or "MultiViews".
          # Note that "MultiViews" must be named *explicitly* --- "Options All"
          # doesn't give it to you.

          You are encouraged to leave the Options setting from above alone, which will instruct the web server to not follow any symbolic links.  If you must use symbolic links for the functionality of your web site, consider the security risks that follow.  It is possible for an attacker to gain access to areas outside the specified document root if the web server is configured to follow symbolic links.  Consider the following scenario in which a server has dual functionality.  The server functions as both a web server and as an Anonymous FTP server.  The two servers also share portions of the same document directories.  This configuration can be exploited if an attacker uploads a symbolic link file into the ftp server's directory.  The attacker then uses a browser to request this file from the web server and is actually shown the system's OS password file instead.  This parameter setting will configure the web server to only follow symbolic links if the owner of the file matches the user who is accessing it.  In this case, the web server user "webserv" should not own any files outside of the web document root and therefore would not be allowed to access any files with this parameter.  This option is preferred over the FollowSymLinks due to the performance hit when Apache verifies the symlink.

      11. Action: Order and Allow/Deny from (Use IP)

      12. Edit the Order and Allow/Deny from parameter within the httpd.conf file:
        <Directory "/usr/local/apache/htdocs">

        # Controls who can get stuff from this server.
          Order allow,deny
            Allow from all

        The order argument specifies the order which any following access control parameters (allow/deny) are applied.  The order does matter!  The order option which is listed last takes precedence.  The example listed above essentially allows anyone to access the web site.  If we were to change this parameter to the following:

          <Directory "/usr/local/apache/htdocs">
               Order allow,deny
               allow from all
               deny from all

        We would effectively lock everyone out since the "deny" directive gets applied last.  You can use more restrictive options to the allow/deny options such as specific hostnames, IP addresses, domain names and IP ranges.

          <Directory "/usr/local/apache/htdocs">
               Order allow,deny
               deny from all
               allow from 202.54.
        This would restrict access to only hosts who reside in the appropriate IP range.  The order and allow/deny parameters should be applied to any portions of your web site which you would like to protect.  You should use IP addresses when possible, to prevent any DNS spoofing attacks.  You can use the allow/deny options in conjunction with any password protected methods as well.
      13. Action: ServerSignature

      14. Edit the ServerSignature parameter within the httpd.conf file:
        # Optionally add a line containing the server version and virtual host
        # name to server-generated pages (error documents, FTP directory listings,
        # mod_status and mod_info output etc., but not CGI generated documents).
        # Set to "EMail" to also include a mailto: link to the ServerAdmin.
        # Set to one of:  On | Off | EMail
        ServerSignature Off

        In order to protect which webserver software we are using, we should not disclose this information in any of our system generated Error pages.  Here is an example of the ServerSignature information from an Apache web page:
        Not Found
        The requested URL was not found on this server.
        Please check the filename requested and/or the link that you followed.

        Apache/1.3.15- Server at Port 80

        Remember when we edited the httpd.h file in section 1B?  This step change the default Server http response header to hide that fact that we are using Apache.  If we do not disable the ServerSignature setting, we will be negating the security benefit we gained by editing the httpd.h file.  By removing the ServerSignature, we can take another step towards protecting our webserver software version.

      15. Action: ServerTokens

      16. Edit the ServerTokens parameter within the httpd.conf file:
        # Set the ServerTokens to Min - this will work in conjunction with the new HTTP
        # Server Header that we created.  We want the HTTP Header to simulate the actual
        # Netscape-Enterprise Server Response. Otherwise, the user will notice that the
        # Server Response Header is not actually Netscape.
        ServerTokens Prod

        This step also works in conjunction with hiding the webserver software.  We do not want to give away any more information about our webserver than is absolutely necessary.  We will only give out the minimum server token information.  This will also aid in disguising our bogus server information we entered in the httpd.h file.  The different server token settings will display information as follows:

          ServerTokens Prod[uctOnly]
          Server sends (e.g.): Server: Apache
          ServerTokens Min[imal]
          Server sends (e.g.): Server: Apache/1.3.0
          ServerTokens OS
          Server sends (e.g.): Server: Apache/1.3.0 (Unix)
          ServerTokens Full (or not specified)
          Server sends (e.g.): Server: Apache/1.3.0 (Unix) PHP/3.0 MyMod/1.2
        If someone checks the HTTP server headers, we want to only display the PROD information for our Apache web server.  This also works in conjunction with our edited httpd.h information.  Here is what a typical HTTP response header should look like from an appropriately configured Apache install (Notice the bolded section):
        # telnet localhost 80
        Connected to localhost.
        Escape character is '^]'.
        HEAD / HTTP/1.0

        HTTP/1.1 200 OK
        Date: Fri, 10 May 2002 19:28:24 GMT
        Server: My-Server
        Last-Modified: Fri, 04 May 2001 00:00:38 GMT
        ETag: "6a631-5b0-3af1f126"
        Accept-Ranges: bytes
        Content-Length: 1456
        Connection: close
        Content-Type: text/html
        Content-Language: en

        Connection closed by foreign host.

      17. Action: CoreDumpDirectory

      18. Edit the CoreDumpDirectory parameter within the httpd.conf file:
        # Specify a directory where the webuser has write access.  This directory should
        # be outside of the web document root to prevent access by an attacker using http.
        CoreDumpDirectory /logs

        This directive tells Apache which directory to switch to before it dumps core.  The directory you specify must be writable by the webuser and should not be accessible from the normal web site.  Core dumps are very useful when diagnosing web server problems, however, they can contain sensitive information such as user authentication sessions.

      19. Action: Error Responses

      20. Edit the default system Error response parameter within the httpd.conf file:
        # Customizable error response (Apache style)
        #  these come in three flavors
        #    1) plain text
        #ErrorDocument 500 "The server made a boo boo.
        #  n.b.  the single leading (") marks it as text, it does not get output
        #    2) local redirects
        #ErrorDocument 404 /missing.html
        #  to redirect to local URL /missing.html
        #ErrorDocument 404 /cgi-bin/
        #  N.B.: You can redirect to a script or a document using server-side-includes.
        #    3) external redirects
        #ErrorDocument 402
        #  N.B.: Many of the environment variables associated with the original
        #  request will *not* be available to such a script.

        ErrorDocument 404 errors/404.html

        Each type of web server has its own distinct style of error pages.  These pages are sent by the server when an error, such as "404 - Not found," has occurred.  By issuing a request for a file that is not present on a web server, an attacker may determine the web server software by simply identifying the error pages displayed.  To avoid this software disclosure, the default error pages presented by the web server must be changed.  There are two possible choices.

        • Edit the default error pages to a style that is consistent with the website's template.  This may include changing color schemes and altering the text message displayed.

        • For deception purposes, edit the error pages to the exact style of a different web server.  For example, if a web server is currently running Apache, change the error pages to resemble the iPlanet web server version. (A)

        In the example above, we are configuring Apache to send the 404.html file, within the /path/to/apache/htdocs/errors directory for all 404-Not Found errors on the web server.

        1. Action: 401/403 Errors

        2. Edit the default system Error responses for 401/403 parameters within the httpd.conf file:
          ErrorDocument 401 /path/to/apache/cgi-bin/401.cgi
          ErrorDocument 403 /path/to/apache/cgi-bin/403.cgi

          SysAdmins need to keep tabs on all security related issues with their web servers, which include any webserver status codes related to unauthorized access attempts.  A glaring weakness of utilizing HTTP authentication as a method of access control, is its inability to track failed attempts for restricted content across multiple connection attempts.  Since HTTP authentication is stateless, it has no perception of past attempts, and therefore, cannot lockout a client who is attempting a brute force attack against protected information. To assist with monitoring for these attacks, the web server should be configured to use custom CGI error response pages for both 401 and 403 server response codes.  The error pages are PERL CGI scripts (Appendix B) that are initiated every time the server issues either of these response codes.  These scripts accomplish many important tasks including issuing an html warning banner to the client and immediately sending an e-mail notification to the SysAdmin.  The e-mail message automates the process of manually collecting security related session information from the web server access and error logs for the request. (A)   Here is an example of an email alert generated by Apache when a client has accessed a password protected file and has failed the authentication:
          There Was An Illegal Access Attempt On:
          Tue Apr 30 12:47:53 EDT 2002


          Server Info -
          IP of Client -
          Request - /secret_directory/password_protected.html

          * For Attacker Information - click on the following link *

          The hyperlink feature, within the e-mail message, is useful for tracking down the appropriate "network abuse" contact personnel responsible for the attacker's IP segment. While not every 401 and 403 message warrants these investigative actions, repeated errors identified from a certain IP address should be handled appropriately.  This CGI alert e-mail system facilitates the prompt notification of proper personnel.

          NOTE - You will need to use a Microsoft Internet Explorer Browser to access the VisualRoute link.  The VisualRoute application is Java based and does not work correctly with Netscape Browsers. (A)

        3. Action: Other Status Codes

        4. Edit the Error responses for other security related status codes within the httpd.conf file:
          # These status code errors will be sent to the WebAdmin/SecAdmin by email.
          # Client Errors that should be tracked.

          ErrorDocument 400 /path/to/apache/cgi-bin/400.cgi # Bad Request
          ErrorDocument 403 /path/to/apache/cgi-bin/405.cgi # Method Not Allowed
          ErrorDocument 413 /path/to/apache/cgi-bin/413.cgi # Request Entity Too Large
          ErrorDocument 414 /path/to/apache/cgi-bin/414.cgi # Request URI Too Large

          # Server Errors that should be tracked.

          ErrorDocument 500 /path/to/apache/cgi-bin/500.cgi # Internal Server Error
          ErrorDocument 501 /path/to/apache/cgi-bin/501.cgi # Not Implemented

          As we discussed in the previous section, there are a number of HTTP status codes that need to be monitored in real-time.  To assist us with this monitoring, we will define the status codes above to trigger many CGI scripts.  The CGI scripts are basically the same as the ones used for the 401/403 errors.  The scripts will generate an html page to send to the client as well as send an alert email to the appropriate administrators.  You may choose to add more status codes to this list.  The status codes listed above were selected since they are common codes which are generated by a web server when a web attack is taking place.

      21. Action: <LimitExcept>

      22. Edit the the httpd.conf file to add the following entry:
        <Directory /usr/local/apache/htdocs>
          <LimitExcept GET POST>
                  Order allow,deny
                  deny from all

        We want to restrict the functionality of our web server to only accept and process certain HTTP Methods.  For normal web server operation, you will typically need to allow the both the GET and POST request methods.  This will allow for downloading of web pages and uploading any type of basic form submission information.  The HEAD requests are included with GET requests when using the LimitExcept directive, so excluding HEAD requests will effectively stop anyone from downloading your web pages.  This entry will cause all non-allowed HTTP Methods to trigger a 403-Forbidden status code.  As we have configured in a previous step, our 403 status codes are sent to a CGI alerting script which will send warning html to the client and send email to the Admin.  This will allow the Admins to monitor continuous Method attacks.  Attackers will often use differing HTTP Request Methods to gain information about either the web server's configuration or the surrounding web environment.  By issuing the OPTIONS method, the attacker quickly finds out all of the Allowed Methods.  The DELETE method should not be allowed for obvious reasons to protect web content.  The TRACE method can be used for HTTP path reconnaissance.  This is a newer technique for both mapping HTTP request paths and for identifying possible new targets.  The HTTP “TRACE” Method is essentially traceroute for Web traffic.  It will send a HTTP packet to a destination host and then return a packet with the path the it took.  The interesting reconnaissance technique is that the TRACE Method will identify Proxy Web Servers that are between the client and the destination host.  Not only should your Apache web server not accept the TRACE method, but your entire network architecture should disallow this functionality as well.

    3. Access Control
      1. Action: Restrict Access to a Directory or File

      2. If you need to restrict access to a directory or file, use the following commands:

        Basic Authentication:
        # htpasswd -c /path/to/passwordfile test
        New password: password
        Re-type new password: password
        Adding password for user test

        Within the httpd.conf file, add an entry to protect the desired content:
        <Directory /usr/local/apache/htdocs/protected>
          AuthType Basic
          AuthName "Private Access"
          AuthUserFile /path/to/passwordfile
          Require user test

        Digest Authentication:
        # htdigest -c /path/to/digestfile realm test
        New password: password
        Re-type new password: password
        Adding password for user test

        Within the httpd.conf file, add an entry to protect the desired content:
        <Directory /usr/local/apache/htdocs/protected>
          AuthType Digest
          AuthName "Private Access"
          AuthDigestFile /path/to/digestfile
          Require user test

        In order to protect content on a web server, you will need to first create a password file/database and then add in user entries for the users who will be allowed to access the protected data.  Another major drawback to Basic HTTP authentication (along with the security issue discussed in the 401 section above) is that the client's credentials are sent across the wire in an insecure manner.  When the client is prompted for a username and password, the data entered is sent back to the web server by only using Base64 Encoding.  This is data which could be easily decoded if an attacker were to sniff the credentials from the network.  There are two alternatives for this security issue - 1) Use Secure Socket Layer (SSL) for all directories which will be protected.  This will provide an encrypted channel between the client and the web server.  or 2) Use the Digest Authentication module.  Digest Authentication is a more secure alternative to Basic Authentication since the user's password is never sent across the network.  Digest Authentication uses MD5 to make a hash of the password entered and this is sent to the web server for verification.  The downside of using Digest Authentication is that not all web browsers support it.  As of the writing of this paper, Microsoft IE 5 will support Digest, however, Netscape Navigator will not.

    4. Common Attack Signatures
      1. Action: Mod_Rewrite Voodoo

      2. Add the following lines to the end of the httpd.conf file:
        RewriteEngine On
        RewriteLog /usr/local/apache/logs/ids.log
        RewriteLogLevel 9
        RewriteRule \.\.|\.\.\.|\s|\'|\"|\+|\/\/|\[|\]|\;|\~|\#|\%|\^|\&|\(|\)|\{|\}|\;|\?|\,|<|<<||\||\!|\`|>|>>|\@|\$|\*       -       [F]
        RewriteRule    /\.[a-z0-9]|/bin|/sbin|/etc|httpd\.conf|access_log|error_log    -    [F]

        The Mod_Rewrite is an extremely powerful tool.  This module is normally used in daily web administration to control either where or what a client is requesting from the web server.  When a website's directory structure has changed, URL redirection allows the webmaster to direct client requests to the current location.  This web server function may also be used for security purposes.

        Attackers will often send  malicious HTTP requests to the web server which will contain non-alphanumeric characters.  Besides the functionality of some CGI scripts, all HTTP requests should only contain either letters, numbers, period, dash or underline characters.  Any other character in a request could be used to trick the web server or application in to executing undesired code.  Common HTTP attack character are as follows -

        • Directory Traversal - "."  ".." and "..." Requests
        • Space in Request - "%20" Requests
        • Unix Pipe Character - "|" Requests
        • Semi-Colon (Command Combinations) - ";" Requests
        • Command Redirection - "<" ">" ">>" "<<" Requests
        • Server Side Includes - "!" Requests
        • Back-Tick (PERL Execution) - "`" Requests
        • System Commands - "/bin" "/sbin" Requests
        • Web Files - "httpd.conf" "access_log" "error_log" Requests

        By manually monitoring the web server's access file, new malicious HTTP requests may be identified.  The URL redirection directive listed above will identify any HTTP request that contains the illegal characters and redirect it to the PERL CGI 403 script.  This warning script can function as a security "Choke Point" where all newly identified malicious HTTP requests can be funneled.  When a new attack is identified in the log files, simply add in a new URL redirection directive within the server's configuration file.  Here is an example email alert from a real access attempt against an Apache web server that was using this Mod_Rewrite rule-set:
        To: [email protected]
        From: WWW-IDS-Alert
        Subject: IDS Alert

        ***Possible URL Attack Detected***
        There was An Illegal Access Attempt On:
        Thu Mar 21 10:14:51 EST 2002

        From Host - 12.XXX.XXX.XXX
        URL Request -