ACLs under Apache

To be published on 20th August 1999

In this article, we will be covering how to use ACLs (Access Control List) to protect data, and how to use them to securely implement HTTP PUT and discuss how to use modules to increase Apache's functionality.

An alternative to what I mentioned last article, of allowing www-data (user the web server runs as) to log in, is to create a user, as previous, but disable the account. This is done by giving it an invalid shell (/bin/false is a good choice for this), and disabling the password (by putting a * at the start of it). The data for the webserver is then owned by a group (www, for example) and any users that require access to update the data are then put in this group, and ensure any data intended for the web server is readable by this group. This means that if the server is compromised, the data is still intact.

Another important point about .htaccess files is to ensure the .htpasswd file (the file that lists username / password) is not accessible via the webserver. This is obviously important, as it doesn't open your password file to possible brute force attacks.

The fundamental directive used to implement ACLs is <Directory> and <Location>. By using these, it is possible to apply directives selectively over a certain portion of the website. Additionally, you can use these to restrict the domains that can access the specified path or URL. For example, to restrict a certain URL to only one domain, in access.conf, put:

	<Location /protected>
	order deny,allow
	deny from all
	allow from
This will only allow any hosts in the domain to access any URLs from http://server/protected/. However, it is generally considered a better idea to restrict via IP address, as this reduces the need for a extra DNS lookup for each access to this URL, and also reduces the chance of DNS spoofing being used to access this data.

However, <Directory> and <Location> can be used for much more than simply restrict access based on hostnames. Apache can be configured to only allow access to the defined DocumentRoot (see last article), and any directories that you wish to allow access to must be specifically enabled. As in many other cases, this is useful, as only what is specifically allowed can be accessed.

To deny everything, add a <Directory> section like:

	<Directory />
	Options None
	AllowOverride None
This means any features you want have to be specifically enabled, which means you can't be compromised by a feature you didn't know about. It is also important to enable any html document areas you wish to be viewable, and any CGI script areas. For html document areas:
	<Directory /var/www>
	Options Indexes Includes FollowSymLinks
	AllowOverride None
	order allow,deny
	allow from all
This will enable following of symlinks, allow viewing of directories and enable includes.

For CGI script areas:

	<Directory /usr/lib/cgi-bin>
	AllowOverride None
	Options ExecCGI
One important way of adding functionality to your web server is by the use of modules. There are many modules available for apache, ranging from simply enabling system password authentication, to implementations of Java servlets - to see what modules are available, have a look at However, before being able to use these modules, it is essential to either compile your apache web server with support for DSO (Dynamic Shared Object), or statically compile the module into the web server. To enable DSO support (in the version of Apache (1.3.6) available at time of writing):
	tar xvfz /path/to/apache-1.3.6.tar.gz
	cd apache-1.3.6
	./configure --prefix=/usr/local/apache --enable-rule=SHARED_CORE --enable-module=so <any usual configure options>
After installing this version of Apache, it is then a simple matter to compile a module and enable it in the server, by the following:
	/path/to/apache/install/apxs -c -i -a mod_<name>.c

Enabling HTTP PUT, which allows uploading to a web server, is done via a combination of <Location> and an Apache module, mod_put. This is available from To configure HTTP PUT, add to the configuration file the following:

	<Location /pub>
	EnablePut On
	AuthType Basic
	AuthName "Web publishing"
	AuthUserFile /www/etc/passwd
	AuthGroupFile /www/etc/group
	<Limit PUT>
	require valid-user
This enabled HTTP PUT in your desired location, sets the user and group files (as last article), and then limits HTTP PUT to a valid user from the configured files.

Another facility that is sometimes wanted in a secure environment is allowing users to authenticate using their system password. This is useful, for example, in an intranet, possibly combined with the previous section about HTTP PUT, to allow users to publish to a local web server. However, the security implications of enabling system passwords for authenication must be carefully considered.

The web server does not limit the amount of times that a user can try to log in, possibly allowing a brute force attack on someones password. Additionally, there is no logging of how many times a user tried to log in, meaning a valid user can not be warned that someone is attacking their account. And, usually, web sites are not encypted, meaning anyone can snoop the unencrypted password as it is transmitted to the server.

However, there are situations where this is useful - in a local intranet, where the only users that have access to the computers are trusted it can be a very useful addition. It is enabled by compiling the module, and adding the following lines to the configuration file:

	LoadModule sys_auth_module     modules/
after the auth_module LoadModule line and
	AddModule mod_auth_sys.c
after the AddModule mod_auth.c line. Then, in the .htaccess file for the directory you wish to protect with system passwords, put:
	AuthName RestoreFiles
	AuthType Basic
	AuthSystem On
	AuthSystemAuthoritative On
	require valid-user
Keeping an eye on web server logs is essential - it can show you trends in how people are accessing your website, and possibly any attempted breakins. There are plenty of programs available that can analyse the standard log format - mention some here. To enable logging in the standard format, use the following configuration file extract:
	ErrorLog /var/log/apache/error.log
	TransferLog /var/log/apache/access.log
Another essential configuration item for logging is if the server logs the hostname of the client or the simply the IP address. It is generally better to log the IP address - this gives a performance increase, as the server does not require a DNS lookup for each client accessing the site, and also reduces the possibity of someone getting incorrect data into your logs by compromising the DNS server that it uses. To disable hostname lookups, add:
	HostnameLookups off
Apache is a pre-forked web server - this means that when it is initially started, it starts a predefined number of servers, and spawns more as the need arises. Careful choice of these values can ensure that your web server can service the requests, but also not require too many clients to wait while another process spawns. Ill chosen values for these settings can either make your server seem sluggish, and unable to handle the load, or even open up the possibility of a Denial of Service (DoS) attack. To set these values, add the following lines:
	MinSpareServers x
	MaxSpareServers y
	StartServers z
Choosing values of x, y and z appropriately requires a reasonable idea of the capabilities of your server, the load you are expecting and many other variables, and can be gradually tuned to become optimal over time - the default values that come with the server are reasonable for more servers. Checking how many processes are running some time after the server has started will give you a good idea of a number of processes that is required.

Once again, you can see that Apache has a huge array of options, and with careful consideration of which ones you use, it is possible to get a fully functional web server that is reasonably secure. In the next article in this series, we will discuss how to secure CGI scripts, and how to chroot Apache.