SuPHP and you
SuPHP is probably one of the first steps to hardening a PHP installation. It doesn’t really add security in the fact that it makes the code less vulnerable but on machines with multiple sites it makes it so that a compromised site can’t take advantage of other user accounts without a lot more work.
What Is SuPHP?
SuPHP does a few things. First and foremost it causes a system to run PHP code called via Apache as the user who owns the account. Why is this important? Normally a user called “nobody” whom is a generic catch all user is used to run PHP scripts for the web server. This means that it needs to have the ability to read and execute those scripts as well as the ability to write any temporary files and directories it may need to. If an attacker gets on the system through one account running poor or out of date code, it will let them be able to alter data on other accounts. The fact that PHP scripts were run as this catch all user violates the reason Unix style permissions are a great thing for security. SuPHP causes these permissions to be back into full swing again.
SuPHP also has a secondary function. It will make it so that files which are globally writeable are not allowed. This means any web site with “777” permissions or any directory with “666” permissions will cause SuPHP to give a 503 error. These can be traced using the Apache log, or you can use find to check for these permissions. “777” PHP is a bad idea and should be avoided unless temporary (as example setting a site up requires the files as 777 and then they are changed back)
Installation
For CPanel/WHM machines, this is as simple as checking and seeing what handler you’re using. There is a very good chance you’re using DSO or FastCGI. Change the handler to SuPHP if it’s there and you’re good to go. If not you’ll have to rebuild Apache using Easy Apache, and then enable SuPHP at the end. Not a biggie but it will result in about 30 minutes of down time.
Configuration
There are a few things that need to be done. The first is a full backup. Sed/find and other utilities listed below are dangerous. You can break things easily if you’re not clear on what you’re doing. The second is that your .htaccess files need to have any php directives removed. How I find what files contain such directives are:
find /home/* -name .htaccess -exec grep php {} -ilr \;
As an example this is my test box, I added a few myself.
[root@FS01 roboto]# find /home/* -name .htaccess -exec grep php {} -ilr \;
/home/network/tms_backups/public_html/smf/attachments/.htaccess
/home/network/tms_backups/public_html/smf~/attachments/.htaccess
/home/roboto/test/test2/.htaccess
/home/roboto/test/.htaccess
We should take the variables that we strip, and then put them in a respective php.ini in the same directory. If we don’t sites could break. To dump the contents of this to a file we would run:
find /home/* -name .htaccess -exec grep php {} -ilr \; > file.txt
and we have a nice list of stuff to go through and add php.inis. If there’s demand for it I will add steps on automation of the creation of these files as well.
If I wanted to see what these are I would remove the i from the -ilr in grep. As an example:
[root@FS01 roboto]# find /home/* -name .htaccess -exec grep php {} -i \;
RemoveHandler .php .php3 .phtml .cgi .fcgi .pl .fpl .shtml
RemoveHandler .php .php3 .phtml .cgi .fcgi .pl .fpl .shtml
php_variable
php_variable
If you notice I have a few handlers removed from the directories, this is likely for security reasons. Not a bad idea it prevents people from putting code in directories it shouldn’t be in and running it.
Back on topic though, there are also two php_variable flags here. php_variable and php_value are normal to see in .htaccess files. Since we know that “php_” is unique in this case, actually editing these files is easy. We just use sed combined with find. As an example:
find /home/* -name .htaccess -exec sed -i ‘s/php\_/\#php\_/’ {} \;
We run it and then check again:
[root@FS01 roboto]# find /home/* -name .htaccess -exec grep php {} -ir \;
RemoveHandler .php .php3 .phtml .cgi .fcgi .pl .fpl .shtml
RemoveHandler .php .php3 .phtml .cgi .fcgi .pl .fpl .shtml
#php_variable
#php_variable
This is how we successfully strip the php variables and flags out of our .htaccess files in as complete of a way as possible.
Lastly we need to find and change any permissions that are not SuPHP friendly. This is simply done by running find with a -exec that changes the permissions of insecure files and directories.
find /home/* -perm 777 -type c -exec chmod 755 {} \;
As an example I made some test files that are 777 permissions.
[root@FS01 roboto]# ls ./test/ -lh
total 8.0K
-rw-r–r– 1 root root 0 Jun 22 02:28 fila.example
-rwxrwxrwx 1 root root 0 Jun 22 02:28 file1.tx
-rwxrwxrwx 1 root root 0 Jun 22 02:28 file1.txt
-rwxrwxrwx 1 root root 0 Jun 22 02:28 file1.txtas
-rwxrwxrwx 1 root root 0 Jun 22 02:28 file1.txtasfhg
-rwxrwxrwx 1 root root 0 Jun 22 02:28 file1.txtasfhgasghadf
drwxrwxrw- 2 root root 4.0K Jun 22 02:18 test2
drw-rw-rw- 2 root root 4.0K Jun 22 02:32 test3
In cases like these it is best to try and make a non destructive evaluation first. This means running it without changing permissions. If there is internal stuff at this point I would stop what I was doing and regroup rather than change permissions of it. This would include anything for Plesk, CPanel or the server its self.
[root@FS01 test]# find /home/roboto/* -perm /766 -type f
/home/roboto/test/test2/.htaccess
/home/roboto/test/file1.txtasfhg
/home/roboto/test/.htaccess
/home/roboto/test/file1.txt
/home/roboto/test/file1.txtas
/home/roboto/test/fila.example
/home/roboto/test/file1.tx
/home/roboto/test/file1.txtasfhgasghadf
Since everything looks good for me in this case, I’m going to go ahead with my execution.
[root@FS01 test]# find /home/* -perm /766 -type f -exec chmod 755 {} \;
[root@FS01 test]# ls -lh
total 8.0K
-rw-r–r– 1 root root 0 Jun 22 02:28 fila.example
-rwxr-xr-x 1 root root 0 Jun 22 02:28 file1.tx
-rwxr-xr-x 1 root root 0 Jun 22 02:28 file1.txt
-rwxr-xr-x 1 root root 0 Jun 22 02:28 file1.txtas
-rwxr-xr-x 1 root root 0 Jun 22 02:28 file1.txtasfhg
-rwxr-xr-x 1 root root 0 Jun 22 02:28 file1.txtasfhgasghadf
drwxrwxrw- 2 root root 4.0K Jun 22 02:18 test2
drw-rw-rw- 2 root root 4.0K Jun 22 02:32 test3
If you notice all the 777 files are now 755. The reason I use 766 is I want the files to be owner writeable only.
After this we just repeat the process for the directories:
[root@FS01 test]# find /home/roboto/* -perm /766 -type d
/home/roboto/test
/home/roboto/test/test3
/home/roboto/test/test2
/home/roboto/test/subdir
If you notice we have some subdirectories here that are set up for this test. Notice how -type f has changed to -type d in this case because we are dealing with directories this time. After this we just check the test dir and find out we are SuPHP ready:
[root@FS01 test]# ls /home/roboto/test/ -lh
total 12K
-rw-r–r– 1 root root 0 Jun 22 02:28 fila.example
-rwxr-xr-x 1 root root 0 Jun 22 02:28 file1.tx
-rwxr-xr-x 1 root root 0 Jun 22 02:28 file1.txt
-rwxr-xr-x 1 root root 0 Jun 22 02:28 file1.txtas
-rwxr-xr-x 1 root root 0 Jun 22 02:28 file1.txtasfhg
-rwxr-xr-x 1 root root 0 Jun 22 02:28 file1.txtasfhgasghadf
drw-r–r– 2 root root 4.0K Jun 22 02:36 subdir
drw-r–r– 2 root root 4.0K Jun 22 02:18 test2
drw-r–r– 2 root root 4.0K Jun 22 02:32 test3
Hopefully this will provide some automation tricks to simplify your migration to SuPHP. If you are managed and want us to take care of it for you, drop us a ticket. We’ll be happy to schedule it