Secure LAMP using suPHP and VirtualHosts on Ubuntu
With the use of suPHP (an Apache2 module) along with Apache2 VirtualHosts, you can isolate your websites/web applications from each other by executing the PHP code as a different user for each website. If a hacker injects code into one of your websites, only that specific website would be compromised instead of all of them for a default installation.
This can be a very good trade-off between complexity of set-up and security if you host multiple and independent websites like, for example, a web-hosting provider.
Installation
This tutorial has been written and tested under Ubuntu Karmic 9.10 with Apache2, PHP5 and suPHP 0.7.1 but it could also be applied to later versions.The starting point of this tutorial is you have LAMP installed (default installation). If you don't already have it, you can install it by typing
$ sudo tasksel
And select (by hitting spacebar) LAMP server then move to Ok (using the arrows) and hit Enter.
Installation of php5-cgi
suPHP needs php5-cgi (and not the php5 Apache module) to be able to run properly. Note that when using php5-cgi, some of the features provided by .htaccess files by Apache are not available (like php_flag) but htscanner from PECL can be a work-around for this problem.To install php5-cgi, type this:
$ sudo apt-get install php5-cgi
And then, we need to deactivate the php5 module to avoid clash with php5-cgi
$ sudo a2dismod php5
Installation of suPHP
Ubuntu provides a package for suPHP, but it is not compiled with paranoid mode enabled. suPHP developers advise to compile suPHP using the paranoid mode and that's what we'll do now.We need to install the development package for Apache2, there are two types: the prefork and the threaded type, it depends on what type of Apache2 you currently have installed. g++ and wget are also necessary.
To figure this out, type:
$ /usr/sbin/apache2 -l|grep prefork
If you see a line that says « prefork.c » then you need to install apache2-prefork-dev:
$ sudo apt-get install wget g++ apache2-prefork-dev
Otherwise you need to install apache2-threaded-dev:
$ sudo apt-get install wget g++ apache2-threaded-dev
Now, let's download suPHP:
$ cd && mkdir suphp && cd suphp #create a suphp dir in your home
$ wget http://www.suphp.org/download/suphp-0.7.1.tar.gz
$ tar xvf suphp-*.tar.gz # extract the files
$ cd suphp-* # go into the freshly extracted suphp directory
We need to ./configure (before compiling) suPHP defining as much as possible our current installation (copy and paste the whole command into your terminal):
1 |
$ ./configure --prefix=/usr \ |
Now we can start compiling, and then install the files system-wide:
1 |
$ make |
If you wish to verify that suPHP has been installed without errors, you can check if the file /usr/lib/apache2/modules/mod_suphp.so exists.
suPHP Configuration
suPHP doesn't install a configuration file by default so we will create one.First, we need to create the /etc/suphp folder:
$ sudo mkdir /etc/suphp
Then, create the file /etc/suphp/suphp.conf with the following content:
[global]
;Path to logfile
logfile=/var/log/suphp.log
;Loglevel
loglevel=info
;User Apache is running as
webserver_user=www-data
;Path all scripts have to be in
docroot=${HOME}/www:/var/www
;Path to chroot() to before executing script
;chroot=/mychroot
;Security options
allow_file_group_writeable=false
allow_file_others_writeable=false
allow_directory_group_writeable=false
allow_directory_others_writeable=false
;Check whether script is within DOCUMENT_ROOT
check_vhost_docroot=true
;Send minor error messages to browser
errors_to_browser=false
;PATH environment variable
env_path=/bin:/usr/bin:/usr/sbin:/sbin
;Umask to set, specify in octal notation
umask=0022
;Minimum UID
min_uid=1000
;Minimum GID
min_gid=1000
[handlers]
;Handler for php-scripts
application/x-httpd-php="php:/usr/bin/php-cgi"
;Handler for CGI-scripts
x-suphp-cgi="execute:!self"
With this configuration, suPHP will not allow scripts to be executed as a user which UID or GID is below 1000 (which are system users and groups).
Files will have to be in the specified docroot, which is ${HOME}/www , so a folder like /home/cooluser/www would work.
/var/www can also be used but I recommend sticking with the www folder in the users' home folder. A clear advantage is that it is a lot easier to do backups because you can just copy /home/ and get users files and websites at the same time.
Loading suPHP automatically
Our next step is to tell Apache2 to load suPHP and also that we need our PHP files to be executed through suPHP.The first file to create is /etc/apache2/mods-available/suphp.load it should only contain the following line:
LoadModule suphp_module /usr/lib/apache2/modules/mod_suphp.so
Then, we create /etc/apache2/mods-available/suphp.conf with the following content, this will tell Apache2 to execute the PHP files using suPHP:
<IfModule mod_suphp.c>
AddType application/x-httpd-php .php .php3 .php4 .php5 .phtml
suPHP_AddHandler application/x-httpd-php
<Directory />
suPHP_Engine on
</Directory>
# By default, disable suPHP for debian packaged web applications as files
# are owned by root and cannot be executed by suPHP because of min_uid.
<Directory /usr/share>
suPHP_Engine off
</Directory>
</IfModule>
Important
Note that suPHP is also activated for /var/www. The best thing to do now is to move all of your existing websites to separate users (e.g. /home/someuser/www/) to avoid breakage. See the following section about VirtualHosts.
Now, we activate the suPHP module:
$ sudo a2enmod suphp
|
VirtualHosts
Now we need to create the virtual hosts. I will explain how to set up domain-based virtual hosts which means they can only be differentiated by their domain name (www.example.com, sub.domain.com, …) and they all share the same IP address.
Creation of the user
First, we'll create a user corresponding to the website (www.mycoolblog.com) we want to host, we'll use mycoolblog as the username.
$ sudo adduser mycoolblog
Type in a long and complicated password, of course.
We'll also create the www folder so that we can put some files in it.
$ sudo su mycoolblog -c 'mkdir /home/mycoolblog/www;'
We need a simple index.php file that will tell us which user is executing the file
$ sudo su mycoolblog -c 'vi /home/mycoolblog/www/index.php'
And write (type I to access insert mode):
<?php system('/usr/bin/id'); ?>
Then hit ESC (to quit insert mode) and type :wq to save and quit.
Creation of the VirtualHost configuration file
The virtual host config file needs to be created so that we can access the website.
/etc/apache2/sites-available/mycoolblog.conf
And put the following content:
<VirtualHost *:80>
ServerName www.mycoolblog.com
ServerAlias mycoolblog.com
suPHP_UserGroup mycoolblog mycoolblog
DocumentRoot /home/mycoolblog/www
<Directory /home/mycoolblog/www>
AllowOverride All
Order allow,deny
allow from all
</Directory>
</VirtualHost>
Make sure you customize this file to your needs.
Then we need to activate the site:
$ sudo a2ensite mycoolblog.conf
Restart Apache2:
$ sudo service apache2 restart
And now you can access your website at http://www.mycoolblog.com (as long as the domain points to your server's IP address!)
Conclusion
Note that if you are having problems with suphp or if you get denied permissions, you can always look at /var/log/suphp.log it will tell you what's wrong with your set up. If it doesn't help you at all then take a look at /var/log/apache2/error.log see if there is more information.
SuPHP can really help in isolating websites and even help you having a cleaner set up for all of your websites, intead of having them all in /var/www.
It's a useful tool to have when you host multiple websites and do not want all of them to be compromised when just one contains a security breach.
blog comments powered by DisqusFeatured Provider
|
Category: Linux Hosting
|
|
Category: Windows Hosting
|
|
Category: Linux Hosting
|


