Chapter 6. Security and Access Control

Understanding the Need for Access Control

Access control is a requirement for many websites. This means that certain content or areas of the website are only accessible to clients that come from a particular range of IP addresses or provide a valid username and password, for example. Access control can be implemented at a variety of levels, including at the operating-system level with packet filtering rules and at the web application level with forms, sessions, and cookies. This chapter deals exclusively with implementing access control, authentication, and authorization using the bundled Apache modules. This chapter also explains how different configuration settings can affect the security of your server and details a number of steps that you can take to improve it.

Apache provides a number of modules that allow you to control access to your content. The two main ones are mod_access, which allows controlling access based on the origin IP address and other characteristics of the request, and mod_auth, which authenticates users based on a username and password.

There are a number of other modules that will be mentioned in this chapter but will not be covered in detail because they are not used as often.

Differences Between Apache Versions

Apache’s authorization and authentication framework was completely overhauled in Apache 2.2. Although most of the changes have occurred at the source code level, there are a number of user-visible changes. For the sake of clarity and because most of the basic concepts still apply, this chapter will primarily describe Apache 1.3 and 2.0 configuration. The Apache 2.2-specific changes will be discussed in the “Apache 2.2” section, later in the chapter.

Understanding Basic and Digest Authentication

You authenticate users of your website for tracking or authorization purposes. The HTTP specification provides two authentication mechanisms: basic and digest. In both cases, the process is the following:

  1. A client tries to access restricted content in the web server.

  2. Apache checks whether the client is providing a username and password. If not, Apache returns an HTTP 401 status code, indicating that user authentication is required.

  3. The client reads the response and prompts the user for the required username and password (usually with a pop-up window).

  4. The client retries accessing the web page, this time transmitting the username and password as part of the HTTP request. The client remembers the username and password and transmits them in later requests to the same site, so the user does not need to retype them for every request.

  5. Apache checks the validity of the credentials and grants or denies access based on the user identity and other access rules.

In basic authentication, the username and password are transmitted in clear text, as part of the HTTP request headers. This poses a security risk because an attacker could easily peek at the conversation between server and browser, learn the username and password, and reuse them freely afterward. Digest authentication provides increased security because it transmits a digest instead of the clear-text password. A digest algorithm is a mathematical operation that takes a text and returns another text, a digest, which uniquely identifies the original one. If a text changes, so does the digest. The digest is based on a combination of several parameters, including the username, password, and request method. The server can calculate the digest on its own and check that the client knows the password, even when the password itself is not transmitted over the network.

Unfortunately, although the specification has been available for quite some time, not all browsers support digest authentication or do it in a compatible manner.

In any case, for both digest and basic authentication, the requested information itself is transmitted unprotected over the network. A better choice to secure access to your website involves using SSL, as explained in Chapter 7.

Introducing Apache Access Control

<Directory /usr/local/apache2/htdocs/private>
    Order Allow, Deny
    Allow from 192.168.0 example.com
    Deny from guest-terminal.example.com
</Directory>

The example shows a sample configuration using IP and hostname-based access control with mod_access. Allow directives specify which individual IP addresses, networks, and hostnames have access to the content. Deny directives specify which ones will be denied. The Order directive specifies how Allow and Deny directives are evaluated.

In this example, the Order Allow, Deny directive specifies that Allow directives are to be evaluated first and Deny directives will be evaluated last. The order in which the directives are evaluated is important, and in this case the Deny directive will take precedence. Also, Order Allow, Deny ensures that if the client does not match any Allow directive, it will be denied access by default. Don’t worry if you are a bit confused about how access control works. It is really easy once you understand the way directives are evaluated.

Introducing Apache Authorization and Authentication Configuration

<Directory /usr/local/apache2/htdocs/private>
AuthType Basic
AuthName "Password Protected Area"
AuthUserFile /usr/local/apache2/conf/htusers
Require user admin
</Directory>

The listing shows a sample configuration snippet that password-protects a directory. AuthType defines the authentication type: in this case, HTTP basic authentication. AuthName associates a text with the area that will be password-protected. This text will be presented to the user when the browser prompts her for a password (usually in a separate pop-up window). The AuthUserFile points to the user database and the Require directive specifies a user who will be granted access upon successful authentication. The following sections include more details on the previous example as well as instructions on how to create and manipulate the user database and how to combine IP and user-based control access, as shown in the “Combining Access Control Methods” section.

Creating a User Database

htpasswd -c file userid

To create a user database (also known as a password file), you can use the htpasswd utility included with Apache. The syntax to create a new password file and add a user to it on Unix is shown in the example. On Windows, you will need to use

htpasswd.exe -cm file userid

If you want to add a new user to an existing password file, the syntax on Unix is simply

htpasswd file userid

and on Windows

htpasswd.exe -m file userid

You will be asked for a password and it will be added to the user database.

You should not keep the password file in any directory accessible from the Web. You should not use -c when adding users to an existing file, as this will destroy the previous contents.

As an example, the following line creates a password file named htusers and adds a user named admin:

htpasswd -c /usr/local/apache2/conf/htusers admin

Using Require to Authorize Users and Groups

<Directory /usr/local/apache2/htdocs/private>
    AuthType Basic
    AuthName "Password Protected Area"
    AuthUserFile /usr/local/apache2/conf/htusers
    AuthGroupFile /usr/local/apache2/conf/groups
    Require group administrators
</Directory>

You can instruct Apache to allow access to any valid user in the database that successfully authenticates with

Require valid-user

If you need to authorize only a certain group of users, you can explicitly list them in the arguments to Require:

Require user userid1 userid2

If you have a great number of users, a more convenient way to accomplish this is to use the AuthGroupFile directive. This directive points to a file containing group information in the following format:

groupname: userid1 userid2 userid3 [..]

For example

administrators: admin boss
users: admin boss user1 user2

The example at the beginning of this section shows a configuration snippet that allows access only to those users that successfully authenticate themselves and also belong to the group administrators. In this example, that would mean users admin and boss.

Handling a Large Number of Users

<DirectoryMatch /home/*/public_html>
   AuthType Basic
   AuthName "Private Area"
   AuthDBMUserFile /usr/local/apache2/conf/dbmusers
   AuthDBMGroupFile /usr/local/apache2/conf/dbmusers
   AuthDBMAuthoritative on
   Require group student faculty
</DirectoryMatch>

The mod_auth_dbm module is equivalent in functionality to mod_auth, but stores user data in a file-based database, speeding data lookup when there is a large number of users. This module provides a number of directives such as AuthDBMAuthoritative, AuthDBMUserFile, and AuthDBMGroupFile, which are equivalent in syntax and functionality to the plain-text ones provided by mod_auth. To manipulate the user and group files, you will need to use htdbm and dbmmanage, the counterparts to mod_auth’s tools. Note that group and user data can be stored in the same database, as shown here.

Allowing Access Only to Specific IP Addresses

<Directory /usr/local/apache2/htdocs/private>
    Order Allow, Deny
   Allow from 192.168.0
</Directory>

Sometimes, it is desirable to restrict access to certain content (such as a company’s internal website) to specific IP addresses, such as those coming from an internal network. This example will allow access to the directory /usr/local/apache2/htdocs/private and its subdirectories only to clients with IP addresses in the range 192.168.0.1 to 192.168.0.254.

The argument passed to the Directory container must literally match the filesystem path that Apache uses to access the files.

The line Order Allow, Deny denies access by default and only clients that match the Allow directive will be granted access. The Allow directive can accept multiple individual IP addresses or a certain address range of IP addresses. Check the directive reference for details.

You can also allow access only to specific IP addresses using the same code in a .htaccess file in /usr/local/apache2/htdocs/private:

Order Allow,Deny
Allow from 192.168.0

Denying Access to Specific IP Addresses

<Directory /usr/local/apache2/htdocs/private>
    Order Deny,Allow
   Deny from 192.168.0.2 192.168.0.5
</Directory>

Conversely to what was explained in the previous section, it is possible to allow general access but deny access when the request comes from a specific IP address or range of IP addresses. This is useful, for example, to block specific machines or web crawlers that have been a source of problems or bandwidth abuse.

This example will allow access to the directory /usr/local/apache2/htdocs/private and its subdirectories to anybody except clients with the IP addresses 192.168.0.2 and 192.168.0.5.

Allow and Deny can also restrict access based on the presence of an environment variable, as explained in the “Restricting Access Based on the Browser Type” section, later in this chapter.

Chapter 9 deals with additional ways of restricting or slowing down access to misbehaving clients.

Combining Access Control Methods

<Location /restricted>
 Allow from 192.168.200.0/255.255.255.0
 AuthType Basic
 AuthUserFile /usr/local/apache2/conf/htusers
 AuthName "Restricted Resource"
 AuthAuthoritative on
 Require valid-user
 Satisfy any
</Location>

You can combine different access control methods using the Satisfy directive. For example, the configuration shown here requires users to either come from an internal, authorized address OR provide a valid username and password.

If you would like to require both that user come from a certain internal address AND provide a valid username and password, you will need to use Satisfy all.

Customizing Your Access Denied Page

When a request gets an access denied response from the web server, the user will be presented with a hardcoded server-generated error message. You can customize the message the user receives using the ErrorDocument directive in three different ways:

You can show the user a custom message, as in the following example

ErrorDocument 403 "You do not have permission to
access this file"

if you are using Apache 2 or

ErrorDocument 403 "You do not have permission to
access this file

if you are using Apache 1.3 (notice that there is only one double-quote, at the beginning of the string).

Alternatively, you can redirect the request to a local URL-path with a custom message:

ErrorDocument 401 /login_failed.html

In this case, the file passed to the directive as the second argument is a path starting with a slash (/), relative to the value specified in the directive DocumentRoot.

Finally, you can redirect the request to an external URL:

ErrorDocument 404 http://www.example.com/page
_not_found.html

These examples referred to different 400 HTTP return codes, which indicate there was an error resolving the request, such as the user not providing a correct username and password. You can of course do the same for other common HTTP codes such as internal server errors. You can find a complete listing of HTTP return codes in the appendix.

Note

Some versions of Microsoft Internet Explorer (MSIE) will by default ignore server-generated error messages when they are less than 512 bytes in size, so be sure to specify a message greater than that. You can learn more about this issue in this Microsoft Knowledge Base article http://support.microsoft.com/default.aspx?scid=kb;en-us;Q294807.

Putting Users in Control

If you have multiple users publishing content in your Apache installation, it is very convenient to allow them to password-protect their own directories using .htaccess files, described in Chapter 1. This mechanism has a performance penalty but relieves you of the task of providing access to or updating the Apache configuration file or user databases each time a change is required.

In the appropriate directory sections of your Apache configuration file, you will need to add

AllowOverride AuthConfig Limit

This will enable your users to create their own .htaccess configuration files and place their own access control and authorization-related directives there.

Conversely, you can prevent per-directory configuration changes with the following global setting:

<Directory />
AllowOverride none
</Directory>

This has the added bonus of improving performance, since Apache does not need to look for the existence of per-directory configuration files for each file requested. Alternatively, you could restrict the type of configuration options that are allowed. For more information, check the documentation for AllowOverride.

Denying Access to System and Sensitive Files

<Files ~ "^.ht">
 Order allow,deny
 Deny from all
</Files>

There are certain types of files that we do not want our visitors to access under any circumstances, because they may contain passwords or other sensitive information. These include example backup files created by Unix text editors, per-directory configuration files, and so on. You may want to deny access to them using explicit configuration settings such as those shown here, which are included by default in the Apache configuration and deny access to .htaccess and .htpasswd files.

It is also possible to prevent the server from delivering unintended content by configuring it not to follow symbolic links. For this purpose, use the FollowSymLinks and SymLinksIfOwnerMatch arguments to the Options directive, as described in its documentation.

You may also want to disable mod_speling, explained in Chapter 4 as sometimes it may accidentally expose the names of files not intended for publishing when a misspelled URL could match multiple documents.

See also the section on how to restrict access to directory listings.

Restricting Program Execution

CGI programs can be a security risk. It is advisable that you disable CGI execution or at least restrict it to specific directories. For that purpose, do not use AddHandler directives to globally enable CGI execution of certain file extensions.

Similarly, mod_include allows execution of CGIs and external commands using Server Side Includes. They are disabled by default by the Options -IncludesNoExec directive. If possible, make sure that the directories containing CGI scripts are writable only by the superuser and not by anyone else, and especially not by the user Apache is running as.

On a related note, you should make sure that, whenever possible, the document tree is read only. This will prevent an attacker from creating a file that can later be executed. An example of this would be to introduce a file containing PHP code in a PHP-enabled server. Also, make sure to password-protect DAV-enabled directories and do not make website contents available through other services such as FTP.

Preventing Abuse

There are a number of ways in which you can restrict or slow down access to all or part of your website. This is useful when you do not want certain content to be available in search engines or when a misbehaving web crawler consumes too many resources. These methods are explained in detail in Chapter 9 which also covers how to avoid or minimize denial-of-service attacks. Denial-of-service attacks are designed to prevent or severely impair the ability of your server to answer your users’ requests. A number of Apache modules and settings can help to reduce in part those issues.

Disabling Directory Listings

<Directory /usr/local/apache2/htdocs/private>
    Options -Indexes
</Directory>

Apache allows you to define special index files with the DirectoryIndex directive. When a request is made by a client that maps into a directory path, Apache looks for one of those index files (usually named index.html or home.html) and returns it to the browser. Alternatively, if no such file is found, Apache will return an HTML page containing a listing of the directory. While this is useful during development, or when making available a file repository, it can also provide the names of files that you do not want published or indexed by search engines (such as backup files). You can disable directory listings by disabling the mod_autoindex module or using the Options directive as shown here.

If per-directory configuration files are enabled, you can also place the example in an .htaccess file.

Changing the Server: Header

ServerTokens Prod

Apache returns a Server: header with every request. By default, this header includes information about the server name, version, and platform. Other modules present in the server, such as SSL, PHP, or mod_perl, may add additional entries to the server string containing the module name and version. You can change or restrict the server header information using the ServerTokens directive. While it is always good to minimize the amount of information about the server configuration that is leaked to the external world, changing the server string will not bring much additional security: Most automated scan and attack tools will ignore this information and just probe for vulnerable scripts and modules one after another, regardless of the version and modules reported.

Preventing Hotlinking to Your Images

RewriteEngine On
RewriteCond %{HTTP_REFERER}
    !^http://(www.)?example.com/ [NC]
RewriteCond %{HTTP_REFERER} ^http:// [NC]
RewriteCond %{HTTP_REFERER} !^$
RewriteRule .(jpg|jpeg|gif|png|bmp)$ - [F]

Sometimes, people will link directly from their website to resources on your server, such as logo images and binary program files. This is called hotlinking and in certain situations, you may want to prevent this from happening. For example, a certain online-merchant realized that half its traffic (and bandwidth bill) was from other sites hotlinking to its images for credit card companies and countries.

You can prevent people from hotlinking to your images by requiring that the requests to the images come from your server. You can do so using mod_rewrite. The example in the listing here will return a Forbidden answer to any request made for image files (identified by their extensions in the fourth RewriteCond line) whose HTTP_REFERER header does not match your domain name (first RewriteCond line). In addition, since certain browsers may not send a valid referer field or not send one at all, additional checks are performed to see that the referer field starts with http:// and is not blank (second and third RewriteCond lines).

Restricting Specific HTTP Methods

<Directory /home/*/public_html>
 AllowOverride FileInfo AuthConfig Limit
 Options MultiViews Indexes SymLinksIfOwnerMatch
      IncludesNoExec
 <Limit GET POST OPTIONS PROPFIND>
  Order allow,deny
  Allow from all
 </Limit>
 <LimitExcept GET POST OPTIONS PROPFIND>
   Order deny,allow
   Deny from all
 </LimitExcept>
</Directory>

You can control access to your server based on the HTTP method of the request using <Limit> and <LimitExcept> directives. This example, taken from the default Apache configuration file, shows how to allow read-only methods and deny requests for any other methods that can modify the content of the file system, such as PUT. The <Directory> section identifies per-user directories that can contain web pages, as explained in Chapter 8. The next two lines restrict the configuration settings that can be changed by users and other security settings. The <Limit> section allows access by default to those HTTP methods that are read-only, such as GET and POST. The <LimitExcept> section does the opposite, denying access to any other method, without explicitly having to enumerate them.

This is particularly useful in the context of allowing your users to administer their own content, as covered in Chapter 8.

Restricting Access Based on the Browser Type

SetEnvIf User-Agent ^EvilSearchEngine broken_crawler
<Directory /usr/local/apache2/htdocs>
    Order Deny,Allow
    Deny from env=broken_crawler
</Directory>

You can restrict access based on the browser type or any other header information or connection property by using environment variables with Allow and Deny.

In this case, browsers with a User-Agent header beginning with EvilSearchEngine will be denied access, and all others will be allowed. This is accomplished by using the SetEnvIf directive to conditionally set an environment variable named broken_crawler if the User-Agent header of the request (first argument) matches a certain regular expression (second argument). Later on, you can conditionally apply Deny and Allow directives based on the existence of that environment variable, identified by an env= prefix. Bear in mind that, although this technique will work most of the time, since the headers are sent by the client, headers cannot really be trusted.

Using Location and Directory Sections

The Order directive controls the order of access directive processing only within each phase of the server’s configuration processing. This implies, for example, that an Allow or Deny directive occurring in a <Location> section will always be evaluated after an Allow or Deny directive occurring in a <Directory> section or .htaccess file, regardless of the setting of the Order directive.

Take into account that symbolic links and Alias directives may affect your authentication setup. For example, your restrictions may be bypassed if your access control directives are placed inside a <Location> container but the content is also accessible through additional URL mappings.

Additional Authentication Modules

In addition to the main modules that provide IP-based access control and the standard basic and digest authentication, Apache bundles a number of other authentication modules, such as

  • mod_auth_anonProvides for FTP-style “anonymous” user access to file-download areas.

  • mod_auth_ldapThis module, available in Apache 2 and later, allows authenticating users against an LDAP directory.

  • mod_sslThis module is covered in detail in Chapter 7 and allows you to use certificate-based client authentication.

One of the virtues of Apache is that it is modular and extensible. A number of third-party modules have been developed that allow Apache to interface with existing authentication frameworks such as Windows domains, LDAP, PAM, and NIS, and user information stored in a variety of databases such as MySQL, PostgreSQL, Oracle, and others. You can find most of those modules at http://modules.apache.org and http://freshmeat.net.

You can always manage authentication at the application level. Usually, this is accomplished by requesting the username and password in a web form and, upon validation, assigning a cookie that authenticates the user for the rest of the session. This is how popular portal and ecommerce sites manage their personalization features.

mod_security

This module deserves a special mention. It is, in essence, an HTTP-level firewall. It allows you to inspect HTTP requests and perform all kind of monitoring, reporting, and access-control operations. It can detect and block common application-level attacks such as those involving SQL-injection and path transversal. You can find more information about this module at http://www.modsecurity.org.

Apache 2.2

<Location /combined>
    AuthType Basic
    AuthName "Restricted Access"
    AuthBasicProvider file ldap
    AuthUserFile /usr/local/apache2/conf/htusers
    AuthLDAPURL ldap://example.com/o=Sample
    Require valid-user
</Location>

Apache 2.2 includes significant changes to how authentication and authorization are implemented in Apache. The changes mostly relate to work that was performed in existing modules to clearly separate methods (basic and digest authentication) and providers (file, LDAP, or SQL backends, for example). Before, both functions were mixed in each module’s implementation.

For example, mod_authn_file implements authentication against text files and mod_authn_dbm authenticates against database files. They can be combined with mod_auth_basic and mod_auth_digest, which in turn implement Basic and Digest HTTP authentication. Additional modules provide authorization functionality that authorizes users based on data stored in LDAP or SQL databases or files, as well as on file ownership or origin IP addresses.

Providers can be mixed and matched, as shown in the example at the beginning of this section. A new module, mod_authn_alias, allows you to define complex authentication setups that can be referred by name elsewhere in the configuration file. This allows you for example to authenticate the same resource against two different LDAP servers.

Keeping Up to Date with Apache Security

As with any other server software, you need to keep up to date with new Apache releases, making sure you are aware of security issues and the patches or workarounds to address them. These URLs will help you with this task.

Security Checklist

It is often said that security is a process, not a feature. To keep your Apache installation secure, you will need to keep up to date with Apache security advisories and monitor your error and access logs. Since Apache does not run isolated from its environment, you will need to do the same at the operating system and application level. In fact, most remotely exploitable problems with Apache are due to problems at the application level, such as vulnerable wiki, PHP libraries, and components.

Having said this, the following is a step-by-step list of measures you can take to secure a default Apache installation.

Disable Unneeded Modules

The first step is to disable all modules that you are not using. If you compiled Apache with loadable module support, you can comment out the directives that load specific modules. You may need to comment out other directives present in the configuration file that relate to the disabled module. Here is a short list of the most important modules that you should remove if you are not using them, roughly in order of importance:

  • PHP, mod_python, mod_mono, mod_perl, and any other server side language modules. Of course, you should only disable PHP if you are not using Apache to run PHP-based applications.

  • mod_include, which provides Server Side Includes support.

  • mod_cgi, which provides support for invoking external programs.

  • mod_ssl, used to provide SSL/TLS support for securing communications between the browser and Apache.

  • mod_proxy, which, if incorrectly configured, can allow outsiders to use your server to relay requests.

  • mod_deflate, an Apache 2 filter for compressing output on the fly.

  • mod_suexec, used to execute external programs under user IDs different from the one Apache is running as.

  • mod_userdir, which allows users in Unix systems to host their own pages.

  • mod_rewrite, which allows arbitrary mapping and rewriting of incoming URLs.

Additionally, in Apache 1.3 you can explicitly disable specific compiled-in modules by using the ClearModuleList directive and then explicitly enable modules using the AddModule directive.

Remove Sample Scripts

Most web server-side software and development environments include sample applications and scripts for demonstration or testing purposes. While useful, these samples are usually not coded with security in mind, and can be vulnerable to several attacks, mostly related to the program not properly escaping user input. These flaws often result in an attacker being able to execute arbitrary system commands, revealing the contents of other files, or being able to modify the database.

Make sure you remove all sample scripts and demo accounts shipped with your application servers, as well as your development environment and other web-based software you may have installed.

Limit or Disable CGI Execution and SSI

If you do not require CGI-script support, you should disable mod_cgi. If you require CGI support, you should limit the ability to execute scripts to specific directories. For example, you should scan your configuration for ScriptAlias directives and Options directives with ExecCGI arguments and make sure they are properly configured. Make sure that directories marked as containing executable scripts are not writable by others. You may also consider using the suExec CGI wrapper, included with Apache.

The same rationale can be applied to Server Side Includes functionality, which is provided by mod_include and allows execution of external commands, unless disabled by Options -IncludesNoExec.

Check File Permissions

On Unix systems, Apache is usually started as root; does a certain number of operations, such as binding to the appropriate port; and then changes its user ID to the one specified with the User directive. Because there are certain operations performed as root, it is critical to make sure that the log and configuration files, as well as the directories containing them, are not writable by other users. Make sure directories being marked as containing executable scripts or that can contain PHP scripts are not world writable and are not accessible through FTP or WebDAV, for example.

Limit or Disable Proxy Functionality

As with CGIs, you need to disable or restrict proxy support in your Apache installation. Otherwise, an open proxy can be used to perform attacks targeted at other websites or even to relay mail spam. If you are running Apache as a reverse proxy, you can disable “regular” proxy (forward-proxy functionality) with

ProxyRequests off

Restrict Access to Your Server by Default

The server should be configured in such a way that by default it denies access to documents on the server unless access is explicitly enabled. The following configuration snippet, extracted from the Apache Documentation, does just that:

<Directory />
    Order Deny,Allow
    Deny from all

</Directory>
<Directory /usr/local/apache2/htdocs>
    Order Deny,Allow
    Allow from all
</Directory>

See also earlier sections on how to disable directory listings.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.17.181.61