Labels

Wednesday, August 14, 2013

Running a script as root

The problem:

In theory, running a script as it's owner (in our case root) is simple, all you have to do is set the 'setuid' bit (sometimes mistakenly called the 'sticky' bit) by using 'chmod 4755' (or chmod 4***, depending on what mode you need). The problem is, that the 'setuid' bit functionality has been disabed on most Linux based distros for security reasons. This affects only scripts, not compiled code which should still work.

Solutions:

binary wrapper

The 'setuid' bit still works for compiled files. So what you can do is write a little c wrapper that will execute the script you want to run as root.
#include 
#include 
#include 
#include 

using namespace std;

int main(int argc, char* argv[]) {
    setuid( 0 );
    string cmd = "/opt/local/cmd.sh";
    for (int i = 1; i < argc; i++) {
        string arg (argv[i]);
        cmd += " ";
        cmd += arg;
    }
    int exitcode;
    exitcode = system(cmd.c_str());
    return WEXITSTATUS(exitcode);
}

Safe this as 'runscript.c', then compile and do the following:
gcc runscript.c -o runscript
sudo chown root:root runscript
sudo chmod 4750 runscript
You should now be able to run this command as root.

sudo wrapper

Add the following line to your sudoers file, with 'group' being the group you want to give access to your script.
group    ALL = NOPASSWD: /path/to/script
Then write a wrapper, executing you script with sudo.
sudo /path/to/script
Also your script will have to perform a 'setuid(0)' to make sure that all child processes are executed as root.

A couple of things to note:

  • it's not enough to do 'chmod 4***' on the binary, you also have to use 'setuid' inside the code.
  • an additional problem on Mac OS X is, that by default the 'setuid' bit is disabled on NFS mounts.


No comments: