I am programming a small web interface to control samba on Debian (kernel 2.6.32-5-686). I started by writing simple scripts to add users, create folders, etc. They worked fine when run as root. However, when run via the web (apache + php) by using php: shell_exec() some of them didn't work. They look like this:

#archive the userprofile
cp /home/samba/profile/$1 /home/samba/archive/$1
smbpasswd -LU $1 -x
userdel $1 
exit 0

I tried using sudo to run the scripts, which doesn't seem to work. I added this line: (jupiter is the servers name)

%sudo jupiter=(ALL)NOPASSWD:/bin/<script>

to the /etc/sudoersfile, gave my www-data user the sudo group, nothing.

Then I read somewhere I should chmod 4755 and chown the scripts. It still didn't work.

At this point I was curious what the problem was and I redirected the STDERR to a file. I ran one of the small scripts, which would call cp, smbpasswdand userdel to delete the user and archive his share. All calls returned the exitcode 1, which AFAIK indicates that something went wrong. STDERR gave me a little clue:

userdel: cannot lock /etc/passwd; try again later.

This seems to be caused by some *.lock files, but there are none in my /etc/ folder.

At this point I got kinda frustrated and tried giving the www-data more root rights by adding it to the root group. Things still didn't work.

So far for my progress, I have no idea what to do next. My question is: How do I get simple scripts which seem to need root privileges to run via the www-data user? I think it might be a problem with the /etc/passwd file, as I can imagine only the root-user has the right to alter it.

  • Also you shouldn't put custom scripts in /bin. Custom scripts should be going into /usr/local/bin instead. This is to prevent possible conflicts with the package manager and also because it's the standard path as defined by the FHS. The world won't explode if you don't, but it's a good practice.
    – phemmer
    Sep 11, 2012 at 12:14

2 Answers 2


my answer is only related to the line

sudo jupiter=(ALL)NOPASSWD:/bin/<script>

With this line you allow user sudo to run /bin/<script> on host juptier as any user without authentication. I don't think that you want this.

If i have understood correctly you want the user www-data to execute /bin/<script> as root. In this case the appropriate line looks like

www-data jupiter=(root) NOPASSWD:/bin/<script>

Now you can execute /bin/<script> as www-data with root privileges by invoking

www-data:~ $ sudo /bin/<script>

or via shell_exec("sudo /bin/<script>") in your php-script (I hope you cared about security issues).

For further details look at man sudoers or the online version sudoers.man. For a quick understanding i recommend to take a look at the EXAMPLES section.

  • Thank you for pointing out my mistake. I corrected the sudoers file. However, I now get the message sudo: no tty present and no askpass program specified. BTW: I forgot the % in my first post.
    – skiddo
    Sep 11, 2012 at 11:45
  • Maybe requiretty is set in your /etc/sudoers? For more information see man sudoers as well. Sep 11, 2012 at 11:55
  • requiretty is not set, but there was a ` symbol in my etc/sudoers, because I forgot to edit it with visudo. It works now. Thank you.
    – skiddo
    Sep 11, 2012 at 13:14

There's a few different ways ...

  • use sudo as already described
  • configure Apache with the suEXEC feature (might not be an option with php?)
  • use a small setuid program that then invokes your code
  • and there's more ...

The easiest is probably using sudo, and that's already been described.

A quick summary of the sudo option :

  1. make sure /etc/sudoers doesn't have "Defaults requiretty"
  2. add this line to that file "apache ALL = NOPASSWD: /path/to/command", which means that "sudo /path/to/command whatever" will by run as root if invoked as apache. (This assumes that your web server runs as the apache user.)

However, if you do this, let me point out the danger of all of this. Anybody who can access your page can do whatever it's meant to do -- so with userdel, they can delete users (and possibly all their files), and depending on how the code is written, they may be able to trick it into letting them run any arbitrary command as root.

(Now, if properly configured, sudo can limit what they can do, as can a properly written program (though writing secure setuid, CGI and php (that use shell_exec() as you are) programs can be tricky) but userdel can be pretty destructive by itself.)

So ... if you do this, at the very least make sure that sudo (if you use sudo) is configured to only run the commands that absolutely need to be run, and make sure that your page is not accessible to just anybody -- lock it behind a password in Apache, for example, and be especially wary if it's on the Internet proper rather than behind a corporate firewall (but even then -- don't trust the firewall to make it safe.) Also make sure that untrusted other people can't add php or CGI programs on this host, because they'll be able to use that line in /etc/sudoers as well.

Since you're using php's shell_exec(), be very careful about the arguments your code feeds to that command. If you let the user put whatever he wants in there, he can have it do anything.

Suppose your command is "userdel $user" and $user came directly from the user of this web page. If user="foo ; reboot". If this was being run as root ... your computer would reboot. But even if not run as root, he could run code as the apache user that could attempt to get into the machine.

That said, how to properly sanitize your inputs is a longer topic than this simple answer really allows -- I'm not really trying to cover that entire topic, just to touch on it.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .