Q:

Allowing PHP to execute a bash script with root permissions

how to allow a PHP script to execute a bash script with root permissions?
Let's say there is a PHP script...
<?php
// location: /var/www/script.php
exec("bash /var/scripts/test.sh"); // "sudo bash ..." does not work
?>

and a bash script ...
#!/bin/bash
# location: /var/scripts/test.sh
sudo mkdir /test

Of course PHP and Apache should not run as root and at best only the script can be executed with root permissions. Any ideas?
Best regards,
Jimbo

A:

Any PHP-based solution that gives root rights at some point of the chain is dangerous: An attacker with access to the PHP user could gain access to the root user, and that is unacceptable from a security point of view.
I have never implemented this myself, but I'll suggest what I suggested here: Have a script/cron job with root rights frequently scan some location for a sign from the PHP script that a job is to be done - for example, a file with a certain name, or an entry in a jobs database. 
If that file is found to exist, the root script does its thing, and removes the file again.
If your PHP script doesn't need direct response from the root script, I think this would be the best way to go. (A response could also be facilitated by the root script writing a status message into the file, of course).
As long as you closely limit what kinds of jobs PHP can write for the root script to do, this is a watertight solution, as it doesn't get the root user into PHP's business.  

A:

If don't want wait for cron, here is a simple wrapper in C, what you will call from php.
#include <unistd.h>
#include <errno.h>
#define WEBUID 500
main( int argc, char ** argv, char ** envp ) {
    if( getuid() != WEBUID ) exit(1);
    /* some more security checks */
    if( setuid(geteuid()) ) perror( "setuid error" );
    envp = 0; /* don't want environment - security problem */
    system( "/hardcoded/path/to/script.bash", argv, envp );
}

This compiled wrapper should be owned as root, group "www" and should have "s-bit".
chwon root.www wrapper; chmod 4440 wrapper, so

when is executed his effective UID will be root
execute it can only group www (web-server's group)
and when the UID of the caller is not a web-server will exit

