posted 2017-09-05
The slapd daemon in all versions of OpenLDAP creates a PID file after dropping privileges to a non-root account. That may be exploitable by the non-root account to kill root processes, because any root script (for example a SysV-style init script) that tries to stop the daemon using the PID file will send a SIGTERM to its contents. The init script provided by the LDAP Tool Box Project is one example of such an init script.
The purpose of the PID file is to hold the PID of the running daemon, so that later it can be stopped, restarted, or otherwise signalled (many daemons reload their configurations in response to a SIGHUP). To fulfill that purpose, the contents of the PID file need to be trustworthy. If the PID file is writable by a non-root user, then he can replace its contents with the PID of a root process. Afterwards, any attempt to signal the PID contained in the PID file will instead signal a root process chosen by the non-root user (a vulnerability).
This is commonly exploitable through init scripts that are run as root and which blindly trust the contents of their PID files. An example of such an init script can be found at ltb-project/openldap-initscript on Github.
There is only a risk of exploitation when some other user relies on the data in the PID file.
An example of a problematic scenario involving an init script would be,
/etc/init.d/slapd start
to start the daemon.
/etc/init.d/slapd stop
to stop the daemon while
I investigate the weird behavior resulting from the hack.
The slapd PID file will remain owned by its unprivileged runtime user: the OpenLDAP project believes it is the responsibility of the init script to address this problem.
To mitigate the risk, the POSIX ps command can be used to verify the PID data. You can get the user of the process whose PID you find with
root # ps -p <pid> -o user=
and you can get the name of the command with
root # ps -p <pid> -o comm=
Init script authors should check the output of those two command
against the expected values before sending a signal to a running
process. That will eliminate the most serious scenarios (where the
attacker kills, for example, the firewall), but still leaves open
the possibility that the attacker can prevent
/etc/init.d/slapd stop
from terminating his compromised
process by entering junk into the PID file.