You are currently viewing the personal blog of Wiras Adi, a web designer and application developer, located in Jakarta, Indonesia.

Using sudo to Execute root-privileged Commands

One of most frequently asked questions I find in the web development mailing list is “How can I execute a root-privileged commands from my scripts?”. I found this question so often that I think it would be worthy for me to write this entry. There are several solutions for this situation however, and each comes with different impacts on both performance and security degree of the application.

Three commonly known solutions are:

  • Running the web server daemon as root. A very very bad and insecure solution. This is the simplest way of enabling your script to run root-privileged commands. However no one would recommend this, including me. This practice exposes a very serious security hole in your application. Little mistake in your coding, might enable some nasty users to send well crafted request to your server and take over your web server. And since the service runs as root, in other words he/she takes over your whole system.
  • Using suEXEC feature of Apache HTTP Server. This Apache built-in solution (though it doesn’t included in the default installation) offers a secure way to execute system commands. However there are some performance hits come with this technique. suEXEC is based on setuid-wrapper program provided by Apache that performs 20 security checkings (as per version 2.2), before that wrapper program launches the target system command. For a more detailed information please refer to Apache HTTP Server Documentation
  • Utilising sudo. This is my favorite, otherwise the title of this writing won’t be the one you clicked a moment ago. sudo is a *nix system utility to enable non-root user to execute root- or other-user-privileged commands or scripts. The central of this utility is a configuration file /etc/sudoers, where all sudo rules are defined, including the host, user, and command configuration.

The Scenario: Enabling nobody user to execute kill * command

By default Apache HTTP Server runs either as apache or nobody user. For the example I’ll use nobody however, to make it clear that sudo is in fact a system-wide utility, designed not just for web related tasks.

All you need to do is to edit the file /etc/sudoers, and put some declarations about the system user, command, and host involved in your application. Although you could edit the file manually using pico or vi, it is strongly recommended you use visudo, special editor for sudo that will check for syntax mistakes every time you save the file. You need to login as root in order to launch visudo.

[slepi@nargothrond slepi]$ visudo

For the scenario, the /etc/sudoers file would look something like this one:

...
# Host alias spec.
# Typically this would be the IP address of the Apache HTTP Server
# In this example we set the host with alias name LOKAL
Host_alias LOCAL=127.0.0.1
# Command alias spec.
# Set alias for /bin/kill command to KILL
Cmnd_alias KILL=/bin/kill *
# Finally, user privilege spec.
# The line below says that
# the user nobody may execute the KILL command (/bin/kill) without password from host LOCAL (127.0.0.1)
nobody LOCAL=NOPASSWD:KILL
...

The file and comments are quite self-explanatory there, so I don’t think it needs further explanations. And now assume you run a PHP-based web application with Apache HTTP Server runs as nobody, and one of the application’s need is to kill process with PID 1234. You would write this line somewhere in your PHP script then:

...
$PID = '1234';
shell_exec('sudo /bin/kill ' . escapeshellarg($PID));
...
 

2 responses to this entry so far.

  1. rehan

    Great article, this is exactly what I needed.

    Not sure if its a formatting error or maybe my system is a bit different, but I was getting errors for “Host_alias” and “Cmnd_alias”. They needed to be “Host_Alias” and “Cmnd_Alias”.

    #1
  2. reyken

    Cool….that’s really useful
    & i hope it will work with mine
    BTW i’m looking to make a Baser GATEWAY INTERFACE to MANGE it (change IP/MASK) get time from NTP SERVER …etc
    could any body give a suggestion for what i need (all this must be on linux using PHP5)
    Thanks a lot

    #2