Information Security Stack Exchange is a question and answer site for information security professionals. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I have noticed several questions on Stack Overflow, like this one, about executing commands with root privileges using PHP. The answer proposed to add the line

www-data ALL=(ALL) NOPASSWD: ALL

to the /etc/sudoers.d file.

Is it a safe approach to solve the problem? Does it create a vulnerability?

share|improve this question
4  
This is pretty unsecure since it allows any process running as www-data actually do anything. If you need to run some app as root from php is not it better to use suid? – user996142 Feb 29 at 19:29
24  
it IS an epic fail! The PHP language has a very handy bindings for a system commands and the point is that a web part of your app is hard limited Use a message queue, for example, to read a requests from your app, validate them and execute from a separate component like a daemon. – Alexey Vesnin Feb 29 at 22:17
12  
Just don't do this. Ever. – stackErr Feb 29 at 22:58
2  
It's sad, but there are lots of tutorials (even for "security" software) that tell you to do this. – korockinout13 Feb 29 at 22:59
3  
This question combined with I just found suspicious PHP code on my server readily explains where all that spam and DDoS attacks come from. – Dmitry Grigoryev Mar 1 at 9:40
up vote 80 down vote accepted

This... is atrocious. The whole point of running Web things as a non-root user is damage containment: in case the Web server process gets hijacked through some vulnerability, at least the attacker won't obtain full control of the machine, since he will be constrained by the limitations of the non-root account www-data. But if you give www-data a way to run every command it wishes to, with the rights of any user (including root), and without any further authentication, then you just lost that damage containment feature.

To be fair, www-data + sudo is slightly better than simply running everything as root, because the going-to-root has to be explicit; therefore, common flaws like a PHP script writing files in improper locations would be harder to exploit. But still, making www-data a member of the sudoers looks like a poor idea.

share|improve this answer
2  
I actually swore when I saw this sudoers line... – silverpenguin Mar 2 at 11:49
    
Would removing the NOPASSWD: make it any safer? – fduff Mar 2 at 12:40
1  
If you remove the NOPASSWD: then it is somewhat better because sudo will require that you type the password for the www-data account before actually granting the extra privileges. But this raises the question of how the invoking code obtains the password in the first place -- if it is hard-coded in the PHP source, then things are just worse, not better. – Tom Leek Mar 2 at 12:53

When considering how secure something is, you should assume the attacker is able to log in as your www-data user, and have a shell. This does not mean your attacker really can get a shell, but there can be plenty of ways how the attacker can execute arbitrary shell commands; they could be results of library bugs like shellshock, or oversights in your code.

The safest way

The best way of doing this is, like @AlexeyVesnin said, to use a specialized process to do the work. Have this process listen on a (unix domain, so it isn't reachable from the network) socket, read its input from said socket, sanitize the input(!), do the work, and return some result to the socket, from where the web server script reads results. Any authorization (user needs to enter some password on the web site to be allowed to do this) should be handled in that process, and the www-data user should not be able to read any of that authorization data.

The mostly-safe sudo way

In case your budget, or your skill, doesn't make this best approach feasible, using the sudo approach isn't completely wrong, but you should restrict sudo permissions to the minimum you actually need. For example, let's assume you want to show current disk I/O data on your web site, for which you need to call iotop:

  • make a script, in this example /var/www/bin/get-disk-io, that extracts the data you need:

    /usr/sbin/iotop -b -n 1 | /usr/bin/head -2

  • Do not allow the caller of the script to pass any parameters, i.e. the script shouldn't access $1, $2, ... , $*, $@
  • In case you absolutely have to use parameters, sanitize them in your script first. Especially pay attention to whitespace or any unusual characters that might be hidden in parameters.
  • Make sure to state the full path to every command in that script, so attackers can't replace any of those commands with their own
  • Allow access to this script, and only this script, in /etc/sudoers
  • Make sure env_reset is in the defaults policy in your sudoers file

Note that this is still safer than a suid program, since (a) you can restrict who can execute it, so an attacker who gains the ability to execute a program under a different user won't be able to use it, (b) you can't pass arbitrary parameters to it, (c) the environment is sanitized by sudo, and (d) you can make sudo log when the command gets executed, so you have an audit trail that a suid program doesn't give you.

The suid way

Note: Do not do this unless you know what you're doing. If you're asking, or reading, this question on stackexchange, you probably don't. So don't do this.

If you set the owner of an executable to a certain user (chown user /my/executable/file), then set the suid bit (chmod u+s /my/executable/file), then that program will run under the permissions of that user every time it is executed. So, for example, chown root /bin/cat; chmod u+s /bin/cat will run every invocation of cat with root rights, which means you can read every file on the system independent of its access rights. Do not try this on a system that is connected to a network, not even for 5 minutes to "check if it works".

  • On many unix systems, this works for compiled programs only, not for scripts that need an interpreter
  • In some configurations, for example if you run the program under strace, the s bit has no effect
  • In NFS configurations, root often doesn't have access to files on the NFS server, so this might even reduce what you're able to do.

The restricted-suid-Linux way

Linux has a capabilities system, that works almost like suid, but a much finer granularity. For example, if you need a process to be able to use port numbers below 1024, in classical unix systems, you need to run the command as root, often meaning you need to do the above chown/chmod u+s stuff, which allows using those port numbers, but also grants access to the filesystem. Linux allows you to give the port capability without everything else that comes with root:

setcap cap_net_bind_service+EP /path/to/my/program

Do man 7 capabilities to learn more. If you seriously consider giving suid to a program, think twice if setting a capability isn't a better idea.

share|improve this answer
2  
I would add that if SELinux is in enforcing mode, further restrictions can be applied so that scripts run by the PHP script can be denied access to resources that otherwise may be world readable on the system. – Randall Mar 1 at 11:14
    
I second that using capabilities and/or SELinux is recommended. However, UserK is obviously not an expert in Linux security (or he wouldn't have asked the original question), so I wouldn't expect him to be able to properly use those. Probably, a properly set up sudoers is his best solution. – Tom Mar 2 at 9:25
    
@Tom: The best solution for the OP would be "ask someone who knows". But it seems he tried that, and came up with "use sudo .. nopasswd, all", which is clearly a bad idea. When he was told that, he commented "Could you specify how to use suid in order to execute commands as root". This is almost as bad, so i tried to make clear he should use a restricted sudo, and if he can't, for some reason, at least prefer capabilities over standard suid. Basically, telling someone "what you're doing is bad" doesn't help much if he has his boss in his back, and you don't tell them a better way to do it. – Guntram Blohm Mar 2 at 10:43
    
"Make sure to state the full path to every command in that script, so attackers can't replace any of those commands with their own" - Or just define PATH in you script with a proper locations – Ferrybig Mar 2 at 10:48
    
@GuntramBlohm yes, giving people a good solution is always the best answer. But stopping them from implementing a bad solution, or one they cannot control, is also valuable. I think for a capable Linux admin with no extended knowledge about capabilities, SELinux, etc. using sudo the way it was intended to is probably the most practical approach. – Tom Mar 8 at 12:51

Every time, with no exception, when you see ALL=(ALL) NOPASSWD: ALL in the /etc/sudoers file, someone deserves to be fired. Basically, you have a second root user.

Is it safe? Hell no. Does it create a vulnerability? Hell yes.

You can use sudo to safely grant a non-root user (including www-data) a privileged execution, but it should always be as specific as possible. If you need to run /usr/bin/my_system_tool +x /var/cache/my_cache as root for whatever reason, that exact command, including parameters should be in the /etc/sudoers file.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.