michael orlitzky

Configuration should be owned and writable only by root

background

UNIX daemons are long-running processes. They run in the background, and are usually started or stopped when the computer is started or stopped. The thing that starts and stops them is called a “service manager.”

A few popular service managers are OpenRC, systemd, and SysV-init. OpenRC and SysV-init start and stop daemons with what are basically shell scripts, while systemd interprets and executes a declarative configuration file innocent children, presumably. They are all supposed to set up the temporary paths and permissions that the daemon needs.

For increased security, daemons will do as much work as possible as an unprivileged, non-root user. OpenRC and systemd have the ability to launch the daemon as that unprivileged user. SysV-init, being mostly shell script, does not. To fake it, you would need to litter every init script with su calls.

the problem

Many daemons are designed to be launched as root but then drop privileges afterwards. This is done for two reasons:

If your daemon is launched as root and if its configuration file is writable by its unprivileged, runtime user, then you are probably screwed in one of two ways.

but wait, why would anyone do that in the first place?

Most UNIX users own their own shit. If you don't think too hard about the little ballet that your service manager performs, then it can sound like a good idea to let the daemon users own their own shit, too. Whatever, I don't know, people just do it.

the problem (continued)

way one

Often, the amount and type of shit that will be done as root is contained in the configuration file; the first way is for the unprivileged to simply change that shit.

Example: if port = 58008 is set in the configuration file, and if the unprivileged user can edit that to say port = 80, then he can cause a denial of service by stealing port 80 from your web server and a denial of boredom by redirecting your visitors to 4chan.

Another example: suppose that keyfile = /path/to/secret.key is configurable and points to a private key that needs to be read as root (because it's private). The unprivileged user might change that path to trick root into reading any file on the system. If the unprivileged user can see the “private key data” at runtime, then he can read any file on the system that way.

way two

Another common practice is to specify the unprivileged user's name inside the configuration file itself. Suppose the daemon is running as the butthead user, because its configuration file says username = butthead. If butthead can write to that configuration file, then he can change it to say username = root. The next time the daemon is started, it won't drop privileges, and will instead do everything as root.

So why is that a problem? Well, the configuration file almost always lets you specify some kind of action; for example

1
mail_command = /usr/sbin/sendmail -f butthead@example.com

If butthead can change that, he can make it say,

1
mail_command = /home/butthead/lol_you_is_fucked.sh

The next time the daemon is started, it will do everything as root, including when it invokes that “mail command.” In cases like these, the unprivileged user can almost always gain full root privileges himself.

the solution

Are you even listening? Configuration should be owned and writable only by root. Pay special attention to the directories that contain your configuration files. Those need to be owned and writable only by root, too; otherwise the files can simply be replaced.

addendum

A related, but much stupider vulnerability exists when the daemon executable itself (as opposed to its configuration file) is writable or owned by a non-root user. That user can change the executable to do bad things, and then root will unwittingly run the modified code the next time that he starts the daemon.

Obviously, anything that might be run by root should be owned and writable only by root. This is obvious. This is obvious? This is obvious.

graveyard