michael orlitzky

CVE-2017-13649: UnrealIRCd privilege escalation via PID file manipulation

posted 2017-08-23

Product
UnrealIRCd (Unreal IRC daemon)
Versions affected
all
Published on
2017-08-23
Bug report
https://bugs.unrealircd.org/view.php?id=4990
MITRE
CVE-2017-13649
OSS-security
https://www.openwall.com/lists/oss-security/2017/08/24/1

Summary

UnrealIRCd (all versions) 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.

Details

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.

Exploitation

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,

  1. I run /etc/init.d/unrealircd start to start the daemon.
  2. unrealircd drops to the unrealircd user.
  3. unrealircd writes its PID file, now owned by the unrealircd user.
  4. Someone compromises the daemon.
  5. The attacker is generally limited in what he can do because the daemon doesn't run as root. However, he can write “1” into the PID file, and he does.
  6. I run /etc/init.d/unrealircd stop to stop the daemon while I investigate the weird behavior resulting from the hack.
  7. The machine reboots, because I killed PID 1 (this is normally restricted to root).

Workaround

The UnrealIRCd team provides limited support for SysV-style init scripts. The documented way to run the daemon is to start it either manually or through cron, as a restricted user. Afterwards, you can stop or reload the daemon as the same restricted user. This avoids the vulnerability because the reload/stop signals aren't sent as root; the PID file is controlled by the user who started and is signaling the daemon. These steps are documented on the following wiki pages:

Another possible workaround, if you are using a supervising init system, is to run unrealircd in the foreground, and let the init system manage its PID file. The -F flag can be passed to the daemon to run it in the foreground; the init system will then create and utilize the PID file safely. This is sufficient for systemd, OpenRC, and the like.