Product: Kannel (open source WAP and SMS gateway)
Author: Michael Orlitzky
(This hasn't been fixed upstream but I don't expect a response, so I'd
rather not make people wait for the workaround.)
== Summary ==
The Kannel daemons create their PID files after dropping privileges to
a non-root user. That may be exploited (through init scripts or other
management tools) by the unprivileged user to kill root processes,
since when a daemon is stopped, root usually sends a SIGTERM to the
contents of its PID file (which are under the control of the runtime
== 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 signaled
(many daemons reload their configurations in response to a SIGHUP).
To fulfil 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.
This is commonly exploitable through init scripts that are run as root
and which blindly trust the contents of their PID files. Kannel itself
ships a few such a init scripts as debian/*.init.
== Exploitation ==
There is only a risk of exploitation when some other user relies on
the data in the PID file.
An example scenario involving an init script would be,
1. I run "/etc/init.d/bearerbox start" to start the daemon.
2. bearerbox drops to the "kannel" user.
3. bearerbox writes its PID file, now owned by the "kannel" 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/bearerbox stop" to stop the daemon while I
7. The machine reboots, because I killed PID 1 (this is normally
restricted to root).
== Workaround ==
The Kannel daemons can be run in the foreground (by omitting
the --daemonize, --pid-file, and --user flags) under a modern init
system like systemd or OpenRC. Those init systems create the PID file as
root, and it can be relocated to a root-owned directory like /run to
avoid the vulnerability.
A SysV-style init script can mitigate the risk by verifying the PID
data. You can get the user of the process whose PID you find with
ps -p <pid> -o user=
and you can get the name of the command with
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 risks.