For simple operations, you can easily create a privilege-separation mechanism to perform commands that require elevated privileges.
For example, in creating a document repository, I had the need to provide access to certain directory and file operations based on a user's login name. It's unrealistic and unsecure to provide the web server access to all of the directories that the user may need to access, so I created a setuid() script to perform the required operations for me.
An exerpt from the code demonstrates this:
<?
function privsep_stat($path)
{
$serialized_result = exec("/path/to/privsep.php stat " . $path, $oa, $return_code);
if ($return_code != 0)
{
return false;
}
return unserialize($serialized_result);
}
$st = privsep_stat("/private_directory/private_file");
print_r($st);
?>
privsep.php looks like this:
#!/usr/local/bin/php
<?
if (isset($_SERVER['REQUEST_METHOD']))
{
print "<br>This program is not intended to be run directly from the WWW.\n";
return 1;
}
if ($argv[1] == "stat")
{
clearstatcache();
$original_uid = posix_get_uid();
$success = posix_setuid(0);
if (!$success)
{
print "Error: Cannot setuid().\n";
return 1;
}
$st = stat($argv[2]);
$success = posix_setuid($original_uid);
if (!$success)
{
print "Error: Cannot setuid().\n";
return 1;
}
$success = posix_seteuid($original_uid);
if (!$success)
{
print "Error: Cannot seteuid().\n";
return 1;
}
$result = serialize($st);
print $result;
return 0;
}
?>
Finally, privsep.php's permissions are configured like this:
# chown root:wheel privsep.php
# chmod 4755 privsep.php
And look like this:
-rwsr-xr-x 1 root wheel 1000 Nov 1 00:00 privsep.php
It's probably wise to keep privsep.php out of your document root to help mitigate any successful attack.
This method can be extended for other functions. Use at your own risk.