Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Date: Tue, 3 Jan 2017 12:06:15 +0100
From: Sebastian Krahmer <krahmer@...e.com>
To: oss-security@...ts.openwall.com
Cc: jfrickson@...ios.com
Subject: Re: Nagios Core < 4.2.4 Root Privilege Escalation
 [CVE-2016-9566]

Hi

On Tue, Dec 20, 2016 at 05:16:39PM -0200, Dawid Golunski wrote:
> Vulnerability:
> Nagios Core < 4.2.4  Root Privilege Escalation CVE-2016-9566
> 
> Discovered by: Dawid Golunski (@dawid_golunski)
> https://legalhackers.com
> 
> Severity: High

[...]

> 
> Nagios daemon was found to open the log file before dropping its root 
> privileges on startup:
> 
> 8148  open("/usr/local/nagios/var/nagios.log",
> O_RDWR|O_CREAT|O_APPEND, 0666) = 4
> 8148  fcntl(4, F_SETFD, FD_CLOEXEC)     = 0
> 8148  fchown(4, 1001, 1001)             = 0
> 8148  getegid()                         = 0
> 8148  setgid(1001)                      = 0
> 8148  geteuid()                         = 0
> [...]

I have had a look at the upstream patch:

https://github.com/NagiosEnterprises/nagioscore/commit/c29557dec91eba2306f5fb11b8da4474ba63f8c4

I think the patch is insufficient in many ways.


Basically the patch is introducing a O_NOFOLLOW and an fstat()
afterwards. O_NOFOLLOW only works for symlinks, but attackers
may also create hardlinks (on the same FS, lets put
Linux link restrictions aside since it may affects other OS's too).

The fstat() check comes too late, the open() already happened
and may caused side-effects (driver files etc.). OTOH, a stat()
before open would be racy. Then, any of the path components
of the logdir may be nagios owned and flipped with symlinks inside subdirs,
since O_NOFOLLOW only fails on the last component being a symlink.

Then, IMHO its not a good idea to have the fix_log_file_owner(uid, gid)
call inside drop_privileges(), since when drop_privileges() fails,
for example because nagios attacker is spawning many zombies,
making setuid() fail, the following logit() call may be invoked as root, ending again in
open_log_file():

597 if(drop_privileges(nagios_user, nagios_group) == ERROR) {
598      logit(NSLOG_PROCESS_INFO | NSLOG_RUNTIME_ERROR,...  Aborting.");

Also, the fix_log_file_owner(uid, gid); call may fail and no error
is checked on return. The call may fail because its calling
open_log_file(). IMHO, dropping privs and setting up the logfiles
should really be separated.
 
There is also this prctl(PR_SET_DUMPABLE, 1) call which may
be dangerous as its a potential attack vector for ptrace injections.

TL;DR: there is no safe way of creating/chowning files inside user owned
directories when running as root. Theres almost in all cases a race, since you
have no fix point. Or at least making some fix point creates a lot
of effort and headache. Its much cleaner to drop to user and then doing
the file-related work. Since the logdir is nagios owned anyway,
I dont see why there is this root/chown approach.


Sebastian

-- 

~ perl self.pl
~ $_='print"\$_=\47$_\47;eval"';eval
~ krahmer@...e.com - SuSE Security Team

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.