michael orlitzky

CVE-2024-43199: NDOUtils root privilege escalation via insecure permissions

posted 2024-08-12

Product
Nagios Data Output Utilities (NDOUtils)
Versions affected
2.1.3 and earlier
Published on
2024-08-12
Fixed in
commit 18ef1203, version 2.1.4
Bug report
https://github.com/NagiosEnterprises/ndoutils/pull/65
MITRE
CVE-2024-43199

Summary

Before v2.1.4, NDOUtils installs its executables owned by the same unprivileged user and group, typically nagios, that the ndo2db daemon runs as. These executables are invoked by other users; in particular, the ndo2db daemon is often started by root as part of the boot process. Since the ndo2db user is free to alter these executables at any time, this leads to code execution.

Details

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

AC_ARG_WITH(
  ndo2db_user,
  AC_HELP_STRING([--with-ndo2db-user=<user>],
                 [sets user name to run NDO2DB]),
  ndo2db_user=$withval,
  ndo2db_user=nagios
)

AC_ARG_WITH(
  ndo2db_group,
  AC_HELP_STRING([--with-ndo2db-group=<group>],
                 [sets group name to run NDO2DB]),
  ndo2db_group=$withval,
  ndo2db_group=nagios
)

AC_SUBST(ndo2db_user)
AC_SUBST(ndo2db_group)

INSTALL_OPTS="-o $ndo2db_user -g $ndo2db_group"
AC_SUBST(INSTALL_OPTS)

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

# USER/GROUP PRIVILEGES
# These options determine the user/group that the daemon should run as.
# You can specify a number (uid/gid) or a name for either option.

ndo2db_user=@ndo2db_user@
ndo2db_group=@ndo2db_group@

The build system then installs several files with their owners/groups set to the user and group specified, through the pervasive use of INSTALL_OPTS (defined above) in src/Makefile.in. For example,

install: install-4x
	$(INSTALL) -m 774 $(INSTALL_OPTS) file2sock $(DESTDIR)$(BINDIR)
	$(INSTALL) -m 774 $(INSTALL_OPTS) log2ndo $(DESTDIR)$(BINDIR)
	$(INSTALL) -m 774 $(INSTALL_OPTS) sockdebug $(DESTDIR)$(BINDIR)
	...

install-4x:
	$(INSTALL) -m 775 $(INSTALL_OPTS) -d $(DESTDIR)$(PIPEDIR)
	$(INSTALL) -m 775 $(INSTALL_OPTS) -d $(DESTDIR)$(BINDIR)
	$(INSTALL) -m 755 $(INSTALL_OPTS) ndo2db-4x $(DESTDIR)$(BINDIR)/ndo2db
	$(INSTALL) -m 755 $(INSTALL_OPTS) ndomod-4x.o $(DESTDIR)$(BINDIR)/ndomod.o

This is exploitable whenever those executables are run as another user. In particular, ndo2db will often be run as root as part of the boot process. (It will later drop privileges, but by then it's too late.) This allows the ndo2db user/group to escalate his privileges, often to root.

Exploitation

The ndo2db user simply overwrites the target (/usr/bin/ndo2db, for example) with his own code and waits.

Resolution

NDOUtils-2.1.4 was released on August 1st, 2024. It contains two commits that address permission issues.

The first is the big one. Commit 18ef1203 completely eliminates the INSTALL_OPTS variable from the build system. This variable contained the options to set the owner and group of the installed files. Now the files will be installed as the user/group who is installing them. For “user” installs, that will be you. For system installs, that will be root.

The other is commit 69a80d6a, which changes the installed mode of three executables—file2sock, log2ndo, and sockdebug—from 0744 to 0755. Specifically, they are made world-executable (because regular users may want to run them), and group-unwritable (because no one should be writing to them). This is not such a big deal after removing INSTALL_OPTS, but before that, group-writability would have provided another way for the ndo2db user to overwrite them.