25

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?

UserK
  • 353
  • 3
  • 7
  • 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 '16 at 19:29
  • Could you please specify how to use `suid` in order to execute commands as root? – UserK Feb 29 '16 at 22:06
  • 1
    You need to chown app with root, then chmod it with u+s. http://pastebin.com/NEgu4mjS See http://www.linuxnix.com/suid-set-suid-linuxunix/ – user996142 Feb 29 '16 at 22:16
  • 25
    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 '16 at 22:17
  • 13
    Just don't do this. Ever. – stackErr Feb 29 '16 at 22:58
  • 2
    It's sad, but there are lots of tutorials (even for "security" software) that tell you to do this. – multithr3at3d Feb 29 '16 at 22:59
  • 2
    Note that even using suid is dangerous, as you're still allowing an untrusted web user to do something as root. What that something is depends on the input (which you may or may not be able to properly sanitize) and the behavior of the application itself (including any security holes it may contain). – Zach Lipton Feb 29 '16 at 23:26
  • Well, if you want a DOS HTTP server. – Joshua Mar 01 '16 at 03:36
  • 5
    This question combined with [I just found suspicious PHP code on my server](http://security.stackexchange.com/q/114919/71607) readily explains where all that spam and DDoS attacks come from. – Dmitry Grigoryev Mar 01 '16 at 09:40
  • 2
    man this line of sudoers made me cry and swear out loud. this is linux abuse and its sick. – TheHidden Mar 02 '16 at 11:51
  • Ah, so this is why there are so many compromised servers attempting to ssh into my box. – Navin Mar 02 '16 at 14:06
  • OMG! I feel like I've time warped back to 2000. If this is the sort of advice provided by the PHP community, no wonder PHP has such an awful rep wrt security. – Tim X Mar 04 '16 at 02:03

4 Answers4

85

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.

Tom Leek
  • 170,038
  • 29
  • 342
  • 480
  • 3
    I actually swore when I saw this sudoers line... – TheHidden Mar 02 '16 at 11:49
  • Would removing the `NOPASSWD:` make it any safer? – fduff Mar 02 '16 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 02 '16 at 12:53
14

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.

Guntram Blohm
  • 1,959
  • 13
  • 14
  • 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 01 '16 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 02 '16 at 09: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 02 '16 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 02 '16 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 08 '16 at 12:51
5

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.

xan
  • 103
  • 3
Tom
  • 10,201
  • 19
  • 51
-1

I did some recent research and found some ways to do this, but as said by @tom-leek, it would in no way be 100% consistent, just a less unsafe method.

But there is a way that I believe is easy even for professionals with little experience like me!

The best secure method is to use the crontab.

  1. Save all your commands in a database (mysql whateaver)

  2. Create a cronjob to read these mysql entries and execute via exec() or shell_exec();

  3. Add these lines to cron

    crontab -e

            • killProcess.php

I prefer to check every 5s but you can check each 10 minutes, as you prefer.

  1. The PHP put values in db table, a simple table with 1 value worked for me and just it! $domain_name kkk

  2. The root user checks the table and get records, generate certificates and remove $domain_name of table.

You can use acme.sh, I prefer Lego, but whatever.

  1. Create cron job and a basic script to renew certificates (most letsencrypt ways to deploy certificates have this ready and easy to deploy)
  2. Update nginx file with certificate files

If your system is hacked you never will lose your root access and can fix it quickly!

I found this good idea in this article: https://sanjaykumarns.blogspot.com/p/how-to-execute-root-level-privileged.html

Where killProcess.php fetches the process IDs from the database and execute the kill linux command(or any other linux commands as per your requirement) through the php function shell_exec().

Since the cronjob entry is configured as the root user, the specified script has all the same set of privileges as the root user.

schroeder
  • 125,553
  • 55
  • 289
  • 326
  • 1
    You seem to completely miss why executing stuff as root is a problem. "if you get hacked you can fix it easily" - no, if your house is burned down, having the keys to the door won't fix anything. –  Dec 19 '20 at 21:55