Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date: Thu, 7 Sep 2017 21:38:11 +0100
From: Simon McVittie <smcv@...ian.org>
To: oss-security@...ts.openwall.com
Subject: Re: CVE-2017-12847: nagios-core privilege escalation
 via PID file manipulation

On Thu, 07 Sep 2017 at 12:29:50 -0400, Daniel Kahn Gillmor wrote:
> On Thu 2017-09-07 16:27:25 +0100, Simon McVittie wrote:
> > Ideally, the sequence of events would be something that ensures that
> > the pid file already exists by the time readiness has been announced,
> > like this pseudocode:
> >
> >     have the necessary privileges to write a pid file
> >     fork
> >     if (parent) {
> >         write child pid to pid file
> >         exit    /* tells supervisor we are ready */
> >     }
> >     else /* child */ {
> >         drop privileges
> >         while (1) { process request }
> >     }
> 
> Is there a potential race condition here?  for example, if dropping
> privileges takes some amount of time, or if there is additional setup
> that ought to be done as non-root (building tables, pre-processing a
> dataset from the filesystem, initializing a PRNG), then this pattern is
> actually pretty hard to get right as a notification.

I was assuming a structure a bit like dbus-daemon, which calls bind()
and listen() while still privileged before forking. It does do some
additional setup as non-root after dropping privileges, but if a
client connects during that window, the client's socket will just block
for a short time (whether that means actually blocking or EAGAIN is up
to the client), until the dbus-daemon is ready to enter its main loop.
It won't get ECONNREFUSED, because the socket is already listening
(assuming the socket backlog is sufficiently long to accommodate all the
clients).

The daemon doesn't need to be ready to actually do its work before
forking, only ready to take responsibility for keeping clients waiting
until it *is* ready.

>  0) if dropping privs is known to be fast, then move any lengthy
>     initialization/setup into the root/pre-fork side.  this is a
>     violation of the principle of least privilege.

Arguably yes, but putting a minimal amount of setup before forking closes
the race condition, and some of that setup is probably going to need
privileges anyway (for example web servers that want to listen on port
80, or dbus-daemon --system which wants to listen on the root-owned
/var/run/dbus/system_bus_socket).

    S

Powered by blists - more mailing lists

Please check out the Open Source Software Security Wiki, which is counterpart to this mailing list.

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.