Issue 8703 - slapd should create its PID file before dropping privileges
Summary: slapd should create its PID file before dropping privileges
Status: VERIFIED FIXED
Alias: None
Product: OpenLDAP
Classification: Unclassified
Component: slapd (show other issues)
Version: 2.4.45
Hardware: All All
: --- normal
Target Milestone: ---
Assignee: OpenLDAP project
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2017-07-28 19:35 UTC by michael@orlitzky.com
Modified: 2017-09-06 14:19 UTC (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description michael@orlitzky.com 2017-07-28 19:35:46 UTC
Full_Name: Michael Orlitzky
Version: 2.4.45
OS: Gentoo
URL: 
Submission from: (NULL) (98.218.46.55)


The slapd daemon should create its PID file before dropping privileges. This
represents a minor security issue; additional factors are needed to make it
exploitable.

Why?

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 by init scripts that are run as root and
which blindly trust the contents of their PID files. If one daemon
flushes its cache in response to SIGUSR2 and another daemon drops all
connections in response to SIGUSR2, it is not hard to imagine a
denial-of-service by the user of the first daemon against the second.
Comment 1 Howard Chu 2017-07-29 14:55:29 UTC
michael@orlitzky.com wrote:
> Full_Name: Michael Orlitzky
> Version: 2.4.45
> OS: Gentoo
> URL:
> Submission from: (NULL) (98.218.46.55)
> 
> 
> The slapd daemon should create its PID file before dropping privileges. This
> represents a minor security issue; additional factors are needed to make it
> exploitable.
> 
> Why?
> 
> 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.

Not sure this is a valid concern. The uid used to run services should not 
actually have a valid login shell, and thus should not ever be usable for any 
purpose other than running the daemon from init.

-- 
   -- Howard Chu
   CTO, Symas Corp.           http://www.symas.com
   Director, Highland Sun     http://highlandsun.com/hyc/
   Chief Architect, OpenLDAP  http://www.openldap.org/project/

Comment 2 michael@orlitzky.com 2017-07-29 15:13:43 UTC
The problem scenario looks like the following:

1. I run "/etc/init.d/slapd start" to start the daemon.

2. slapd drops to the "slapd" user.

3. slapd writes its PID file, now owned by the "slapd" user.

4. Someone compromises the daemon, which sits on the open network.

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
   slapd.pid file, and he does.

6. I run "/etc/init.d/slapd stop" to stop the daemon while I investigate
   the weird behavior resulting from the hack.

7. Oops, the machine reboots, because I killed PID 1.

Comment 3 michael@orlitzky.com 2017-09-05 17:51:21 UTC
This has been assigned CVE-2017-14159.

Comment 4 Ryan Tandy 2017-09-05 21:38:01 UTC
On Fri, Jul 28, 2017 at 07:35:47PM +0000, michael@orlitzky.com wrote:
>The slapd daemon should create its PID file before dropping privileges. This
>represents a minor security issue; additional factors are needed to make it
>exploitable.

If I understood you correctly, "Additional factors are needed" basically 
means you have to find a code execution vulnerability in slapd? At that 
point I think you can do much more interesting things - pretending that 
your user is uid 0, or in various admin groups are only the first ideas 
that come to mind.

If you would like to propose a patch, we could review that. For myself I 
don't think I would attach a high priority to this.

Howard pointed out on IRC that if the directory containing the pid file 
is sticky, making it owned by root means slapd can no longer remove it 
on exit. I'm not sure how common that is but it's a setup that works 
right now.

Comment 5 michael@orlitzky.com 2017-09-06 11:38:18 UTC
On 09/05/2017 05:38 PM, Ryan Tandy wrote:
> 
> If you would like to propose a patch, we could review that. For myself I 
> don't think I would attach a high priority to this.

I understand that it's a low priority, I'm just trying to clean up the
hundred or so cases of this that we have in Gentoo. In a few, it's
impossible to do so because of the way the daemon creates the PID file
(like it is here), so I'm doing bugs/CVEs to keep track of them. This
way that distribution maintainers have something to watch and will know
when they can fix their init scripts.


> Howard pointed out on IRC that if the directory containing the pid file 
> is sticky, making it owned by root means slapd can no longer remove it 
> on exit. I'm not sure how common that is but it's a setup that works 
> right now.

Typically the PID file would go directly in /run (or /var/run) and be
owned by root. That means that you can't clean it up when the daemon
exits, but no one expects a daemon to do that.

Practically, the PID file exists solely for the benefit of init systems.
Given the choice between,

  1. How do I determine if I can trust the contents of this file owned
     by an untrusted user?

  2. How do I remove the PID file after killing the daemon?

the second is much easier to do. The first is next to impossible to get
right; so if we have to pick one, that's the way to go IMO.

Comment 6 Howard Chu 2017-09-06 12:29:09 UTC
michael@orlitzky.com wrote:
> On 09/05/2017 05:38 PM, Ryan Tandy wrote:
>>
>> If you would like to propose a patch, we could review that. For myself I
>> don't think I would attach a high priority to this.
> 
> I understand that it's a low priority, I'm just trying to clean up the
> hundred or so cases of this that we have in Gentoo. In a few, it's
> impossible to do so because of the way the daemon creates the PID file
> (like it is here), so I'm doing bugs/CVEs to keep track of them. This
> way that distribution maintainers have something to watch and will know
> when they can fix their init scripts.

Your problem scenario is still unrealistic.

> 4. Someone compromises the daemon, which sits on the open network.

Nobody compromises slapd from the network. There are no buffer overflow 
vulnerabilities, there are no RCE vulnerabilities.

> 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
>    slapd.pid file, and he does.
> 
> 6. I run "/etc/init.d/slapd stop" to stop the daemon while I investigate
>    the weird behavior resulting from the hack.

Even if that were possible, it's clearly a bug in the init script, which 
failed to check that the process with that PID was the process it was 
expecting to find. Note that this is something any init script needs to do 
anyway, since PID files can go stale and some other process may be using the 
PID by the time you reference the file.

> 7. Oops, the machine reboots, because I killed PID 1.
> 
Big deal, you caused a temporary service outage. No remote code was injected, 
no data was leaked, no actual lasting damage was done.

I'm inclined to close this ticket. It presupposes a class of bug that doesn't 
exist in OpenLDAP code, and it relies on an additional bug in a script that 
isn't part of OpenLDAP code. At best, this ticket has been mis-filed and the 
submitter needs to submit it to somewhere relevant, like whoever authored the 
broken init script.

-- 
   -- Howard Chu
   CTO, Symas Corp.           http://www.symas.com
   Director, Highland Sun     http://highlandsun.com/hyc/
   Chief Architect, OpenLDAP  http://www.openldap.org/project/

Comment 7 michael@orlitzky.com 2017-09-06 12:57:44 UTC
On 09/06/2017 08:29 AM, Howard Chu wrote:
> 
>> 4. Someone compromises the daemon, which sits on the open network.
> 
> Nobody compromises slapd from the network. There are no buffer overflow 
> vulnerabilities, there are no RCE vulnerabilities.
> 

Oh, it's one of /those/ daemons.


>>
>> 6. I run "/etc/init.d/slapd stop" to stop the daemon while I investigate
>>    the weird behavior resulting from the hack.
> 
> Even if that were possible, it's clearly a bug in the init script, which 
> failed to check that the process with that PID was the process it was 
> expecting to find. Note that this is something any init script needs to do 
> anyway, since PID files can go stale and some other process may be using the 
> PID by the time you reference the file.

Have you ever seen such an init script?

How should the init system know what process it was expecting to find,
if not by reading that process's PID from the PID file?

If you decide not to write the PID file as root, that's of course up to
you, but I still have to tell something to the people who ship OpenLDAP
as part of their distributions. I can tell them "Howard says it should
be easy," but considering that no one has ever done it, that's not real
helpful advice.

There are only two requirements really: it needs to be portable POSIX
sh, and the stop() function must only kill the one process created by
start(). If you give that a shot, you might see why I suggested that
this be fixed in slapd.

Comment 8 Howard Chu 2017-09-06 13:29:41 UTC
michael@orlitzky.com wrote:
> On 09/06/2017 08:29 AM, Howard Chu wrote:
>>> 6. I run "/etc/init.d/slapd stop" to stop the daemon while I investigate
>>>     the weird behavior resulting from the hack.
>>
>> Even if that were possible, it's clearly a bug in the init script, which
>> failed to check that the process with that PID was the process it was
>> expecting to find. Note that this is something any init script needs to do
>> anyway, since PID files can go stale and some other process may be using the
>> PID by the time you reference the file.
> 
> Have you ever seen such an init script?
> 
> How should the init system know what process it was expecting to find,
> if not by reading that process's PID from the PID file?

Learn something about Unix, please.

Use the ps command to verify that the process at least has the correct name. 
The init script should know it's looking for a process named slapd, not init.

-- 
   -- Howard Chu
   CTO, Symas Corp.           http://www.symas.com
   Director, Highland Sun     http://highlandsun.com/hyc/
   Chief Architect, OpenLDAP  http://www.openldap.org/project/

Comment 9 michael@orlitzky.com 2017-09-06 13:56:08 UTC
On 09/06/2017 09:29 AM, Howard Chu wrote:
> 
> Learn something about Unix, please.
> 
> Use the ps command to verify that the process at least has the correct name. 
> The init script should know it's looking for a process named slapd, not init.
> 

Supposing we want to copy/paste two or more "ps" calls into every slapd
init script, this still lets a hacker prevent his own hacked process
from being killed by writing junk into the file.

If the standard practice was to write the PID file as an unprivileged
user, we would need to not only copy/paste those "ps" calls into every
slapd init script, but literally every init script for every daemon.
Apparently my predecessors didn't want to do that, so the standard
practice is to write the PID file as root. Do with that information what
you will.

Comment 10 Howard Chu 2017-09-06 14:18:33 UTC
michael@orlitzky.com wrote:
> On 09/06/2017 09:29 AM, Howard Chu wrote:
>>
>> Learn something about Unix, please.
>>
>> Use the ps command to verify that the process at least has the correct name.
>> The init script should know it's looking for a process named slapd, not init.
>>
> 
> Supposing we want to copy/paste two or more "ps" calls into every slapd
> init script, this still lets a hacker prevent his own hacked process
> from being killed by writing junk into the file.
> 
> If the standard practice was to write the PID file as an unprivileged
> user, we would need to not only copy/paste those "ps" calls into every
> slapd init script, but literally every init script for every daemon.
> Apparently my predecessors didn't want to do that, so the standard
> practice is to write the PID file as root. Do with that information what
> you will.

Apparently your predecessors also didn't understand that PIDs get recycled. If 
your init scripts are just blindly trusting the contents of PID files they're 
all broken already. But none of that is of any concern of the OpenLDAP Project.

Closing this ITS as Invalid.

-- 
   -- Howard Chu
   CTO, Symas Corp.           http://www.symas.com
   Director, Highland Sun     http://highlandsun.com/hyc/
   Chief Architect, OpenLDAP  http://www.openldap.org/project/

Comment 11 OpenLDAP project 2017-09-06 14:19:13 UTC
Invalid/not ours
Comment 12 Howard Chu 2017-09-06 14:19:13 UTC
changed notes
changed state Open to Closed