Join/Renew Benefits Sage Programs SysAdmin Resources Jobs Board SAGE Home
The USENIX Special Interest Group for Sysadmins

Apache Web Server Details

Return to Main

Run the Server as an Unprivileged User

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 userid and group nobody are typically used for this purpose, but a userid and group that are unique to the Web server is a better solution from a security perspective.

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.

Use the following command line entries as patterns for creating a group and user for the Web server. Substitute the directory you intend to use for the Web server for <server root> (under Solaris 2.x, this would typically be a subdirectory of /opt (e.g. /opt/httpd).

groupadd httpd
useradd -d <server root> -g httpd -s /bin/false -c "Web Server" -m httpd

To make sure the user account you created can't be used to log on, check the entry for the user in /etc/shadow. The password field should contain the entry *LK*, indicating that the account is locked and cannot be used to log in.

httpd:*LK*:::::::

Install the Server

By convention, shared third-party applications are installed in the /opt directory. The root directory for a Web server, commonly referred to as the Server Root directory, would thus be a subdirectory in /opt (e.g., /opt/httpd).

If you have followed our instructions for securing the host, you will have to unpack the distribution and compile it on a separate host. When you unpack the distribution file, you should see the following directories:

cgi-bin
conf
htdocs
icons
logs
src
support

To make your server more secure, use a separate disk partition for your Web content. Create a unique mount point for this directory; htdocs is a good name to use, but make it somewhere outside the ServerRoot directory. You'll need to update /etc/vfstab to mount this partition as part of your server's startup process.

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: it contains information an attacker could use to penetrate your system. Move these documentation files into your support directory so that the Webmasters for your site can refer to them as needed.

The src directory should not be installed on your server. The contents of this directory are only needed when you are compiling the dæmon executable.


Set Directory and File Permissions

Background Information

We focus our discussion on the issues involved in setting directory and file permissions on Solaris 2.x. Throughout this guide, we will use /opt/httpd as the server's base directory (i.e., as ServerRoot).

Apache (and NCSA) server software includes files grouped by function into subdirectories. The following table lists subdirectories normally located in the ServerRootdirectory:

Server Root Directories
Apache/NCSA Directories
Name Function Contents
conf Server Configuration httpd.conf, srm.conf, access.conf
logs Server Logs access_log, agent_log, error_log
cgi-bin Web-based executables CGI Scripts
icons Static Icons Icons used for fancy directory listings
support Tools Webmasters' Utilities

NOTE: Because the server's log files can quickly grow in size, you may want to move this directory to another file system with adequate space. You will have to change the server's configuration to support this change.

To define access privileges for the Web server and related files, we can break users into three groups. Because we want the server to run under a non-privileged userid, we define a fourth group for the server itself. These groups are based on functional roles:

Functional User Roles
Role Description
Webmaster
A (hopefully) small group who maintain the server
Web Developer
Those who develop programs (CGI scripts, JavaScript, ...)
Web Author
Those who develop Web pages
Web Server
The userid under which the server runs

The following matrix lists permissions for each directory by group role. This matrix is based in part on recommendations provided in Lincoln Stein's book, Web Security. Note that you will have to add some individuals to multiple groups to provide the required levels of access.

Recommended Permissions
Group Configuration Tools Logs CGI Documents
Webmaster rwx r-x r-x rwx rwx
Web Developer - - - rwx rwx
Web Author - - - r-x rwx
Web Server - - - r-x r-x

Making the Changes

  1. Create UNIX groups for each of the functional roles defined above:
    groupadd Webmastr
    groupadd Webauth
    groupadd Webdev

    Edit /etc/group to add users to these new groups. Members of the Webmaster group must also be members of the Webdev and Webauth groups, and some members of the Webdev group must also be in the Webauth group.

  2. Make sure root owns all of the directories and files in the directory tree that contains all of the server-related files:
    chown -R root /opt/httpd
  3. Change group ownership of the server dæmon:
    chgrp bin /opt/httpd/httpd
  4. Make sure only root can execute the dæmon:
    chmod 100 /opt/httpd/httpd (---x------)
  5. Change group ownership of specific server subdirectories:
    chgrp -R Webmastr /opt/httpd/
    chgrp -R Webdev /opt/httpd/cgi-bin
    chgrp -R Webauth <Document Root>
  6. Change permission for the configuration directory and files:
    chmod 770 /opt/httpd/conf (drwxrwx---)
    chmod 660 /opt/httpd/conf/* (-rw-rw----)
  7. Change permission for the Webmaster's tools directory and files:
    chmod 770 /opt/httpd/support (drwxrwx---)
    chmod 770 /opt/httpd/support/* (-rwxrwx---)
  8. Change permission for the logs directory and files:
    chmod 750 /opt/httpd/logs (drwxr-x---)
    chmod 640 /opt/httpd/logs/* (-rw-r-----)
  9. Change permission for the cgi-bin directory and files.
    NOTE: Stein recommends file mode 775 for interpreted scripts and 771 for compiled scripts:
    chmod 2771 /opt/httpd/cgi-bin (drwxrws--x)
    chmod 775 /opt/httpd/cgi-bin/* (-rwxrwxr-x)
  10. Change permission for the htdocs directory and files:
    chmod 2771 <Document Root> (drwxrws--x)
    chmod 664 (all files in <Document Root> and its subdirectories) (-rw-rw-r--)
  11. Change permission for the icon directory and files:
    chmod 771 /opt/httpd/icons (drwxrwx--x)
    chmod 664 /opt/httpd/icons/* (-rw-rw-r--)

NOTE: In his Web Security Lincoln Stein recommends using mode 2xxx (i.e. setting the SGID bit) for some server directories. His point is that this makes file and directory sharing easier for members of the groups involved in maintaining parts of the server. We followed his recommendations for the server's ScriptAlias and DocumentRoot< directories, but users' UMASKs may have to be changed to make group ownership of new files match the group ownership for the directory.


Delete Unneeded CGI Scripts

Delete all CGI scripts included in your Apache distribution. Install only those CGI scripts you have tested and found safe. At least one of the commonly distributed scripts, pfh, has been used to compromise several Web servers.

You should require that all CGI scripts be run only from your strictly controlled cgi-bin directory, and you should not allow not the use of shell scripts.


Delete Unneeded HTML Documents

Remove all non-essential files from the directories under the DocumentRoot directory specified in your srm.conf file.

It takes only a small error to cause your server to provide a listing of the files in a directory to a browser. If you've developed the habit of leaving files in the directories within your DocumentRoot directory tree, thinking that they can't be accessed if they're not linked to some document, that one small mistake can lead to an unauthorized disclosure. A freshly installed Web server is the best time to start developing good file discipline.


Configure the Server

Within the /opt/httpd/conf directory, make copies of the default configuration files distributed with for Apache/NCSA.
NOTE: This is not required if you are using our distribution.

# cd /opt/httpd/conf
# cp httpd.conf-dist httpd.conf
# cp srm.conf-dist srm.conf
# cp access.conf-dist access.conf

Make the changes specified below for each of the server configuration files to make your server work correctly.

httpd.conf (Basic Server Configuration)

In the table below we list server directives and suggested values. Server directives not mentioned should be left at the default values.

Recommended Values for httpd.conf Directives
Directive Setting
ServerType standalone (more secure than starting it with inetd)
HostnameLookups off
(DHCP, firewalls and proxies make client name resolution ineffective)
User httpd
Group httpd
ServerAdmin root@<hostname> (replace hostname with the DNS name of your host)
NOTE: this doesn't really matter because we don't use SMTP mail
ServerRoot /opt/httpd
ErrorLog logs/error_log
(or change to a directory with lots of free space?)
TransferLog logs/access_log
(or change to a directory with lots of free space?)
ServerName The complete DNS name for your server (e.g., www.<servername>.<domain>)

The following entries affect the load placed on your host machine by the Web server. The StartServers and MinSpareServers entries are closely related; if you change one, you must make the same change in the other. The default value for these parameters is five. Depending on the load you anticipate, you may want to adjust this value up or down.

StartServers
MinSpareServers
MaxSpareServers

The following is a list of other entries in this file that can affect your server's ability to withstand a denial of service attack. You can safely leave these additional settings at the default values, but should familiarize yourself with the entries and their effect on the server:

Timeout
KeepAlive
MaxKeepAliveRequests
KeepAliveTimeout
MaxClients
MaxRequestsPerChild

srm.conf (Directory and Document Configuration)

Entries not specifically mentioned here can be safely left with default values.

Recommended Values for srm.conf Directives
Directive Setting
DocumentRoot The base directory for your Web content: should be a separate partition
UserDir Comment this entry out. This entry allows Web content from directories outside the DocumentRoot directory tree. This decreases your ability to prevent access to other file systems on your Web server—not a good security practice.
DirectoryIndex index.mm (default value)
NOTE: If a file specified in this entry is not present in a subdirectory within DocumentRoot, the server will send the browser a list of all files and subdirectories in the directory. Clients can access any files or subdirectory in this list, even with no hyperlinks to them from other documents. See access.conf for a way to prevent this behavior.
FancyIndexing off: Prevents the server from displaying an icon to reveal the type of a file when the server presents a list of file names in a directory that does not contain a file named in DirectoryIndex.
Alias /icons/: Comment this entry out. Turning FancyIndexing off removes the need for this setting.
ScriptAlias /cgi-bin/ /opt/httpd/cgi-bin/
NOTE: To use CGI scripts, you will also have to make a change in access.conf.
AccessFileName .htaccess: This is used with the server's Basic Security capability. You can leave this at the default value, but you should be aware of its function in protecting the Web pages (and scripts) located in protected directories.

The following entries in srm.conf can compromise security and should therefore be commented out. Make sure you understand the consequences if you choose to make one or more of these options active.

  • AddHandler (all of them)
  • MetaDir
  • MetaSuffix

access.conf (Security Related Configuration)

This file controls several critical security features of the Web server.

NOTE: The directives in this file apply to specific items. For example, if we define /htdocs within the <Directory ...> ...</Directory> tags, we can apply access controls and other restrictions to the entire directory tree with an entry of the following form in this file:

<Directory /htdocs>
   Options IncludesNoExec
   ...
   order allow,deny
   allow from all
   ...
</Directory>

A complete explanation of the structure and capabilities provided through this file is way beyond the scope of this document. Please refer to the Apache User's Guide for a more complete explanation.

Recommended Values for access.conf Directives
Directive Setting
<Directory /usr/local/etc/httpd/htdocs> Change the path to match the DocumentRoot entry specified in srm.conf.
Options Change the default entry Indexes FollowSymLinks to IncludesNoExec. This will prevent your server from sending a list of files in a directory if there is no file with a name specified by the DirectoryIndex setting in srm.conf. It will also prevent the use of symbolic links that could provide access to a file outside your DocumentRoot. The new value allows Server Side Includes (SSI) but prevents execution of code using an SSI. It also restricts the use of CGI scripts to the ScriptAlias directory.
NOTE: The options specified here apply to the entire server. Use Options within other <Directory> and <Limit> blocks to limit exceptions to specific directories.
order allow,deny
allow from all
This default entry allows world access. See the section on Access Control below for more details, or check the Apache User's Guide.

<Directory /usr/local/etc/httpd/cgi-bin> Change the path to match the ScriptAlias entry in srm.conf.
NOTE: CGI scripts in the ScriptAlias directory should execute. If they don't, you may have to change the Options setting for this directory block to ExecCGI.

Configure Server Auditing

By default, log files are written to the logs subdirectory of the ServerRoot directory. You can change the log file names and locations by modifying their directives in httpd.conf. Do not disable logging.

The server normally creates two log files:

access_log (TransferLog)
error_log (ErrorLog)

Optional Log

You can capture user agent (browser) data by adding the AgentLog directive to httpd.conf—use the other log entries as a pattern.


Configure Access Control and Authentication

The Apache server offers a number of methods for restricting access. Capabilities range from allowing connections only from specified IP addresses or domains, to detailed user and password access control for individual files. A complete discussion of Apache's access control features is beyond the scope of this document. Please refer to the Apache User Guide for details.

Access control for the server is set in the access.conf file. The primary access control for the server is specified in a <Directory...> entry covering the server's DocumentRoot. As specified by the Options field in this directive, the default is to allow the server to present index listings and to follow symbolic links in locating Web pages. Who is allowed to access the server is controlled by the order and allow fields in this same directive. By default, the whole world can access everything. To change access permissions, change the allow entry and add deny entries as required.

For example, to permit access from only those clients whose IP addresses are in the class B address space 162.45.xxx.xxx you would change the default settings:

order allow,deny
allow from all
to:
order allow,deny
allow from 162.45
deny from all

Authentication and access control are handled by the Options field in <Directory> and <Limit> directives. These directives are normally specified in the access.conf file. Use of these directives and the access control features they provide is related to the use of .htaccess files in subdirectories located in the server's DocumentRoot, but this can be changed through the use of the AllowOverride directive.


Restrict Remote Operations

Permission to add files to a directory using FTP's PUT is controlled by file and directory permissions. The default configuration we specify will allow anyone in the Webauth group to FTP files into your DocumentRoot directory tree.

HTTP POST is controlled using the Limit directive. Before you configure your server to allow HTTP POST operations, you should understand the use of Apache's authentication and access controls to restrict these activities to designated individuals.


Provide a Security Banner

Use the following as an example:

###################################################################### This system is intended for authorized users only. Activity on this system is monitored and recorded. If monitoring reveals activities exceeding privileges, attempts to penetrate system security, or possible criminal activity, system personnel may provide evidence of such activity to law enforcement officials. If you continue past this point, you consent to this monitoring. ######################################################################

Starting and Stopping the Server

The following script is a pattern for automating the process of starting and stopping the Web server. Give this script the filename httpd and copy it to /etc/init.d, then create the soft links specified below to complete the process.

#!/bin/sh
#
# /etc/init.d/httpd - Start/Stop httpd server
#
# This is a startup file for the daemon at system init time.
# by Solaris convention, it should be in /etc/init.d with
# links to it from rc3.d and rc0.d.

killproc() { # kill the named process(es)
pid=`cat /opt/httpd/logs/httpd.pid`
[ "$pid" != "" ] && kill $pid
}

case $1 in
'start')
if [ -f /opt/httpd/httpd ]; then
/opt/httpd/httpd -d /opt/httpd
fi

;;
'stop')
killproc httpd
;;
*)
echo "usage: /etc/init.d/httpd {start|stop}"
;;
esac

Create the following links to the above script:

cd /etc/rc3.d
ln -s /etc/init.d/httpd S99httpd
cd /etc/rc0.d
ln -s /etc/init.d/httpd K99httpd

Periodically Archive and Reset Logs

Apache stores the offset of the end of the most recent entry in its log files and will try to write the next entry at that offset in the file. So, to archive and rotate Apache's logs, you need to move the log files and restart Apache. Because access.log grows by about one megabyte for each 10,000 hits, you should do this on a regular basis.

Here's a small shell script you can run from cron to move the log files, create (empty) new ones and archive the old logs. This process requires an archive subdirectory in your logs directory. We recommend clearing your logs with this procedure on a weekly basis. If you're running a program to automatically update a server statistics page, you can run this script shortly after your statistics program does its update.

#!/bin/sh
cd /opt/httpd/logs
mv *_log archive
touch access_log error_log # add other logs if you're using them
kill -1 `cat httpd.pid`
cd archive
DATE=`date -u +%d%m%Y`
tar -cvf httpd-logs.$DATE *_log
if [ $? = 0 ]
then
compress -f *.$DATE
if [ $? = 0 ]
then
rm *_log
else
echo "Compress failed"
fi
else
echo "Tar failed"
fi