[ubuntu-uk] PHP security

Chris Rowson christopherrowson at gmail.com
Tue Jun 15 21:04:38 BST 2010


>>> Here's the my current level of understanding! If anyone can fill in
>>> the gaps (or correct me if I'm wrong) I'd be really grateful.
>>
>> (snipped for brevity)
>>
>> Your stated understanding is correct, as far as I know it.
>>
>>> What I'm still hazy on is this:
>>>
>>> cgi is slower than fastcgi because it (a bit like prefork MPM) has one
>>> process per thread (whereas fastcgi can service multiple requests with
>>> one process).
>>>
>>> However...... we want each virtual host to have its own waiting
>>> fastcgi process (to separate out script execution to enhance security)
>>> standing by to execute PHP scripts. How do we do that?
>>
>> That's easy. Again, webmin + virtualmin will set it up for each domain/account
>> pretty easily. But here are the packages you need:
>>
>> apache2-mpm-worker libapache2-mod-fcgid php5-cgi
>
> <snip>
>
> I had a day off today so I spent it reading up on the topics in your
> previous email. Well worth it because I understand a little better how
> Apache and PHP work together. Sharing these practical examples has
> helped fit the pieces of the jigsaw together.
>
> Again, sincere thanks Tyler for taking the time to share your knowledge.

I managed to get a virtual server running apache2 with mpm-worker,
fastcgi, suexec and php5 using info from Tyler on this mailing list
and a little bit of good old Googling to fill in the blanks.

I had to diverge from adding the php handler in apache2.conf however
as it didn't seem to work in this configuration. Suexec prevented php
scripts from executing as the php binary wasn't under the web server's
document root. The wrapper script that's supposed to get around this
only seemed to work when the php handler information was put into the
virtual host's configuration file.

Please feel free to point out any errors etc. I might work this into a
how to and publish it on the 'tinterweb (of course giving proper
attribution to folk such as Tyler) as instructions on how to do this
seem to be spread across quite a few sites.

Chris

Instructions:

Install the prerequisites:

   apt-get install apache2-mpm-worker apache2 apache2-suexec
libapache2-mod-fcgid php5-cgi

Enable suexec and fastcgi:

   a2enmod fcgid      (fastcgi is probably already enabled)
   a2enmod suexec
   a2enmod rewrite   (we'll also need mod rewrite to rewrite urls)

And as we're using fastcgi, disable standard cgi

   a2dismod cgid

And give Apache a restart

   /etc/init.d/apache2 restart


Setting up accounts

So first of all, we set up a user and group. We obviously don't want
the user to have access to the shell (so we set it to /bin/false) and
we also want his home directory to be in /var/www/domainname (which we
set with the -d option and -m makes the directory if it doesn't
exist). The following example creates a group called webuser, then
creates a user called webuser adds it to the webuser group and creates
the home directory of test.yourdomain.com within the /var/www area. If
you want to double check that the account has been created properly
after you have done it, try cat /etc/passwd

   groupadd webuser
   useradd -s /bin/false -d /var/www/test.yourdomain.com -m -g webuser webuser

And then create the document root and chown it to the webuser group and user

   mkdir -p /var/www/test.yourdomain.com/public_html
   chown webuser:webuser /var/www/webuser/public_html

Next create a cgi-bin for the site. This will contain a wrapper script
which to call the php cgi binary which is located in /usr/bin/cgi-bin.
We can't call it directly because suexec won't allow us to call
anything outside of the document root. Neither will it allow symlinks.

   mkdir -p /var/www/test.yourdomain.com/cgi-bin
   chown webuser:webuser /var/www/test.yourdomain.com/cgi-bin

Now we can create the wrapper script mentioned above within our newly
created cgi-bin. Create a file within
/var/www/test.yourdomain.com/cgi-bin called php5.cgi and populate it
with the following data.The PHPRC line contains the directory where
the php.ini file is located

   #!/bin/bash
   export PHPRC=/etc/php5/cgi
   umask 022
   export SCRIPT_FILENAME=$PATH_TRANSLATED
   exec /usr/bin/php-cgi

And make it executable

   chmod ug+x /var/www/test.yourdomain.com/cgi-bin/php5.cgi

So now that we have a user setup, and a web directory for that user to
use, we need to set up a site definition. This is done in
/etc/apache2/sites-available/. Within create a file with the same name
as your site (for instance test.yourdomain.com) , and populate it with
the following data. The SuexecUserGroup command tells the server to
run fastcgi scripts under the user and group listed. You want this to
be the user and group you just created. To get the user id and group
id numbers for suexec try the id command followed by your web-user's
name (for instance id webuser).

    <VirtualHost *:80>
     ServerName test.yourdomain.com
     DocumentRoot /var/www/test.yourdomain.com/public_html/
     ScriptAlias /cgi-bin/ /var/www.test.yourdomain.com/cgi-bin/
     AddHandler fcgid-script .php
     FCGIWrapper /var/www/test.yourdomain.com/cgi-bin/php5.cgi .php
     DirectoryIndex index.html index.php
     SuexecUserGroup "#1001" "#1001"
    </VirtualHost>


Now give apache a quick restart just for good measure

   /etc/init.d/apache2 restart

Enable the virtual host you just created

   a2ensite test.yourdomain.com

and the reload apache

   /etc/init.d/apache2 reload

And that's that!



More information about the ubuntu-uk mailing list