Friday, March 9, 2007

SuExec

I thought I would write down my notes on phpsuexec so that it is understood by others. I know that I had a hard time understanding how it was supposed to work. So here goes:

First off, for security, we want to run PHP with suEXEC. Why? Because that way scripts are executed under the username of the domain owner. Making it easier to track what they are doing and emails that are sent. It also limits what they can modify and whether they can view session data in the /tmp folder. OK, you should know the benefits of suEXEC… so I won’t dig any deeper.

The first thing you need to realize is that for PHP to use suEXEC, it must be run as a CGI. This is probably the most secure way of running PHP. This is in contrast to running it as a module (i.e. mod_php).

The problem with running PHP as a CGI is that it would require all PHP scripts to start with an opening spec (just like most UNIX scripts) saying what the interpreter to use is. For example, you would have to change ALL your PHP scripts to have the following first line:

code: #!/usr/bin/php

Now, this is a problem because you would then need to change ALL PHP scripts to have this first line. Of course, this would be out of the question if you had many sites or worse, many servers… Your clients would be upset and it would take a while to implement.

That’s where phpsuexec comes in. It is nothing more than a module loaded into Apache that essentially prepends that line to PHP scripts so that you don’t need to go and edit all of them. THIS IS THE MAGIC!

This that I explained so far was the piece of the puzzle that I needed in my mind to understand it best.

Now, knowing how it worked, I went back and made sure that I had taken these steps to get it working:

1. Make sure you compile PHP as a binary. (In my case, I build my own PHP and not the one with easyapache).
2. Make sure you place the PHP binary into /usr/bin (it must be here since this is where the phpsuexec patch will look for it).
3. Recompile easyapache. In my case, I specify to use phpsuexec and also tell it to NOT compile PHP since I use my own.
4. The easyapache script comments out the PHP module loading from httpd.conf. This is normal because, of course, you are no longer using PHP as a module.
5. Once apache restarts it starts running PHP scripts with the binary PHP.

Now the fun starts. Because PHP is a binary now, and being suEXEC’d, the same rules apply as they do when you suEXEC any other script. That is, the script must abide by the following rules:

1. User executing the wrapper must be a valid user on this system.
2. The command that the request wishes to execute must not contain a /.
3. The command being executed must reside under the user’s web document root..
4. The current working directory must be a directory.
5. The current working directory must not be writable by group or other.
6. The command being executed cannot be a symbolic link.
7. The command being executed cannot be writable by group or other.
8. The command being executed cannot be a setuid or setgid program.
9. The target UID and GID must be a valid user and group on this system.
10. The target UID and GID to execute as, must match the UID and GID of the directory.
11. The target execution UID and GID must not be the privledged ID 0.
12. Group access list is set to NOGROUP and the command is executed.

Once you convert over to phpsuexec, you should probably babysit the suexec_log file (/etc/httpd/logs/suexec_log) to check for any errors. WHM has the nify “Fax script permissions” thingy that will automatically change perms for you so that they are correct.

The other issue you have to deal with are the php_value settings you probably have lying around on your server. php_value settings in .htaccess files are only interpreted by the module version of PHP. The binary version actually chokes on these and you get a Server 500 error.

The way around this is to find all .htaccess files that have php_value in them. Then, copy php.ini into the same directory as the .htaccess file is located and apply the settings in .htaccess to php.ini. Then of course, remove the php_value settings from .htaccess and you are golden.

I imagine I will run into more issues, but for now these are the main ones. I hope this helps others understand the phpsuexec beast. It’s not that complicated once you understand it’s purpose. Once again: It simply makes running PHP as a CGI easier to do by taking away the need to add the #!/usr/bin/php line to your scripts.

No comments: