Introducing Apache


The Apache Web server is the posterchild of the Open Source movement. Having won over both academic and enterprise users, it now accounts for over 55% of the Web sites on the Internet, almost double those that run on Microsoft's often-exploited IIS system (http://www. netcraft .net/survey/). Apple has worked closely with the Apache Software Group to ensure that Apache works correctly on Mac OS X and is easy to both compile and update.


Like other software we've discussed in this book, Apple does not always include the latest Apache distribution with OS X. Although upgrading manually isn't difficult, you must pay close attention to Apple's automatic security updates; these updates often include changes to Apache and its components , replacing any custom installation you may have performed.

At the time of this writing, the Apache Web server was in its initial 2.0 release, but had not yet been adopted by Apache for Mac OS X Client or Server. In addition to new features and extensibility, 2.0 brings robust Windows support, which will undoubtedly increase its popularity even more.

Recent Exploits

I've had the pleasure of recently being part of a conversation that started with the words, "If Apache was as popular a server as Windows, you'd see it being attacked as well." As mentioned previously, Apache is more popular than IIS, and has had its share of attacks over the past few years . The difference, however, is that Apache's problems have paled in comparison to IIS's, in terms of both frequency and severity, as well as how they're addressed by the server administrators. Good Unix administrators have learned to keep track of system updates and apply them as needed. In today's "install-Windows-2000-and-you're-an-instant-administrator" IT climate, too many NT/2000/XP systems go unpatched, are compromised, and remain online in a "hacked" state doing who- knows -what.

Here is a brief history of Apache exploits, starting with the initial Mac OS X release version, up to October of 2002:

Use of mod_rewrite can reveal arbitrary file contents (Apache 1.3.12)

The Apache mod_rewrite module is used to redirect page requests to another location, which it does by rewriting the request on the fly. It can be used to seamlessly transition between different servers, and even includes a proxy function for mapping remote Web servers "onto" your local server. The exploit took effect when mod_rewrite mapped a request onto a file whose name contained a regular expression. Examples and more information are available from and name =CVE-2000-0913. This bug was corrected in Apache 1.3.14.

Bug in mod_vhost_alias provides access to CGI source code (1.3.12)

A bug in Apache's virtual host module allowed remote attackers to view the contents of CGIs, rather than execute them, if the cgi-bin directory was located at the document root of the server. Corrected in Apache 1.3.14. More information can be found at

Malformed URL displays directory contents (Apache 1.3.14)

Inappropriate URL handling by mod_negotiation , mod_dir , and mod_autoindex allowed attackers to create URLs with a large number of slash ( / ) characters (as in thousands) and potentially reveal directory listings rather than the appropriate index file. An example exploit script written in Perl can be found at More information on the bug is located at

Multiviews bug (Apache 1.3.20)

The Apache Multiviews feature enables the Apache server to intelligently respond to a request for a resource that, as named, is not present. When the Multiviews option is set, the server will attempt to respond to a request for a file that isn't present by matching the base file name against others in the directory, and will serve the best match to the client. In Apache 1.3.20, if the resource was called with the query string M=D appended to it, a directory listing would be returned instead. Although basic file permissions were not overridden, this did reveal file information that otherwise would be hidden and resulted in pages that should not have been easily seen. This error was fixed in Apache 1.3.22. See for more information.

Denial of service attack against Apache (1.3.24)

A serious bug, this DoS attack resulted from a mishandling of chunked encoding by the Web server. In some systems, it posed no more of a threat than simply using additional system resources. On others ”namely Windows and 64-bit platforms ”the bug was found to enable the remote attacker to execute arbitrary code on the server. This is one of the most serious Apache bugs to surface since its inception. The problem affected almost all platforms, and all versions of Apache, including the early 2.0 releases. It was corrected in Apache 1.3.26. The original CERT warning can be found at, and additional resources are available from

Shared memory DoS exploit (1.3.26)

The Apache "scoreboard" provides shared stats for all the active Apache processes running. It also suffered from a serious security hole that enabled any user with the Apache processes' user ID (that is, any scripts running from the server) to send a SIGUSR1 signal to any local process as root. The implications of this depend on the system being attacked, but range from a simple DoS attack to taking down the entire machine. The default action for SIGUSR1 is to terminate the target process unless the signal is handled internally. This error has been fixed in Apache 1.3.27. More information and links can be found at and


Two well-known Mac OS X “specific Apache exploits also existed that could be used to reveal sensitive information. The first is related to the lack of case sensitivity in the default Mac OS X file system ”HFS+. Unless Apache is serving from a UFS formatted file system, it incorrectly assumes that HFS+ is case sensitive. As a result, one could create a directory named myprivateinformation that was blocked to everyone but a select few. As long as the resource was accessed exactly as it was defined, the block worked. Unfortunately, however, if you attempted to access the resource using a different case variation, such as MYprivateINFORMATION , the block would not be applied, and the information would be served . To get around this, Apple created the mod_hfs_apple Apache module, which correctly deals with case sensitivity between requests. This module is installed by default on your system, but if you recompile and reinstall Apache, you should also reinstall mod_hfs_apple .

The second Mac OS X “specific security problem deals with the .DS_Store files created by the operating system to hold file-specific information. These metadata files could originally be requested in a URL, potentially revealing sensitive system information ( names , types, permissions, and so on). Apple has since corrected the problem in Mac OS X 10.1.

Apache Configuration

Apache is a very large piece of software that has hundreds of configuration options and possible setups. A number of books have been written about Apache. This section looks at the most common attributes that can be configured and how they affect your system. It is not meant to be a complete reference to Apache. Version 2.0 of Apache is available from, but it is not yet distributed with Mac OS X and lacks support for many popular modules including PHP (which you'll learn about in the next chapter). The current shipping version, 1.3.27, is discussed here.

Apple has done an excellent job of making the Apache Web server configuration manageable for machines with large numbers of personal Web sites. Instead of a single monolithic configuration, like the standard Linux or Windows installation, the server can be configured on two different levels:

  • Systemwide configuration ( path : /etc/httpd/httpd.conf )>. This is the master configuration file. It contains information about the system as a whole: what directories are accessible, what plug-ins are in use, and so on. Changes to the Web server as a whole are included here.

  • User-directory configuration ( path: /etc/httpd/users/< username> .conf ). When the Mac OS X Users System Preference panel creates a new account, it automatically adds a basic configuration file for that user within the /etc/httpd/users directory. This mini configuration file determines the security for the Web pages within a user's Sites folder.

By splitting up the configuration, the administrator can quickly adjust Web permissions on a given account. To edit the user or system configuration, you must either log in (or su ) as root , or use sudo .


Although the user configuration files are stored based on the user's name, they have no real connection to the actual user other than containing the path to a personal Sites folder. These files can contain any Apache configuration option, including those that affect other users. The division by username is for ease of editing only.

Apache approaches configuration in a very object-oriented manner. The configuration files are XML-like, but not compliant, so don't attempt to edit them by using the plist editor. Apache calls each configuration option a directive. There are two types of configuration directives:

  • Global . Global directives affect the entire server ”everything from setting a name for the Web server to loading and activating modules.

  • Container-based . An Apache container is one of a number of objects that can hold Web pages. For example, a directory is a container, a virtual host is a container, and an aliased location is also a container. If you don't know what these are, don't worry, we'll get there. For now, just realize that each container can be configured to limit who has access to what it contains, and what pages within it can do.

Before you look at the security-related "container" directives, it's a good idea to first become familiar with the global directives you're likely to encounter while editing /etc/httpd/httpd.conf . The goal of this chapter is to give you a well-rounded knowledge of Apache configuration, rather than just dump a series of commands on you and leave you to your own resources.

Global Options

The global options can fall anywhere within the server configuration file. If you're running a heavy-traffic Web site you'll definitely want to change the defaults. By default, Apache starts only one server and keeps a maximum of five running at any given time. These numbers do not allow the server to quickly adapt to increased server load.

Table 15.1 documents the most important configuration directives contained in the /etc/httpd/httpd.conf file. They are listed in the order that you're likely to encounter them in the httpd.conf file.


Several of the Apache directives refer to the number of server processes that should be started. These processes are subprocesses of the parent Apache process. When you use apachectl to control the server, you are controlling all the Apache processes.

Table 15.1. Global Apache Directives



ServerType <standaloneinetd>

The Server type determines how Apache starts. Standalone servers are the default. Inetd-based servers use the inetd process to activate a server only when it is accessed. This is inefficient and not recommended for all but the lowest -traffic systems.

ServerRoot <path>

The base path of the Apache binary files.

PidFile <path/filename>

The path (and filename) of the file that should store Apache's process ID.

Timeout <seconds>

The number of seconds that Apache will wait for a response from a remote client. After the time period expires , the connection will be closed.

KeepAlive <OnOff>

Allow more than one request per connection. This is the default behavior of HTTP/1.1 browsers. Shutting this off might result in a higher server load and longer page load times for clients .

MaxKeepAliveRequests <#>

The maximum number of requests that can be made on a single connection.

KeepAliveTimeout <seconds>

The number of seconds to wait between requests on a single connection.

MinSpareServers <#>

Apache automatically regulates the number of running servers to keep up with incoming requests. This is the minimum number of servers kept running at any given time.

MaxSpareServers <#>

The maximum number of servers that will be kept running when there is no load. This is not a limit on the total number of server processes to start; it limits the number of unused processes that will be kept running to adapt to changes in load.

StartServers <#>

The number of servers to start when Apache is first launched.

MaxClients <#>

The MaxClients directive sets an upper limit on the number of servers that can be started at a given time. Keeping this number low can help prevent denial of service attacks from eating up all system resources. A heavy-volume server should rarely need more than 100.

MaxRequestsPerChild <#>

Some systems have memory leaks. A memory leak is a portion of the system software in which memory usage slowly grows in size . Apache recognizes that memory leaks might exist and automatically kills a server after it has processed a given number of requests, freeing up any memory it was using. The server process is then restarted, fresh and ready to go.

LoadModule <modulename> <modulepath>

Loads an Apache module. Many modules will be installed automatically, so you rarely need to adjust anything.

AddModule <modulename.c>

Activates a loaded module.

Port <#>

The port number that the Apache server will use. The standard HTTP port is 80.

User <username>

The user ID under which Apache will run. Apache has the full access permissions of this user, so never, ever, EVER, set this to the root account. Mac OS X has the user www configured for the purpose of running Apache.

Group <groupname>

The group ID under which Apache will run. Like the User directive, this should never be set to a privileged account. If it is, any broken Web applications could compromise your entire computer. You should use the www group for this purpose on Mac OS X.

ServerAdmin <Email Address>

The e-mail address of the Web server operator.

ServerName <Server Name>

If your server has several different hostnames assigned, use the ServerName directive to set the one that will be returned to the client browser. This cannot be an arbitrary name; it must exist!

DocumentRoot <path to html files>

This defines the path to the main server HTML files.The Mac OS X default is /Library/WebServer/Documents .

UserDir <name of user's website directory>

The personal Web site directory within each user's home directory.As you already know, OS X uses Sites ; the default used in most Apache installs is public_html . Removing this directive renders individual users unable to create Web sites.

DirectoryIndex <Default HTML file>

When a URL is specified by only a directory name, the Web server attempts to display a default HTML file with this name.

AccessFileName <Access Filename>

The name of a file that, if encountered in a directory, will be read for additional configuration directives for that directory. Typically used to password protect a directory. The default name is .htaccess .


The default MIME type for outgoing documents. The text/html type should be used to serve HTML files.

HostnameLookups <OnOff>

If activated, Apache stores the full hostname of each computer accessing the server rather than its IP address. This is not recommended for servers with more than a trivial load. Hostname lookups can greatly slow down response time and overall server performance.

TypesConfig <mime type configuration file>

The path to a file that contains a list of MIME types and file extensions that should be served with that MIME type. For example, the type text/html is applied to files with the .html extension. The default MIME types are located at /private/etc/httpd/mime.types .

LogLevel <level>

One of eight different error log levels: debug , info , notice , warn , error , crit , alert , or emerg .

LogFormat <Log Format> <short name>

Defines a custom log format and assigns it to a name. Discussed shortly.

CustomLog <Log filename><short name>

Sets a log filename and assigns it to one of the LogFormat types.

Alias <URL path> <server pathname>

Creates a URL that aliases to a different directory on the server.

ScriptAlias <URL path> <server pathname>

Creates a URL that aliases to a directory containing CGI applications on the server.

Redirect <old URL> <new URL>

Redirects (transfers) a client from one URL to another. Can be used to transfer between URLs on the same server, or to transfer a client accessing a local Web page to a remote site.

AddType <MIME-type> <extension(s)>

Adds a MIME-type without editing the mime.types file.

AddHandler server-parsed <file extension>

Activates server-side includes for files with the specified extension. The default SSI extension is .shtml .

AddHandler send-as-is <file extension>

When activated, files with the defined extension are sent directly to the remote client as is.

AddHandler imap-file <file extension>

Sets the extension for server-side imagemap features. All modern Web browsers use client-side image maps, but if you need compatibility with Netscape 1.0 browsers, you need to use server-side maps.

ErrorHandler <error number> <Error Handler>

Sets an error handler from any one of the standard HTML error messages. This will be discussed in greater detail shortly.

Include <directory>

Reads multiple configuration files from a directory. This is set to /etc/httpd/users .

This is only a partial list of commonly used directives; for a complete list, visit Apache's Web site. To get a handle on configuration, let's take a look at a few different directives in use. These commands, because of their global nature, can be used anywhere within the /etc/httpd/httpd.conf configuration file.


Apache on Mac OS X stores its log files in the directory /var/log/httpd . By default, there are two logs: access_log and error_log .

The access_log file contains a record of what remote computers have accessed Apache, what they asked for, and when they did it. Logging is, obviously, one of the best ways to keep track of inappropriate access to your computer. For example: - - [08/Nov/2002:11:49:07 -0500]   "GET /scripts/..%c1%1c../winnt/system32/cmd.exe?/c+dir HTTP/1.0" 404 295 - - [08/Nov/2002:11:49:10 -0500]   "GET /scripts/..%c0%2f../winnt/system32/cmd.exe?/c+dir HTTP/1.0" 404 295 - - [08/Nov/2002:11:49:13 -0500]   "GET /scripts/..%c0%af../winnt/system32/cmd.exe?/c+dir HTTP/1.0" 404 295 - - [08/Nov/2002:11:49:16 -0500]   "GET /scripts/..%c1%9c../winnt/system32/cmd.exe?/c+dir HTTP/1.0" 404 295 

This log excerpt shows four requests for a cmd.exe file on the Web server. This is a standard Windows IIS attack. Five fields are stored with each log entry:

  • Remote Client . The machine accessing the Apache Web server. In these examples, that client is .

  • Date and Time . A time and date stamp for when the request was made.

  • Request String . The actual request that the remote machine made. Most requests begin with GET and are followed by the resource to retrieve, then the version of the HTTP protocol with which to retrieve it.

  • Response Code . Identifies how the remote server responded to the request. The code 200 shows that the request was successfully served. A 404, on the other hand, indicates that the request couldn't be satisfied because the resource wasn't found. The response codes for HTTP 1.1 are available from

  • Response Size . The number of bytes sent to the remote client to satisfy the request.


There are actually seven fields in this log format. The second and third fields contain a - that indicates a value could not be determined. It is unlikely you'll see values here.

Apache knows this style of access log as the common log format. Use of the LogFormat directive makes log formats completely customizable. The common format is defined as

 LogFormat "%h %l %u %t \"%r\" %>s %b" common 

Each of the %h elements denotes an element to be stored in the log file. The \" is an escaped quote, meaning that a quote will also be stored in that location. You can build a log format by using any of the following:

  • %h . Hostname of the requesting computer.

  • %a . IP address of the remote computer.

  • %r . Request string.

  • %t . Time of request.

  • %T . Amount of time taken to serve the request.

  • %b . Bytes sent.

  • %U . URL path requested.

  • %P . Process ID of the child that served the request.

  • %>s . The last status reported by the server.

  • %{Referer}i . The referring URL (the URL that contained the link to current page).

  • %{User- Agent}i . The string identifies the remote browser.


This is only a partial listing. You can find a complete list of the Apache Log elements at

You define a log format by using the LogFormat line, a string containing the format elements, and a name for the file. For example, to define a log called mylog that stores only the hostname of the remote client for each request, you would use

 LogFormat "%h" mylog 

Except for custom solutions, you'll be best served by one of Apache's default log formats. Although the common log is common, it probably isn't the best thing for doing extensive reporting. A better choice is Apache's combined log format. The combined log format includes referer and user-agent strings with each request. Most Web analysis packages use the combined log style.

To activate a log format, use the CustomLog directive, followed by the pathname for the log and the log name. To activate the combined log format, use it within the /etc/httpd/httpd.conf file:

 CustomLog "/private/var/log/httpd/access_log" combined 

Log files are an important part of any Web server. They can provide important data on the popular pages of the server, errors that have occurred, and how much traffic your system is getting.


The error_log is not shown here because it should contain only startup and shutdown messages. If a security violation or configuration error occurs, it is recorded to this file. In addition, programmers can find detailed information about program errors written to this location.

Container Options

The second type of Apache directives are container based. These directives control how Apache serves a certain group of files. Files are chosen based on pattern, location (URL), or directory, and are denoted by a start and end tag in the Apache configuration file. For example, the /etc/httpd/users/ configuration files define a container consisting of each user's Sites directory. This is the configuration file created for my jray user account (in my case, that file would be /etc/httpd/httpd.conf ):

 <Directory "/Users/jray/Sites/">     Options Indexes MultiViews     AllowOverride None     Order allow,deny     Allow from all </Directory> 

In this example, the directory /Users/jray/Sites is the container. Web pages within this container can use the Indexes and Multiviews options. The AllowOverride , Order , and Allow directives control who has access to the files within this container. This will be explained in more detail shortly.

Besides a directory container, other constructs can also be added to the configuration file(s):

  • Directory . Creates a directory-based container. All files within the named directory are part of the container.

  • DirectoryMatch . Like Directory, but uses a regular expression to match directory names. Check out "So What's A $#!%% Regular Expression, Anyway?!" for a nice introduction to writing and understanding regular expressions: http://www. devshed .com/Server_Side/Administration/RegExp/page1.html.

  • Files . Groups files based on their names. All files matching the specified name are included in the container. The filename should be given exactly, or you should use the ? and * wildcards to match a single unknown character or any number of unknown characters.

  • FilesMatch . Similar to Files, but matches filenames based on a regular expression rather than an exact name.

  • Location . The Location container is similar to Directory, but matches Web content based on a URL, rather than a full-server directory.

  • LocationMatch . If you've been following along, you'll probably guess correctly that LocationMatch is the same as Location, but matches the URL based on a regular expression.

  • VirtualHost . The VirtualHost container defines a virtual server within the main server. For external clients, the virtual host appears identical to any other Web server. To you, the system administrator, it is a directory on your server that gets its very own domain name. You'll see how this can be set up shortly.

Within the container objects, the administrator can add a number of directives to control access to the contents, or whatever special features are available in that location. Table 15.2 includes the container directives you'll encounter most often.

Table 15.2. Apache Container Directives



Options <Option List>

Sets the special abilities of the server container. There are eight possible options; each can be preceded by an optional + or to add or remove it.

AllowOverride < All> < None> <Directive Type>

Chooses the server-defined directives that a local .htaccess file can override. The .htaccess file is used to apply directives outside of the main Apache server configuration and can be edited by any user with access to the directory. For that reason, it is important to allow only trusted users to override options. None disables all overrides ; All allows all server directives to be overridden, or specifies a combination of AuthConfig , FileInfo , Indexes , Limit , or Options to allow these directive types to be overridden.

Order <Deny Allow> , <Deny Allow> mutual-failure

Controls the order in which security controls are evaluated, whether or not the list of allowed hosts ( Allow ) or denied hosts ( Deny ) is checked first.

Allow from <allowed networks all >

A list of IP addresses, networks and subnets, or domain names that can be allowed access to the resource.

Deny from <allowed networks all >

A list of IP addresses, networks and subnets, or domain names that should be denied access to the resource.

AuthType <BasicDigest>

Attaches HTTP authorization password protection to a directory.

AuthName < text string>

Identifies the password-protected resource to the end user.

AuthUserFile <userfile path>

Sets a path to the userfile being used for basic authentication.

AuthDigestFile <digest userfile path>

Sets a path to the MD5 Digest password file used with Digest authentication.

AuthGroupFile <groupfile path>

Sets the path to a file containing group definitions for use with authentication.

Require usergroup valid user <user/group list>

Allows only listed users, groups, or any valid user to access a directory. The users and groups are not Mac OS X users unless you're using mod_auth_apple , discussed shortly. They are created with the htpasswd command.

ErrorDocument <Error ID><Document Path>

Used to substitute a custom-error page in place of the default Apache pages. Use the standard HTTPD error codes (such as 404) and a path to the HTML page to display when the error occurs within the given resource.


The email address of the administrator of a virtual host.


The root-level directory for a virtual host.


The fully qualified domain name for a virtual host, such as .

Now let's see how these directives can be used to refine and secure your Apache Web server.


Mac OS X ships with very restrictive settings for the Apache server already in place. It is unlikely that you'll have any problems if you work with the default settings. This chapter assumes that you want to customize your environment to deal with multiple users and multiple Web sites.

Defining Directory Options

The options that you permit to be used in a directory are critical to your server's security. For example, you don't want to enable every user to execute CGI applications that haven't been approved. Used with a "container" object (such as a directory), the Options directive will help you "lock down" areas of your server.

In short, the Options directive lets you choose what can happen in a given directory. Available Options directives are described in Table 15.3.

Table 15.3. Options Values




Enables CGI execution.


Follows symbolic links in the directory.


Enables server-side includes .


Enables server-side includes without allowing application execution.


Displays a directory listing if an index document doesn't exist.


Uses content negotiation to activates multiple views.


Follows symbolic links only if the owner of the link matches the owner of the linked directory.


Enables all options (except for MultiViews , which must be named explicitly). This is the default.


Disables all options.

In general, you should enable as few of the Options directives as is possible. Providing access to CGIs and Server Side Includes enables users to execute arbitrary code on your server with the user ID of the Web server ( www on Mac OS X). Unless you truly trust your users and their code, you should never provide ExecCGI or Includes options for general users.

Another potentially bad option is FollowSymLinks . This option allows the Web server to process symbolic links in the directory as if the files were actually located in the given directory. Private files, for example, could be "linked" into a Web directory and viewed online, even if they were outside the normal "Web space."

Finally, the Indexes option provides a directory listing if a directory name is specified and no index.html file is present. If you aren't comfortable with users browsing your file system, this should not be active.

Options are specified within a container object and you can give them a + or - prefix to add or remove them. The + and - really come in handy only to add or remove privileges from nested resources. For example, assume you want to provide Indexes and Includes on the default Web location /Library/WebServer/Documents :

 <Directory /Library/WebServer/Documents> Options Indexes Includes </Directory> 

Suppose, however, another directory, /Library/WebServer/Documents/PDFFiles , exists inside the Documents directory and you do not want Indexes activated for it, but do want ExecCGI enabled. In this case, you could modify the Options that you inherit from the main directory by adding the following:

 <Directory /Library/WebServer/Documents/PDFFiles> Options -Indexes +ExecCGI </Directory> 

If you specify options without +/-, you'll override any inherited options from the parent directories. If you're comfortable with this, there's no reason why you can't do it. Inherited options are cleaner, but can lead to difficult-to-read configuration files.

AllowOverride and .htaccess

Apache directives are usually specified within the main /etc/httpd/httpd.conf file or any of the httpd.conf included files (such as the /etc/httpd/users directory). Constantly having to edit the server configuration files can be a bit of a pain, so Apache provides a means of creating an " on-the-fly " directory configuration by placing a file named .htaccess within the directory you want to change.


You can change the .htaccess filename to anything you'd like by using the AccessFileName <htaccess file name> global Apache directive, but .htaccess is the default and standard.

An .htaccess file can contain the same sort of "container" configuration directives as in the main httpd config files and is read each time the Web server accesses a directory containing the .htaccess file. You can create configuration changes in the file without needing to restart the server! This flexibility, however, makes it possible for users to place .htaccess files in their Web directories with contents such as

 Options +ExecCGI 

This would enable the user to execute CGIs without the system administrator even knowing about it. To guard against this happening, you can use the AllowOverride <directive-type(s)> directive to choose exactly what can be overridden in the .htaccess file. There are eight possible override types, documented in Table 15.4.

Table 15.4. The AllowOverride Directive Types

Directive Type



Allow all directive types to be overridden by .htaccess .


Don't allow any directives to be overridden in .htaccess .


Allow all authentication directives to be used within .htaccess .


Provide access to directives controlling document types to the .htaccess file.


Allow .htaccess to control directory indexing attributes.


Let .htaccess provide control over host access with Allow , Deny , and Order .


Allow .htaccess to change the options specified by the Options directive.

For example, if you want to enable any site under the /Users directory to create its own password-protected directories by creating .htaccess files with the appropriate authentication options (which we'll learn next), you can add this to /etc/httpd/httpd.conf :

 <Directory /Users/*>     Options None     AllowOverride AuthConfig </Directory> 

In this example, all Options are disabled, but users are enabled to override AuthConfig directives, and thus password-protect their own resources.


The AuthConfig directives are those directives that deal with setting up Apache authentication. Prefixed with Auth , these include AuthGroupFile , AuthName , AuthType , AuthUserFile , and Require , which we'll cover directly.

Basic Password Protection: htpasswd

Password-protecting a directory is extremely simple. For example, suppose a user wants to password-protect his entire public Web site for development purposes. The first step is to set up a username and password file that will contain the login information for those who are allowed to access the resource. This is accomplished with htpasswd . There are two steps to the process: First, create a new password file with a single user; second, add additional usernames/passwords to it.

To create a new file, use the syntax htpasswd -c <password pathname> <initial username> . For example:

 %  htpasswd -c /Users/jray/.htpasswd jray  New password:  ******  Re-type new password:  ******  Adding password for user jray 

A new password file ( /Users/jray/.htpasswd ) is created, and the initial user jray is added.

Subsequent users can be added to the existing file with htpasswd -b <password pathname > <username> <password> :

 % htpasswd -b /Users/jray/.htpasswd testuser testpass Adding password for user testuser 

The password file .htpasswd now has two entries: the initial jray user and now testuser .

Next, create a directory container that encompasses the files that need to be protected. Because this example is protecting a personal Web site, the container already exists as a <username> .conf file in /etc/httpd/users :

 <Directory "/Users/jray/Sites/">     Options Indexes MultiViews ExecCGI     AllowOverride None     Order allow,deny     Allow from all </Directory> 


This example file has been modified slightly since the initial Mac OS X installation. The options directive includes ExecCGI to allow CGI development to take place.

To this directory container, add AuthType , AuthName , AuthUserFile , and Require directives. You must be root or using sudo to edit the file:

 <Directory "/Users/jray/Sites/">  AuthType Basic   AuthName "Development"   AuthUserFile /Users/jray/.htpasswd   Require valid-user  Options Indexes MultiViews ExecCGI     AllowOverride None     Order allow,deny     Allow from all </Directory> 

The AuthUserFile is set to the name of the password file created with htpasswd , whereas the Require valid-user directive allows any user in the password file to gain access to the protected resource. The AuthName directive provides a simple label describing the resource that will appear when a user connects. To activate the authentication, use sudo /usr/sbin/apachectl restart :

 % sudo /usr/sbin/apachectl restart /usr/sbin/apachectl restart: httpd restarted 

Attempting to access the /Users/jray/Sites directory ( ~jray ) now opens an HTTP authentication dialog, as shown in Figure 15.1.

Figure 15.1. The directory is protected with basic authentication.


In some cases, your access control might become complex enough that you'll want to group your users together to simplify granting access to resources. This is easily accomplished with the AuthGroupFile directive. Group files consist of group records: a single line with the group name, followed by a colon ( : ), and a space-separated list of the users who should be in the group. For example, assume I've defined the users "jray," "agroves", "robyn," and "jackd" in my .htpasswd file and I want to group "jray," "agroves," and "robyn" into a group called "admin." I'd create a new group file name (such as /Users/jray/.htgroup ) with the contents:

 admin: jray robyn agroves 

The group file is plaintext, so creating it doesn't require a special tool (beyond your favorite editor). Now, to provide access to my /Users/jray/Sites directory to everyone in the admin group, I'd change my /etc/httpd/users/jray.conf file to read as follows:

 <Directory "/Users/jray/Sites/">  AuthType Basic   AuthName "Development"   AuthUserFile /Users/jray/.htpasswd   AuthGroupFile /Users/jray/.htgroup   Require group admin  Options Indexes MultiViews ExecCGI     AllowOverride None     Order allow,deny     Allow from all </Directory> 

The AuthGroupFile directive names the location of the group definitions (in this case /Users/jray/.htgroup ), whereas the Requires directive has now been modified with the group clause to force authentication against the users in the group admin .

Unfortunately, Basic authentication is just that ”basic. It is easily sniffable because the username and password are transmitted as plaintext across the network. The name and password are transmitted with each request to a given resource, so potential attackers have a large window of opportunity to scan network traffic for the password.


Digital Cow Software ( has created a System Preference panel called Weblock, which provides a GUI for password-protecting Apache-served directories and managing user and group files. If you find yourself repetitively setting up authentication directives, you might want to take a look at this software.

MD5 Digest Password Protection: htdigest

To partially eliminate the problem with plaintext passwords, Apache also supports MD5 Digest authentication. Defined in, digest authentication does not (at any time) send the cleartext password over the network, but a "digested" version instead. This, however, does not provide a complete security solution in that many early browsers do not support MD5 Digest authentication. Additionally, the digested password is capable of being sniffed, and attackers could potentially use the digested form of the password to gain access to the protected resources. The only real solution for Web site security is SSL, which we'll be getting to shortly.

To activate MD5 Digest authentication for a resource, we'll use the htdigest command-line utility and the AuthUserFile , AuthName , AuthDigestFile , and AuthType Digest directives to provide protection.

First, we'll use htdigest -c <password pathname> <realm> <username> to create a new MD5 Digest password file. The arguments are self-explanatory, except the realm , which you can set to the same value as AuthName ”or, for this example, "Development":

 %  htdigest -c /Users/jray/.htdigest Development jray  Adding password for jray in realm Development. New password:  *****  Re-type new password:  *****  

The password file /Users/jray/.htdigest is created with the initial user jray . Adding additional users requires that you drop the -c option from the htdigest command: htdigest <password pathname> <realm> <username> .

After creating the password file, use the same techniques described in the previous section, "Basic Password Protection: htpasswd," to protect the resources, substituting AuthDigestFile for AuthUserFile and setting AuthType to Digest . For example, to protect the contents of my personal Sites directory, I'd change my /etc/httpd/users/jray.conf file to read as follows:

 <Directory "/Users/jray/Sites/">  AuthType Digest   AuthName "Development"   AuthDigestFile /Users/jray/.htdigest   Require valid-user  Options Indexes MultiViews ExecCGI     AllowOverride None     Order allow,deny     Allow from all </Directory> 

The Require directive functions identically to what you've already seen in Basic authentication. You can Require individual users, groups, or any valid user.

Authenticating Against User Accounts with mod_auth_apple

Using the basic and MD5 authentication mechanisms is fine in many cases, but you may find yourself wanting to protect resources based on actual user accounts on your computer. Although it's simple enough to create a password file for each user, these passwords will not be updated as users update their Mac OS X passwords. In some cases (such as running a Web server with users that access their sites through WebDAV) managing all the necessary password files can truly become a hassle. The best solution would be to provide an authentication mechanism by which resources could be protected by actual system accounts and system passwords. This is entirely possible courtesy of Apple's mod_auth_apple Apache module.

Included with Mac OS X Server by default, Mac OS X client users can download and install mod_auth_apple with very little trouble. There are two components to the install: First, a missing header file Security/checkpw.h must be copied from the Darwin CVS repository or mirror, then the source code for mod_auth_apple can be downloaded and installed.

The header file can be downloaded directly from Apple at, but you'll need to register before downloading. Alternatively, download the header from After downloading, make a new directory /usr/include/Security , and copy the header file to the new location:

[View full width]
[View full width]
# curl -O " src/Security/checkpw/ graphics/ccc.gif checkpw.h?rev=" # mkdir /usr/include/Security # mv checkpw.h /usr/include/Security/

Next, download the latest mod_auth_apple package from, unarchive it, then enter the source distribution directory:

 #  tar zxf mod_auth_apple-XS-10.2.tgz  #  cd mod_auth_apple  

Be sure to check the Apple README file for installation instructions; they may change between versions. The instructions shown here are "modified" from Apple's directions so that the software configures automatically. Use make followed by apxs -i -a to compile and install the module:

[View full width]
[View full width]
# make /usr/sbin/apxs -c -Wc,"-traditional-cpp -Wno-four-char-constants -F/System/Library/ graphics/ccc.gif PrivateFrameworks -DUSE_CHKUSRNAMPASSWD" -Wl,"-bundle_loader /usr/sbin/httpd -framework graphics/ccc.gif Security" -o mod_auth_apple.c gcc -DDARWIN -DUSE_HSREGEX -DUSE_EXPAT -I../lib/expat-lite -g -Os -pipe graphics/ccc.gif -DHARD_SERVER_LIMIT=2048 -DEAPI -DSHARED_MODULE -I/usr/include/httpd -traditional -cpp graphics/ccc.gif -Wno-four-char-constants -F/System/Library/PrivateFrameworks -DUSE_CHKUSRNAMPASSWD -c graphics/ccc.gif mod_auth_apple.c ... # apxs -i -a [activating module 'apple_auth' in /private/etc/httpd/httpd.conf] cp /usr/libexec/httpd/ chmod 755 /usr/libexec/httpd/ cp /private/etc/httpd/httpd.conf /private/etc/httpd/httpd.conf.bak cp /private/etc/httpd/ /private/etc/httpd/httpd.conf rm /private/etc/httpd/

The mod_auth_apple module is now compiled and installed. Using it is identical to the examples we've already seen for Basic and Digest authentication, except no password file is needed. For example, to protect a resource so that only my account (jray) can access it, I would add directives like this to the appropriate place in /etc/httpd/httpd.conf , or to a separate .htaccess file in the directory I want to protect:

 AuthType Basic Authname "Whatever" Require user jray 

To verify against any account on the machine, one would replace Require user jray with Require valid-user . Alternatively, to validate against a group, Require group <groupname> could be employed.

Unfortunately, this is Basic authentication ”passwords are not encrypted, and the slightly-more-secure digest mode is not even available. The only truly secure way to use mod_auth_apple is to encrypt the entire authentication sequence by using HTTPS and mod_ssl . This will be your next stop in setting up a secure Web server.

Apple added a new module ( mod_auth_digest_apple ) to the Darwin project that is capable of handling digest authentication. You can now download and install it using the same procedure you used with mod_auth_apple .

Restricting Access by Network

To create more stringent control over the users who can access a given resource, use Allow and Deny to set up networks that should or shouldn't have access to portions of your Web site. This is extremely useful for setting up intranet sites that should be accessible only by a given subnet. For example, assume that you want to restrict access to a resource from everyone except the subnet 192.168.0.x (having the netmask The following rules define the access permissions:

 Allow from Deny from all 

Because there isn't an ordering specified, what really happens with these rules is ambiguous. Is a connection from allowed because of the allow statement? Or denied because all the connections are denied?

To solve the problem, insert the Order directive:

 Order Deny,Allow Allow from Deny from all 

With this ordering, an incoming connection is first compared to the deny list. Because all access is denied by default, any address matches this rule. However, the Allow directive is used for the final evaluation of the connection and allows any connection from the network with the subnet .

The Allow and Deny directives can also be used based on domain name, FQDN, or a partial IP address. One can, for example, provide write rules such as

 Deny from 10.0.1 

Here, requests from the machine would be denied, as would requests from any host in ( , , and so on), and any host with an IP address that starts 10.0.1 .

To add one additional option to the mix, one can use the mutual-failure ordering option. The rarely used setting ensures that both the Allow and Deny directives must evaluate to true for the resource to be displayed. For example, assume that you have a corporate intranet that should be visible to everyone on your local domain ( ), except some guest workstations in the lobby ( and ). In this case, you would use Order mutual-failure with the following Allow and Deny directives:

 Order mutual-failure Allow from Deny from 

Using different orderings and different Allow/Deny lists, you can lock down a Web site to only those people who should have access, or disable troublesome hosts that misuse the site.


As with any change to the Apache configuration file, you must use /usr/sbin/apachectl to restart the server.

An alternative to restarting is to add an .htaccess file to the directory you want to protect. This file can contain any of the standard directory container directives and will be read automatically when Apache attempts to read any file from the directory.

Choosing Between Multiple Access Controls: Satisfy

When using authentication directives and the Allow directives, you may run into a situation where you want only one or the other to be true, but not both. For example, suppose you've protected a directory with the following:

 <Directory "/Users/jray/Sites/">     AuthType Digest     AuthName "Development"     AuthDigestFile /Users/jray/.htdigest     Require valid-user     Order Deny,Allow     Allow from     Deny from all </Directory> 

In this example configuration, my directory is protected so that a request must come from the subnet and have a valid username and password given. Suppose, however, one wanted to deny access to everyone except the subnet or anyone who enters a valid username and password. If any of security controls are satisfied, the Apache should provide access to the user, rather than enforcing all the controls.

This change is quite simple: Add the Satisfy any / all directive. Satisify all , the default, requires that both the user authentication and Allow limits be satisfied. Satisfy any , on the other hand, allows access to the resource if either of the limits is satisfied. Thus, the configuration becomes

 <Directory "/Users/jray/Sites/">     AuthType Digest     AuthName "Development"     AuthDigestFile /Users/jray/.htdigest     Require valid-user     Order Deny,Allow     Allow from     Deny from all     Satisfy any </Directory> 
Disabling Rendezvous Advertising in Apache

Starting in Mac OS X 10.2.4, Apple included a special mod_rendezvous_apple module that advertises your main Web site and individual users' Sites directories via Rendezvous to compatible browsers such as Safari and Chimera.

Although not a security risk per se (the sites are available via HTTP, after all), this might not be a desired behavior on your network. You can disable the Rendezvous support by commenting out the following lines in your /etc/httpd/httpd.conf file:

 LoadModule rendezvous_apple_module libexec/httpd/ AddModule mod_rendezvous_apple.c 

Presumably Apple will add an interface to this at some time in the future, but for now, it seems a bit inappropriate for all machines to be advertising their services to the network unbeknownst to the machine's operator.


Mac OS X Maximum Security
Maximum Mac OS X Security
ISBN: 0672323818
EAN: 2147483647
Year: 2003
Pages: 158 © 2008-2017.
If you may any questions please contact us: