Advertisements

WordPress, suPHP, and Ubuntu Server 10.04

If you have WordPress running under an unprivileged user account, you may have noticed that when trying to install or delete a plugin that it prompts you for FTP information. This is due to a rather unintuitive way that WordPress checks for file access:

The following code is from the get_filesystem_method() method in the wp-admin/includes/file.php file:

if( function_exists('getmyuid') && function_exists('fileowner') ){
    $temp_file = wp_tempnam();
    if ( getmyuid() == fileowner($temp_file) )
        $method = 'direct';
    unlink($temp_file);
}

This code creates a temporary file and confirms that the file just created is owned by the same user that owns the script currently being run. In the case of installing plugins, the script being run is wp-admin/plugin-install.php.

This may seem a little counter-intuitive, since the only thing WordPress really needs to be able to do is write to the wp-content/plugins directory.

If you’re on your own server (i.e. your own box or a VPS) and not worried about security implications, you can simply make the files owned by your web server process (usually www-data or nobody). This will have WordPress’ check succeed and no longer ask for your information.

If you’re on your own server and running a shared hosting environment, or just care about the security implications, you should install suPHP.

What are the security implications? If all web files are owned by the web server process, it’s extremely easy for someone to introduce malicious php code which can affect other sites on the server. Since the web server process has access to all of the web server files across the server, malicious code would have no problem gaining access to other files and directories on the server.

suPHP, configured correctly, causes all php scripts under a defined directory (usually /home) to run as the user account they are owned by. It also enforces other security measures, such as requiring that directories and files do not have write permissions for anyone other than the user.

I could go on and on about what it does, but my biggest struggle has been getting it to work. Installation is easy, but it’s painfully clear it does not work out of the box. After dozens of searches I found varying different ways of making it work, but sometimes drastic and not clean nor easy, few didn’t require recompiling something (which I wasn’t going to do), and none of them seemed to work.

After more than a day of searching and testing, I finally came up with a simple, elegant, working solution. Note that this was written and based on Ubuntu Server 10.04 64-bit, and libapache2-mod-suphp 0.7.1-1 and may or may not work for other platforms.

Install suPHP:

apt-get install suphp-common libapache2-mod-suphp

Edit the sites-enabled/xxxx.conf file for your VirtualHost

Inside your directive, add:

php_admin_flag engine off
AddHandler application/x-httpd-php .php .php3 .php4 .php5 .phtml
suPHP_AddHandler application/x-httpd-php
suPHP_Engine on

Lastly, edit /etc/suphp/suphp.conf and under ;Handler for php-scripts (at the bottom) change:

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

to

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

Restart apache and all should be well.

/etc/init.d/apache2 restart

Note: You might get an error message like the following:

Syntax error on line 7 of /etc/apache2/sites-enabled/example.com.conf:
Invalid command 'php_admin_flag', perhaps misspelled or defined by a module not included in the server configuration

In this case, check that you actually have the Apache PHP mod installed and enabled. In can get uninstalled or disabled on occasion when upgrading Apache. Here’s how to reinstall/reenable:

sudo apt-get install libapache2-mod-php5
sudo a2enmod php5

Checking that it’s working

Create a phpinfo.php file with the follow contents:

<?php phpinfo(); ?>

Call it via your browser and check the Server API line near the top: CGI / FastCGI means suphp is working. Anything else means it’s not.

Suphp is slow!

Yes, unfortunately suphp is slow. Suphp runs PHP scripts in CGI mode, which reportedly causes them to run slower. I would argue that the security advantages outweigh the need for fast scripts, but each situation is unique. You have to decide for yourself.

500 Internal Server Error

If you’re getting the 500 Internal Server Error, it means that suphp is probably working, but for some reason it won’t allow the script to run.

Check that you don’t have any PHP opcode caching (APC, etc) running. If you are running any type of PHP opcode cache suphp will never work. You must disable your opcode caching. If you’re using APC, you can disable it system-wide by simply editing /etc/php5/conf.d/apc.ini and commenting the line out with a semicolon as follows:

;extension=apc.so

Another element of importance is file permissions. SuPHP will fail (with a 500 Internal Server Error) any file that has permissions which are not allowed, as defined in /etc/suphp/suphp.conf. For example:

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

Any file or directory with the attributes defined as allow=false will fail. Based on the configuration above, any file that is group- or world-writable will automatically fail. Same with directories. It’s best to leave these options alone (instead of changing them), and change the permissions on your scripts instead.

However, it is supposedly possible to disable it on a per-VirtualHost basis. I haven’t tested this.

Also check that your /var/log/suphp/suphp.log file isn’t over 2GB. If it is, rotate it or delete it.

If all else fails, check /var/log/suphp/suphp.log and /var/log/apache2/error.log for hints.

Many thanks to all of the blogs and articles that each held a piece of this puzzle. :)

Advertisements

, , , , , , , , ,

  1. #1 by Syamsul on April 2, 2011 - 8:36 am

    Thanks for this tutorial – it has not been easy to find a single comprehensive yet easy-to-follow one for suPHP!

    You mentioned that suPHP is slow but that APC would also need to be disabled. What would you recommend to help improve speeds?

    • #2 by Mike on April 2, 2011 - 12:07 pm

      Oh, you’re absolutely welcome!

      Honestly I don’t have an answer about the speed issue. I’ve read in various forums that once you enable suPHP, you’re pretty explicitly trading speed for security.

      http://forum.directadmin.com/showthread.php?t=30291&s=96b91d0d4432ccefb2ced6802e757824&p=153440#post153440

      The one thing I might recommend is, if you’re hosting customer code and your own code, you may be able to speed up your own code by disabling APC and going the suPHP route on the customer-occupied areas of the server, and using APC and not suPHP on your own areas. That comes with the “I haven’t tested it yet” disclaimer, though. :)

      If you find yourself trying that, I would be grateful if you could share your results with me.

  2. #3 by Jez on December 27, 2011 - 7:11 pm

    Very useful information, thanks. I’d previously tried to set this up in a global server context, but ran into all sorts of problems. Doing it on an individual vhost is much better.

    One thing worth mentioning is that I found that the standard umask=0077 leads to uploaded files that Apache can’t read – changing to umask=0022 in /etc/suphp/suphp.conf leaves files that are readable.

    • #4 by Mike on January 1, 2012 - 12:55 am

      Thanks for that tip. I was noticing that I was having issues with Apache not wanting to access files when software (i.e. WordPress) was updated. I didn’t think to look at umask. Thanks so much for sharing this!

  3. #5 by sulliwane on April 21, 2012 - 11:16 am

    Thanks a lot man ! you made my day :o) certainly one of the best tuto of the web.

    btw, you just forgot a ? before the closing tag > (should be ).

    Keep on !

    • #6 by Mike Beach on April 21, 2012 - 11:38 am

      Thank you!

      I took a good deal of time and effort in putting this guide together. I figured I couldn’t be the only one feeling like I was banging my head against the wall looking for a way to make this work. I’m glad it’s been helpful, and I appreciate all the feedback.

      Also, thanks for pointing out the typo — I fixed it and a few other formatting issues.

      Thanks again!

  4. #7 by Swashata on January 16, 2013 - 2:17 pm

    You will also need to replace application/x-httpd-suphp to application/x-httpd-php on /etc/apache2/mods-available/suphp.conf in order to avoid to 500 internal server error. Otherwise, this will add in your apache2 log

    Caused by KeyNotFoundException in Configuration.cpp:234: Handler "application/x-httpd-suphp" not found

    I was really scratching my head since last 3 hours to get this working. Tried installing it (compiled and installed suPHP) manually with no luck. Finally your tutorial gave me the idea to solve this. Thanks a ton.

    • #8 by Swashata on January 18, 2013 - 9:22 am

      Or this will even work, if we do not change the application/x-httpd-suphp inside /etc/suphp/suphp.conf at all.

      I do not know about other versions, but this seem to work on Ubuntu 11.04, 12.04 and 12.10.

      Can you please tell me, why did you change the x-httpd-suphp to x-httpd-php inside the /etc/suphp/suphp.conf at the first place? Becasue, both x-httpd-suphp and x-httpd-php are set inside

      /etc/apache2/mods-available/suphp.conf
      and
      /etc/apache2/mods-available/php5.conf

      Also, suphp simply uses the libapache2-mod-php and then php-cgi for execution. As defined in
      /etc/suphp/suphp.conf

      application/x-httpd-suphp=”php:/usr/bin/php-cgi”

      I was just wondering.

      PS: Firstly, I got the 500 internal server error mainly because of wrong permission (which you have explained).

      • #9 by Mike on January 18, 2013 - 9:51 am

        In the case of when I wrote this, it didn’t seem to work correctly if I didn’t change that line.

        • #10 by Swashata on January 19, 2013 - 1:07 am

          Hi Mike,
          You are right. Sorry for my confusion. It seems, without changing those parameters, this will work for PHP 5.4.x. But for 5.3.x we need to do exactly what you had said, ie, edit the /etc/suphp/suphp.conf and change application/x-httpd-suphp=”php:/usr/bin/php-cgi”. It seems to be some bug with PHP 5.3 and suPHP compatibility.

          I figured this out because, in one of my VPS I have running Ubuntu 11.04 and in another, 12.04. While the latest ubuntu installed PHP 5.4 and didn’t give all these trouble, when I started setting up Ubuntu 11.04 (which installs PHP 5.3) it started giving me another round of headache! Then I did exactly what you had said and it solved.

          So it seems, on Ubuntu 11.04, we need to change all these, and from 12.04 we don’t have to.

          • #11 by Mike on January 19, 2013 - 1:21 pm

            Ahh, that explains it!

            Thanks for the legwork on figuring out the differences in the versions! Much appreciated!