michael orlitzky

CVE-2017-16834: pnp4nagios root privilege escalation via insecure permissions

Product
pnp4nagios
Versions affected
all
Published on
2017-11-15
Author
Michael Orlitzky
Fixed in
Commit 23c123f
Bug report
https://github.com/lingej/pnp4nagios/issues/140
MITRE
https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-16834
OSS-security
http://www.openwall.com/lists/oss-security/2017/11/16/1

Summary

The pnp4nagios build system installs two sets of files with insecure permissions. After installation, the executables and the configuration files are all owned by the same unprivileged user and group (typically, nagios) that the npcd daemon runs as. In one attack, the unprivileged user simply replaces the npcd executable with one that does his bidding. A slightly more complicated attack can be mounted by the unprivileged user by configuring a malicious action and then altering npcd.cfg to execute that action as root.

Details

The pnp4nagios build system allows you to specify a runtime user and group (default: nagios) via the two ./configure parameters --with-nagios-user and --with-nagios-group:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
AC_ARG_WITH(
  nagios_user,
  AC_HELP_STRING([--with-nagios-user=<user>],
                 [sets user name to run nagios]),
  nagios_user=$withval,
  nagios_user=nagios)

AC_ARG_WITH(
  nagios_group,
  AC_HELP_STRING([--with-nagios-group=<grp>],
                 [sets group name to run nagios]),
  nagios_grp=$withval,
  nagios_grp=nagios)

AC_SUBST(nagios_user)
AC_SUBST(nagios_grp)

The npcd daemon runs as that user and group by default, because the upstream configuration file incorporates those flag values into the user and group settings in sample-config/pnp/npcd.cfg-sample.in:

1
2
3
4
# Privilege Options

user = @nagios_user@
group = @nagios_grp@

The build system then installs most of the files for the package with their owners/groups set to the user and group specified, through the pervasive use of the following INSTALL_OPTS in configure.ac:

1
2
INSTALL_OPTS="-o $nagios_user -g $nagios_grp"
AC_SUBST(INSTALL_OPTS)

This creates vulnerabilities because the npcd daemon is intended to be run as root.

Exploitation

The default ownership is exploitable in at least two ways:

  1. The runtime user owns the daemon executable, typically located at /usr/bin/npcd. That executable is run as root, and drops privileges to the runtime user itself. This invites a simple attack where the runtime user replaces the daemon executable with his own code.
  2. The daemon configuration file npcd.cfg is also owned by the unprivileged runtime user, but npcd.cfg is where the runtime user and group are specified. The unprivileged runtime user can schedule a malicious action (specified in the configuration files he owns) and then put user=root in npcd.cfg. The next time the daemon is started, it will run as root and execute the malicious action.

Mitigation

For new installations, trial and error has shown that the aforementioned INSTALL_OPTS are unnecessary. Users can unset that variable when installing pnp4nagios,

root # make INSTALL_OPTS="" install

to avoid setting the insecure permissions in the first place. Afterwards, there are four directories that need to be made writable by the runtime user,

Note that the above can be made writable through group permissions rather than directory ownership.

In addition, upgraders will need to reset all pre-existing ownership and group information to safe values. Unfortunately, executing the following command recursively would risk breaking existing Nagios installations; so instead, users must be responsible for running it only on those $paths installed by pnp4nagios:

root # nagios_user=nagios

root # nagios_group=nagios

root # chown --no-dereference --from="${nagios_user}" root $path

root # chown --no-dereference --from=":${nagios_group}" :0 $path

Repeat for every $path installed by pnp4nagios, and keep in mind that afterwards, the four directories mentioned earlier will need to be made writable by the runtime user.