Installing and Configuring suPHP on CentOS 5.x

I’m deviating from my SCAP posts a bit. I was looking at better ways to secure sites when I stumbled on this.

What is suPHP?

suPHP will execute php scripts as the user you specify. This enhances security by not running scripts as the web server user (nobody) or as root (really bad idea). So even if there is a vulnerable php script installed, it can at most execute with the permissions of the non-privileged user you choose for it to use.

How does it work?

PHP scripts are interpreted by suPHP and suPHP then calls the php interpreter as the specified user and interprets the scripts as that user.

Why am I writing this How-To?

I have found several guides that *almost* get it done, but then there are a few details that you have to go hunt for. Hopefully this guide is easy to use and can get you set up on the first try.

Installation and Configuration

First Steps

There is an suPHP package in the RPMForge repository. You will need this installed. Follow the guide on the CentOS Wiki: http://wiki.centos.org/AdditionalResources/Repositories/RPMForge
If you follow each step for CentOS 5, it will work. I guarantee it.

The RPMForge package you will need is called “mod_suphp” and as of this writing, here are the package details:
Name       : mod_suphp
Arch       : i386
Version    : 0.7.0
Release    : 1.el5.rf
Size       : 597 k
Repo       : rpmforge
Summary    : Apache module that enables running PHP scripts under different users

Install The Package

yum install mod_suphp

This will install a few configuration files:
/etc/suphp.conf – This is the configuration file for suPHP itself
/etc/httpd/conf.d/suphp.conf – This is the configuration file for the suPHP Apache module

Edit the suPHP Config file – /etc/suphp.conf

There are a few lines that need changd to make this work.

webserver_user=apache

Depending on what user you run your web server as, you may need to change this line.

x-httpd-php=php:/usr/bin/php

This line must be modified to put double quotes around the value. suPHP will not work without it. You must also change it to use the PHP commandline interpreter, php-cgi. It should look like this:

 x-httpd-php="php:/usr/bin/php-cgi"

x-suphp-cgi=execute:!self

The same applies with this line. Put double quotes around the value, so it looks like this:

x-suphp-cgi="execute:!self"

Edit the suPHP Apache Module Configuration File – /etc/httpd/conf.d/suphp.conf

This file loads the suPHP Apache module as well as sets global configuration for the module. On my server, different sites (VirtualHosts) on my server have files owned by different users. To allow each user/VirtualHost to run PHP as their user, we do not enable nor configure suPHP globally. To skip global configuration, I comment out every line in /etc/httpd/conf.d/suphp.conf except the LoadModule line.

Configuration of the suPHP module will be handled on a per-VirtualHost basis in the httpd.conf.

Edit the httpd config file to set up individual VirtualHosts – /etc/httpd/conf/httpd.conf

suPHP usage is defined per VirtualHost. An unchanged VirtualHost directive will still execute PHP, but as the web server user. You can change this so PHP will not execute at all unless it uses suPHP, but I don’t do that in my config.

Below is my unchanged VirtualHost directive for http://www.packetsense.net:

<VirtualHost *:80>
ServerName packetsense.net
ServerAlias www.packetsense.net
DocumentRoot /home/packetsense/www/
ScriptAlias /cgi-bin/ /home/packetsense/cgi-bin/
ScriptAlias /cgi-sys/ /home/packetsense/cgisys/
SetEnv PHPRC /home/packetsense/etc/
ErrorDocument 404 /404.html
php_admin_value sendmail_path "/usr/sbin/sendmail -t -i -fchris@packetsense.net"
ServerAdmin chris@packetsense.net
php_admin_flag allow_url_fopen off
</VirtualHost>

You may not have all those directives defined in your config, but that doesn’t really matter.
To set a VirtualHost to work with suPHP, you only need to add 4 lines.

suPHP_Engine on
suPHP_UserGroup username groupname
AddHandler x-httpd-php .php .php3 .php4 .php5
suPHP_AddHandler x-httpd-php

In my case, my files are owned by User: packetsense, and Group: packetsense.

My modified VirtualHost directive now looks like this:

<VirtualHost *:80>
ServerName packetsense.net
ServerAlias www.packetsense.net
DocumentRoot /home/packetsense/www/
suPHP_Engine on
suPHP_UserGroup packetsense packetsense
AddHandler x-httpd-php .php .php3 .php4 .php5
suPHP_AddHandler x-httpd-php
ScriptAlias /cgi-bin/ /home/packetsense/cgi-bin/
ScriptAlias /cgi-sys/ /home/packetsense/cgisys/
SetEnv PHPRC /home/packetsense/etc/
ErrorDocument 404 /404.html
php_admin_value sendmail_path "/usr/sbin/sendmail -t -i -fchris@packetsense.net"
ServerAdmin chris@packetsense.net
php_admin_flag allow_url_fopen off
</VirtualHost>

Finally: All that’s left is to restart the web server service.

Now: Test It

To see which user your PHP is running as, create a file in your web directory called whoami.php. Include this code:

<?php
echo "Output of the 'whoami' command:<br /><br />\n";
echo exec('/usr/bin/whoami');
?>

You should see something like this:
Output of the ‘whoami’ command:

packetsense

Common Problems

500 Internal Server Error

Check your /var/log/httpd/error_log. You might see something like this:

[Sun Oct 11 11:27:47 2009] [error] [client 72.185.236.25] SoftException in Application.cpp:249:
File "/home/packetsense/www/whoami.php" is writeable by group
[Sun Oct 11 11:27:47 2009] [error] [client 72.185.236.25] Premature end of script headers: whoami.php

In this case, just chmod 644 the file you’re working with. Alternatively, you can adjust the tolerance for file permissions by editing the /etc/suphp.conf file. Look at this section:

; Security options
allow_file_group_writeable=false
allow_file_others_writeable=false
allow_directory_group_writeable=false
allow_directory_others_writeable=false

Change them to true.

Another cause of the internal server error might be if you did not change the interpreter line in /etc/suphp.conf from:
x-httpd-php=”php:/usr/bin/php” to x-httpd-php=”php:/usr/bin/php-cgi”

Your PHP source code displays in the browser in Plain Text

Check your /etc/suphp.conf for proper quote marks and the php-cgi interpreter specified.

Problems with Sessions

If your scripts use PHP sessions, you may run into failures when PHP attempts to write to the /var/lib/php/session directory. By default, it is chmod 770, and owner is root, group is apache. I recommend adding your users to a phpsession group and then to chgrp the /var/lib/php/session directory to the phpsession group. I ran into this problem when trying to run PHPMyAdmin

Please let me know if this is helpful to you. Also, please leave any comments, corrections, or suggestions.

22 Comments so far »

  1. Ronald said,

    Wrote on October 28, 2009 @ 04:13

    what do you if i set :

    $ sudo chmod 1777 /var/lib/php/session

    btw, nice tutorial. thanks

    Ronald

  2. Ron said,

    Wrote on November 16, 2009 @ 07:52

    Pff finally a complete _working_ guide..
    After a day of trying and testing and not getting it fixed… I found this, non of the other sites had a complete step-by-step..

    Tnx dude..

  3. seeal said,

    Wrote on November 16, 2009 @ 08:31

    thx very much, work fine in centos 5 :)

  4. Wordpress suphp said,

    Wrote on November 22, 2009 @ 17:41

    Problem with install. I run my own webserver running wordpress Mu on the server had problems with upgrading etc run over a post that SUPHP would take away the issues however noe I only get a blank page, and when I type in the admin backend i just get some codes and error mesages. I followed your post except for the virtual part since I run all my domains through a multi plugin for wordpress mu instead.

  5. Chris said,

    Wrote on December 9, 2009 @ 12:34

    Could you add something at the beginning explaining how the user you want to use for suphp should be setup and whether that user or root should create the folders?

    It was very confusing. I had to create the folders under the /home/user directory with root, otherwise I got errors.

    It still doesn’t work though for me, since there’s some weird DNS problem going on and it points me to my old site for some things.. yet the VZPP works fine.

  6. james said,

    Wrote on January 31, 2010 @ 04:40

    You forgot to have the LoadModule line

  7. Chris said,

    Wrote on January 31, 2010 @ 05:01

    james … you mean this?

    “I comment out every line in /etc/httpd/conf.d/suphp.conf except the LoadModule line.”

  8. james said,

    Wrote on January 31, 2010 @ 05:37

    Will suphp speed be significantly slower than php? Also please talk about the conf.d directory, how would Apache knows it?

  9. james said,

    Wrote on January 31, 2010 @ 05:41

    “I comment out every line in /etc/httpd/conf.d/suphp.conf except the LoadModule line.”
    Why not eliminate this file and put that loadmodule line into httpd.conf.

    I found this file is not called if I put it in /usr/local/apache2/conf.d – which is my test version.

  10. Chris said,

    Wrote on January 31, 2010 @ 16:34

    If your files are going in /usr/local/apache2/conf.d, then you’re not using CentOS. You’ll have to figure that one out.

    As for not putting the line directly in httpd.conf and eliminating the file, I did that so when yum updates suphp, a new config file won’t be created which might cause conflicts.

  11. james said,

    Wrote on February 1, 2010 @ 03:25

    Oh, I am using CentOS, I am doing a test version on Apache – I called it Apache2 (not the regular Apache2), listening to port 90. So I guess
    /etc/httpd/conf.d/suphp.conf was built in? Not sure why. Since all the modules are under /usr/local/apache2 though.

    Got your points of the suphp.conf, thanks.

  12. Chris said,

    Wrote on February 1, 2010 @ 13:11

    Your main httpd.conf tells apache where to look for additional config files. In my main config, I have this:

    #
    # Load config files from the config directory “/etc/httpd/conf.d”.
    #
    Include conf.d/*.conf

    So that relative path would work out to an abs path of /etc/httpd/conf.d/*.conf for me.

    For your test apache, you may need to use an absolute path for your conf.d directory.

  13. james said,

    Wrote on February 2, 2010 @ 03:34

    Thanks, man. I don’t have a include in either of my two httpd.conf file.

    BTW, the suPHP is extremely slow – don’t know why. I think it should be abandoned. Have you tried mpm-peruser? It should be a lot faster than suPHP.

  14. Fabrizio said,

    Wrote on October 7, 2010 @ 18:20

    Excellent guide for centos 5.
    It works great.

  15. Bill said,

    Wrote on February 8, 2011 @ 13:27

    Thanks so much for this guide. This helped me fix a major issue with constantly having to change permissions on things to keep everything happy as I was finally able to get suphp working properly with your guide.

  16. vps said,

    Wrote on February 11, 2011 @ 10:11

    thanks! It works great.

  17. Barry said,

    Wrote on April 6, 2011 @ 13:38

    Thanks allot for this!

  18. xaverio said,

    Wrote on May 23, 2011 @ 12:15

    i noticed that the parent directory of docroot must be owned by root. with other owner shows again internal server error

  19. Rock Solid said,

    Wrote on August 23, 2011 @ 18:13

    Just a side note that i ran into this on my CentOS 5.6 box where i was getting the WordPress error:
    The uploaded file could not be moved to /var/www/html/public/wp-content/uploads/2011/08
    Some additional notes:
    CentOS 5.6 i386 comes with php 5.1 which is not compatible with Word Press 3.2 so you need to upgrade to PHP.  I could not find a binary of suPHP for PHP 5.3 which was readily available via yum so i followed the instructions here:
    http://wiki.centos.org/HowTos/PHP_5.1_To_5.2
    then you can just:
    yum install mod_suphp
    once that's done i was able to use your instructions to complete the setup of suphp only to find that it still didn't work and Word Press still complained with the same error.  The next problem was that SELinux was also blocking the upload and once i looked in /var/log/messages i found:
    setroubleshoot: SELinux is preventing the php-cgi from using potentially mislabeled files ./2011 (public_content_t). For complete SELinux messages. run sealert -l 639a98ce-cd80-432e-9ed9-8d80e145ff9f
    i updated the SELinux rules with:
     chcon -R -t httpd_sys_content_t '/var/www/html/public/wp-content/uploads/2011'
    and with that…Presto…6 hrs of screwing around, reading posts and articles and i've got a working Media upload widget in Word Press on my CentOS 5.6 i386 box.
    now that wasn't so bad was it?

  20. Rock Solid said,

    Wrote on August 23, 2011 @ 18:20

    whoops i almost missed a piece.  i also needed to add this to the httpd.conf:
    <Directory "/var/www/html/public">
            php_admin_flag engine off
            AddHandler application/x-httpd-php .php .php3 .php4 .php5 .phtml
            suPHP_AddHandler application/x-httpd-php
            suPHP_Engine on
    </Directory>
     
    thanks again.

  21. yoga said,

    Wrote on September 15, 2011 @ 05:17

    i run php5handler on suphp, but suddenly my site has internal server error, what causing this and how to fix? thanks

  22. httpd error because of mod_suphp - Page 2 said,

    Wrote on November 29, 2011 @ 18:28

    [...] want to go no it's ok by me. If you want to give it another try, post the errors you get, or follow this guide written for centos, where it uses an rpm suphp package. [...]

Comment RSS · TrackBack URI

Leave a Comment

Name: (Required)

E-mail: (Required)

Website:

Comment: