http://www.brianhouk.com

Secure Apache Configuration

brian at brianhouk dot com

If you're running a network of any type chances are that you're going to have a webserver running on it. Chances are also very good that it is running on a unix-like OS and that if it is running a httpd server it is running Apache. Apache is the most widely used webserver out there, as well it's had a pretty good security record compared to other webservers out there.

Starting off:

Usually apache will be started by the root user, this will have to be done if you're planning on binding apache to any port below 1024. After that the server will run as a defined user. Out of habit now I make it run as the user web on my servers. That is specified in httpd.conf or httpsd.conf with the User Directive. As with any other commands which root executes you should take measures that any commands executed can't be modified from non-root users. Not only should the files only be writeable by root, but the directories should share that as well. For example ServerRoot is /www then it's suggested you create the directory as root with something like the following set of commands: mkdir /www; cd /www; mkdir bin conf logs; chown root:root bin conf logs; chmod 755 bin conf logs and now you're all done. Also after you're done with installing apache you should ensure that it's protected as well. chown root:root /www/bin/httpd; chmod 511 /www/bin/httpd, or httpsd in the event you're using it. The permissions on the htdocs directory which would be /www/htdocs in this scenario can be somewhat more lax as root shouldn't ever be executing anything out of that directory or any of its subdirectories. It's common practice to not allow any non-root users to modify any of the commands which root may be executing. For example if someone has write access to the httpd binary they may replace it with a binary that executes arbitrary code. As for the logs directory if it's writeable by non-root users someone could create a symlink to some other system file in that directory and then root may overwrite that file with arbitrary data.

SSI (server side includes)

Server Side Inclues can be configured so that users can execute arbitrary programs on the server. That's really nice and as an administrator it should make you happy that it can do that. A solution for you in this scenario is to use the IncludesNOEXEC option in the Options directive.

CGI

Non Script Aliased CGI, well for the most part I think that this is a stupid idea and I wouldn't allow it in any scenario. In order to do this you're going to have to trust your users ability to write secure CGI Scripts, yeah so don't do it.

Script Alias'ed CGI, You can and should limit CGI execution to certain directories. This gives the administrator control over what goes into those directories . This is much more secure than allowing script execution in every directory, this way only people who have write access to the specified directory which CGI will execute in will have the ability to execute CGI scripts. Still with this setup, users the admin either trusts or the admin knows can write clean CGI code should be able to write to this directory.

General, unfortunately you don't have time to audit every bit of code which users are going to be putting into their CGI directories. So as as systems administrator you do have to take some trust in people who you're allowing to put CGI scripts on your webserver. Unless configured otherwise all cgi scripts on the server run as the same user. The user which the webserver runs as, so on my machine it runs as the user web. Just use your imagination a bit and think of what could be done with this ability, you could write a CGI script to totally trash another users database on the local machine granted they don't have it secured correctly. One program which can and should be used in the event that you have multiple users or multiple domains executing cgi scripts is using suEXEC which should be included in your default apache install. suEXEC allows different cgi scripts to run as different users. If you're not liking suEXEC then CGIWrap may be something which you'll want to look into.

There are a few modules which apache comes with in reguards to security.

mod_access
This allows you to list domains or ip addresses / networks which can be permitted or denied access to a resource on the httpd server. For example the following lines would deny access to your intranet from everyone except those coming to your website from the subnet 10.3.2.0/24
<Directory /www/htdocs/intranet>
Order deny, allow
Allow from 10.3.2.0
</Directory>

Now I know what you're saying why can people even access your intranet if they're not coming from inside your intranet. Well, when apache by default binds to all IP(S) on the machine it's running on if not configured correctly could make it so that people externally could access your internal files. This is if apache is not configured correctly, in the event that say this machine had an external and internal interface and you didn't want it to bind to the external interface you'd have to tell your apache server to only bind to the internal interface. This would be done via the line "Listen 10.3.2.1:80" where 10.3.2.1 would be the internal IP address of your intranet and of course would have been assigned to the machine already.

Check apache's site for information on this module.

mod_auth_db


This module is essentially the same as mod_auth but in this case the authentication credentials are stored in a Berkeley DB file format. I haven't done anything ever with this module so apache's site would be the best reference for this module. Check out apache's information on this module.




mod_auth_dbm


Just like mod_auth_dbbut credentials are stored in a DBM file. Check out apache's information on this module.




mod_auth_anon


This module provides user access similar to that of of anonymous ftp sites. It does that in that you have a (as the documentation puts it) magic user id 'anonymous' and the e-mail address as a password. This module is more helpful in monitoring access to resources and keeping pesky robots out, as well it may deter some webbots. Check out apache's information on this module.



More User Problems

Just like anything else you do as a systems administrator to ensure safety and security on your machines you're going to have users trying to find ways and potentially finding ways around those policies which you've set. Using .htaccess files users may be able to override your systems default configuration settings. To deny them the ability to do this put the following in httpd.conf or httpsd.conf.

<Directory />
AllowOverride None
Options None
Allow from all
</Directory>

After that you can give permissions to other directories so that if a user wants to be able to override something with .htaccess they'll have to get permission from you first and you'll have to grant them the ability to do so.

Protecting Files

Running as tight of a server as possible always is your first intention, if people want access to be able to do something then they should have to request it. This isn't always an efficient way of doing business but for security's sake it's the best way to go. If you're allowing your http server to follow symlinks and a user simply did cd /; ln -s / public_html; then someone went to yourserver.tld/~user/ and indexing was turned on, then then have the ability to walk any filesystem they choose as long as it's readable.

So putting the following in your configuration file is going to be friendly to you.

<Directory />
Order Deny, Allow
Deny from all
</Directory

then from there allow access only to the specific directory blocks in which people browsing should be able to access. For example you'd want to add in my case a

<Directory /home/users/*/public_html>
Order Deny, Allow
Allow from all
</Directory>

<Directory /www/htdocs/>
Order Deny, Allow
Allow from all
</Directory>

These lines would allow people to access my users public_html directories so ~/user/ would work as well as grant access to files in the directory /www/htdocs. Be careful to watch out for the <Location> directive, as it may override a configuration which you've specifically set to deny <Directory>

Denying Agents: The following lines Deny Marvin and wget.

BrowserMatchNoCase "^Wget/[0-9]" UGHSTOP
BrowserMatchNoCase "Marvin/[0-9]" UGHSTOP
<FilesMatch *>
Order Deny, Allow
Deny from env=UGHSTOP
</FilesMatch>

Rejecting CGI-Scanning Kids:

There are numerous things which you can do to kids who are scanning your webserver for cgi-vulnerabilities. I say have the most fun with them that you can. There aint nothing wrong with wasting a little script kiddie time.

<FilesMatch ~ "\..exe|EXE" >
Deny from all
Error Document 403 http://www.brianhouk.com/wedontrunnt.html
</FilesMatch>

<FilesMatch ~ "_vti_">

Deny from all

Error Document 403 http://www.brianhouk.com/allyourfrontpagearebelongtous.html

</FilesMatch>


The given example could re-direct to say a page which you choose the content, I have all requests like that going to a CGI script which logs everything on them. From the given example you should easily see what kind of fun you could have with cgi scanners.

People Hotlinking: I used to run a site with hundreds and hundreds of funny pictures, a problem which I constantly had was people hotlinking to images on my website. The following will DENY them unless they have been referred by your website.

SetEnvIfNoCase Referer "^http://www\.brianhouk\.com/" local_ref=1
SetEnvIfNoCase Referer "^http://brianhouk.com\.com/" local_ref=1

<FilesMatch ~ "\.(gif|jpg|GIF|JPG)">
Order Allow,Deny
Allow from env=local_ref
Error Document 403 http://www.brianhouk.com/thesiteyoucamefromhasahotlinkingwebmaster.html
</FilesMatch>

Password Protection:

Some administrators password protect access to certain directories on the webserver. It's not unusual for administrators in this case to want regular users to be able to use their system passwords in gaining access to files via the web. This is a BAD IDEA! not only is it bad, it's REALLY REALLY REALLY bad. Passwords for the most part which are sent to gain access to resources on a webserver are sent in plaintext. Those can be sniffed very easily, if you don't think so install dsniff sometime and use it on your networks gateway, then you'll know what I'm talking about.

Anyway let's quickly create a simple password protection scheme for a directory on your website, if this is confusing google.com will provide you with more than enough information to understand it fully.

mkdir protected
cd protected
cat > .htaccess
AuthType Basic
AuthName Authentication
AuthUserFile /www/htdocs/protected/.htpasswd
<Limit GET POST>
require valid-user
order deny, allow
deny from all
allow from 10.3.2.0
</Limit>
^d

this is creating your .htaccess file which defines who can access this directory as well as what IP(S) that they can access it from. Next you'll have to make the password file which will work in conjunction with the .htaccess file in denying or providing acces to services on that webserver.

cd /www/htdocs/protected/
htpasswd -c .htpasswd newusernametoadd
Adding new user newusernametoadd
New password:
Re-type new password:


You've now setup accesscontrol for that directory from the webserver. Currently the only person who can access it is the user newusernametoadd.


If you have any questions or find any information contained in this document which is incorrect I would appreciate an e-mail. brian at brianhouk dot com.