xorl %eax, %eax

Securing a LAMP Installation

with 4 comments

Assuming that you have a LAMP installed somewhere and you want to perform some basic hardening (in the existing installation). Here is a list of a couple of tips (not including any system level hardening that you should do):

– Firewall
Since it’s a web server you don’t need any other ports accessible apart from HTTP and SSL (if your web server utilizes it). Here is a sample statefull firewall using iptables/netfilter that leaves open for incoming connections just those two ports:

iptables -F
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -p tcp --dport 80  -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -j ACCEPT

You can edit its configuration (usually at /etc/php5/apache2/php.ini) to disable the exposure of the version of the running PHP with this option:

expose_php = Off

In addition to this, PHP provides a way to limit the accessible files to those of the owner of the caller PHP script by enabling this:

safe_mode = On

You can enforce that also the group ID should be the same (the previous affects only the user ID) by disabling this:

safe_mode_gid = Off

Since you are configuring a production system, there is no need for displaying the errors that may reveal sensitive information. To disable this functionality, do this:

display_errors = Off

Various DoS attacks can be avoided by setting appropriately the following parameters:

max_execution_time = 10
max_input_time = 20
memory_limit = 16M
post_max_size = 5M

Of course, those options could vary depending on your application(s). If you allow your clients to upload..let’s say, videos, then 16MB limit and maximum of 20 seconds for input may not be a wise choice.
If you don’t need any file uploading from clients on your server, or if you want to limit the maximum size (you can do it with memory_limit as well) there are these options available:

file_uploads = On
upload_max_filesize = 2M

Many attacks are being performed in the wild because of poorly coded PHP applications that allow attackers to include remote files using include() function (so called, “remote file include”). You can limit those requests to local files only using this:

allow_url_include = Off

Another technique to obfuscate what language generates the cookies is to change the default name of the session cookies:

session.name = XORLSID

By default session IDs are generated in a possibly predictable way. You can change this by specifying the entropy length as well as the entropy file of your choice like this:

session.entropy_length = 20
session.entropy_file = /dev/urandom

It is also important to change your hash function from MD5 to SHA-1 like this:

session.hash_function = 1

Where 1 represents SHA-1 and 0 MD5 hashing algorithms. There are probably more options that might be useful on securing PHP but those are a few I have personally used. Now, let’s move to Apache installation.

– Apache

I’m assuming that is already running in a chroot’d environment and since there are countless sites describing how this is done I’m not goind to write about that. However, even if this isn’t such a great security measure, it is definitely an additional obstacle for the attackers (like most of the security mechanisms). First of all, check out its user/group at its configuration file (apache2.conf):

User nobody
Group nobody

And ensure that no shell is available for those:

root@www# grep nobody /etc/passwd

An additional security measure to limit the exposure of your server’s software is to use custom error pages, for example.. here are the options for 404 and 403 error codes:

ErrorDocument 404 /my_site/index.php
ErrorDocument 403 /my_site/index.php

You can use the same approach for any HTTP error code. Here I’m redirecting the pages to index.php so that the attacker will not be aware of the error, or at least the average attacker. The classic way to disable version exposure and product name is this:

ServerTokens ProductOnly
ServerSignature Off

It is also crucial that you disable any Apache modules that you don’t need. You can also tune the following options to fit your needs:

MaxClients 100
MaxRequestsPerChild 0

Also set the email of the server’s administrator to something that does exist. A couple of years ago, I was reporting vulnerabilities on web applications for fun (yeah… no more free bugs :-P) and one of the most distrurbing things was when I was unable to find an email to report the bug. So…

ServerAdmin some.real.email@address

Also, disable directory indexing/browsing using the following directive:

Options -Indexes

If your clients are coming from a known netblock you can use your httpd.conf to specifically filter those addresses, for example for you can use this:

Order Deny, Allow
Deny from all
Allow from

To prevent users from adding their own .htaccess files that can override your configuration, add this directive:

<Directory />
AllowOverride None

Well, always keep up to day with security fixes and it is important to remember that all of the above are completely useless if you’re running some crappy code on it. If an attacker can exploit a vulnerability on your web application the above security measures can be bypassed one way or another. Probably not by the average attacker, but they can definitely be bypassed. Always audit your applications carefully…
Keep in mind that for a local attacker, it is only a matter of time to gain root privileges and compromise your entire system.
At last, all of the above should be performed in addition to common system hardening such as, custom kernel patches (e.g. grsecurity), filesystem integrity checking applications etc.

This post is delivered to you by the administrative side of xorl. :-P

P.S.: If you’re aware of more options or tips on this subject feel free to contact me or leave a comment.

Written by xorl

April 28, 2009 at 13:07

Posted in administration, linux

4 Responses

Subscribe to comments with RSS.

  1. where is the M stuff? :-P


    May 3, 2009 at 22:15

  2. what M stuff?
    Sorry but I’m not 100% sure I got it :-P


    May 4, 2009 at 17:18

  3. Mysql I guess :)


    May 5, 2009 at 07:45

  4. Haha! You’re right! I totally missed the ‘M’ part. Maybe I’ll post some tips in a different blog post later. Thanks for the remark. :-)


    May 5, 2009 at 12:22

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s