Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
Bug 641042 - <net-dns/unbound-1.6.8-r2: root privilege escalation via writable config file
Summary: <net-dns/unbound-1.6.8-r2: root privilege escalation via writable config file
Status: RESOLVED FIXED
Alias: None
Product: Gentoo Security
Classification: Unclassified
Component: Vulnerabilities (show other bugs)
Hardware: All Linux
: High major (vote)
Assignee: Gentoo Security
URL:
Whiteboard: B1 [glsa+]
Keywords:
Depends on:
Blocks:
 
Reported: 2017-12-14 19:26 UTC by Michael Orlitzky
Modified: 2019-04-02 04:20 UTC (History)
1 user (show)

See Also:
Package list:
Runtime testing required: ---


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Michael Orlitzky gentoo-dev 2017-12-14 19:26:46 UTC
The ebuilds for net-dns/unbound create the "unbound" user with its home directory set to /etc/unbound:

  pkg_setup() {
    enewgroup unbound
    enewuser unbound -1 -1 /etc/unbound unbound

    use python && python-single-r1_pkg_setup
  }

As a result, /etc/unbound is writable by the "unbound" user. However, that's where the sensitive unbound.conf gets installed (as root:root):

  $ /bin/ls -al /etc/unbound/
  total 44
  drwxr-xr-x  2 unbound root  4096 Dec 14 13:59 .
  drwxr-xr-x 79 root    root  4096 Dec 14 13:59 ..
  -rw-r--r--  1 root    root 34276 Dec 14 13:59 unbound.conf

That conf file must only be writable by root; at least...

  * the OpenRC service script uses the value of "pidfile" found
    in unbound.conf, so anyone who can edit that file can clobber
    things on the fileystem.

  * the daemon binds to its interface and port as root, so the
    "unbound" user could bind to e.g. port 80.

  * From daemon/unbound.c and daemon/remote.c, it looks like unbound
    will call "chown" on its pidfile/socket respectively, meaning that
    if the "unbound" user can alter the pidfile or local socket location,
    then he can take control of any file the next time the daemon is
    started. (I haven't tested this one, because the first two are bad
    enough.)

I just noticed this on our DNS servers a few minutes ago, and have done

  chown root /etc/unbound

as a quick workaround. Nothing bad seems to have happened so far, but it's only been a few minutes. I'll report back if the phones start ringing.
Comment 1 Marc Schiffbauer gentoo-dev 2017-12-14 23:29:02 UTC
Thanks for spotting! I think the ebuild should 'chown root /etc/unbound' to fix this.

But caution has to be taken when unbound is running chrooted into /etc/unbound (this is the default) because unbound then cannot update the DNSSEC trust anchor file anymore for example. Something like /etc/unbound/var that is owned by unbound will help then.
Comment 2 Michael Orlitzky gentoo-dev 2017-12-15 02:28:44 UTC
(In reply to Marc Schiffbauer from comment #1)
> Thanks for spotting! I think the ebuild should 'chown root /etc/unbound' to
> fix this.

Yeah, regardless of any other changes to the ebuild, someone -- either us, in pkg_postinst, or the user himself -- will need to fix the existing ownership information. That's actually pretty hard to get right in general, but I think you're lucky. Since you only need to change ownership of one path (/etc/unbound) and it lives in a root-owned directory (/etc), the following should be safe:

  if [[ -d "${ROOT}/etc/unbound" ]]; then
    chown --no-dereference --from=unbound root "${ROOT}/etc/unbound"
  fi

in pkg_postinst.


> But caution has to be taken when unbound is running chrooted into
> /etc/unbound (this is the default) because unbound then cannot update the
> DNSSEC trust anchor file anymore for example. Something like
> /etc/unbound/var that is owned by unbound will help then.

I don't know enough about unbound to know what it needs in the chroot.. would something like the following work?

  1. Change the "enewuser" to set $HOME to /dev/null (just delete all the
     args to enewuser)

  2. Dosym a link /var/lib/unbound/etc/unbound -> /etc/unbound

  3. Change the default chroot path from /etc/unbound to /var/lib/unbound

That way, /etc/unbound is safe but a chrooted daemon can see it. If the chrooted daemon needs to be able to write to something, you can make /var/lib/unbound or one of its subdirectories writeable by the "unbound" user.

The daemon is willing to start for me out-of-the-box with those modifications, but I don't know how to make it try to write stuff.

Also, so I don't forget... if the above steps turn out to work, there is an ugly  item "1.a." that we'll need to address; namely updating the home directory for any "unbound" users that already exist on the system.
Comment 3 Thomas Deutschmann gentoo-dev Security 2018-02-21 23:19:15 UTC
@ Maintainer(s): Can we please get a status update?
Comment 4 Marc Schiffbauer gentoo-dev 2018-02-23 00:52:44 UTC
I will have a look and then a fix very soon. Thanks for the reminder.
Comment 5 Marc Schiffbauer gentoo-dev 2018-02-23 20:13:25 UTC
Fixed and revbunped in 6f3d0c2027034767f2acf1b52940c15ec137d6c0
Thanks Michael for spotting.
FYI: I fix ownership in pkg_setup() as this is where the user and his $HOME is created. If we did this in pkg_postinst() that would have been racy
Comment 6 Thomas Deutschmann gentoo-dev Security 2018-02-23 22:59:51 UTC
@ Marc: Please do not close security bugs.

@ Michael: Can you please review the changes and ack/nack?
Comment 7 Michael Orlitzky gentoo-dev 2018-02-24 00:04:44 UTC
Is there a reason to keep

  enewuser unbound -1 -1 /etc/unbound unbound

instead of

  enewuser unbound -1 -1 -1 unbound

going forward? Its homedir will be unwritable either way, now. Regardless, the immediate problem looks fixed. Thank you!
Comment 8 Robin Johnson archtester Gentoo Infrastructure gentoo-dev Security 2018-02-24 23:05:28 UTC
This has broken unbound usage for trust-anchor fetching, and broke all of the Gentoo infra unbound instances!

open("root-anchors.txt.3292-0", O_WRONLY|O_CREAT|O_TRUNC, 0666) = -1 EACCES (Permission denied)
sendto(8, "<26>Feb 24 22:58:09 unbound: [3292:0] fatal error: could not open autotrust file for writing, root-anchors.txt.3292-0: Permission denied", 136, MSG_NOSIGNAL, NULL, 0) = 136

Per upstream unbound EXPECTS to be able to write this.

Per the unbound.conf manpage:
       auto-trust-anchor-file: <filename>
              File  with  trust  anchor for one zone, which is tracked with RFC5011
              probes.  The probes are several times per  month,  thus  the  machine
              must be online frequently.  The initial file can be one with contents
              as described in trust-anchor-file.  The file is written to  when  the
              anchor  is  updated,  so the unbound user must have write permission.
              Write permission to the file, but also to the directory it is in  (to
              create  a  temporary file, which is necessary to deal with filesystem
              full events), it must also be inside the chroot (if that is used).
Comment 9 Robin Johnson archtester Gentoo Infrastructure gentoo-dev Security 2018-02-24 23:26:00 UTC
While I agree with the intent of deploying this fix, the silent breakage on a revbump without any other notice of it is what caught me out. 

1. let's ship the example unbound.conf that uses "var/" prefix in auto-trust-anchor-file
2. pre-create /etc/unbound/var/ that IS writable by the daemon, and is populated ready to go.
Comment 10 Michael Orlitzky gentoo-dev 2018-02-25 07:03:59 UTC
How about creating /var/lib/unbound writable by the unbound user and then setting --with-run-dir=/var/lib/unbound (i.e. comment #2)? I think /var is a better place for this data, but only if it doesn't cause other problems with the chroot.
Comment 11 Marc Schiffbauer gentoo-dev 2018-02-26 01:08:11 UTC
(In reply to Robin Johnson from comment #9)
> While I agree with the intent of deploying this fix, the silent breakage on
> a revbump without any other notice of it is what caught me out. 
> 
> 1. let's ship the example unbound.conf that uses "var/" prefix in
> auto-trust-anchor-file
> 2. pre-create /etc/unbound/var/ that IS writable by the daemon, and is
> populated ready to go.

+1

I revbumped with a fix for auto-trust-anchor-file and add an additional var/ dir in /etc/unbound

@Michael: Thanks for your suggestion. But using --with-run-dir would cause more things to be changed which I want to avoid. For example the config file would not be in the chroot anymore, so we'd have to install it in run-dir as well and then create a symlink in /etc/unbound... I would find this too invasive for what we'd like to achieve now.

And I am still not completey happy with this whole trust anchor file handling: at some point in the past the dnssec-root package has been added to the tree and unbound depends on it.
And we compile unbound with --with-rootkey-file="${EPREFIX}"/etc/dnssec/root-anchors.txt which makes unbound-anchor and unbound-host use this file as default.
The man-page of unbound-anchor suggests to run unbound-anchor and then start unbound with a config that lets auto-trust-anchor-file point to /etc/dnssec/root-anchors.txt so its basedir would need to be writable by unbound to make updates work, which is bad.
Additionally this breaks unbounds default chroot support because /etc/dnssec is outside the unbound chroot.
So I will just patch the example config file to suggest /etc/unbound/var/root-anchors.txt as value for auto-trust-anchor-file.
Comment 12 Aaron Bauman Gentoo Infrastructure gentoo-dev Security 2018-11-23 23:26:21 UTC
(In reply to Marc Schiffbauer from comment #11)
> (In reply to Robin Johnson from comment #9)
> > While I agree with the intent of deploying this fix, the silent breakage on
> > a revbump without any other notice of it is what caught me out. 
> > 
> > 1. let's ship the example unbound.conf that uses "var/" prefix in
> > auto-trust-anchor-file
> > 2. pre-create /etc/unbound/var/ that IS writable by the daemon, and is
> > populated ready to go.
> 
> +1
> 
> I revbumped with a fix for auto-trust-anchor-file and add an additional var/
> dir in /etc/unbound
> 
> @Michael: Thanks for your suggestion. But using --with-run-dir would cause
> more things to be changed which I want to avoid. For example the config file
> would not be in the chroot anymore, so we'd have to install it in run-dir as
> well and then create a symlink in /etc/unbound... I would find this too
> invasive for what we'd like to achieve now.
> 
> And I am still not completey happy with this whole trust anchor file
> handling: at some point in the past the dnssec-root package has been added
> to the tree and unbound depends on it.
> And we compile unbound with
> --with-rootkey-file="${EPREFIX}"/etc/dnssec/root-anchors.txt which makes
> unbound-anchor and unbound-host use this file as default.
> The man-page of unbound-anchor suggests to run unbound-anchor and then start
> unbound with a config that lets auto-trust-anchor-file point to
> /etc/dnssec/root-anchors.txt so its basedir would need to be writable by
> unbound to make updates work, which is bad.
> Additionally this breaks unbounds default chroot support because /etc/dnssec
> is outside the unbound chroot.
> So I will just patch the example config file to suggest
> /etc/unbound/var/root-anchors.txt as value for auto-trust-anchor-file.

Which version did you push with this fix?
Comment 13 Marc Schiffbauer gentoo-dev 2018-12-03 17:02:52 UTC
(In reply to Aaron Bauman from comment #12)
> (In reply to Marc Schiffbauer from comment #11)
> > (In reply to Robin Johnson from comment #9)
> > > While I agree with the intent of deploying this fix, the silent breakage on
> > > a revbump without any other notice of it is what caught me out. 
> > > 
> > > 1. let's ship the example unbound.conf that uses "var/" prefix in
> > > auto-trust-anchor-file
> > > 2. pre-create /etc/unbound/var/ that IS writable by the daemon, and is
> > > populated ready to go.
> > 
> > +1
> > 
> > I revbumped with a fix for auto-trust-anchor-file and add an additional var/
> > dir in /etc/unbound
> > 
> > @Michael: Thanks for your suggestion. But using --with-run-dir would cause
> > more things to be changed which I want to avoid. For example the config file
> > would not be in the chroot anymore, so we'd have to install it in run-dir as
> > well and then create a symlink in /etc/unbound... I would find this too
> > invasive for what we'd like to achieve now.
> > 
> > And I am still not completey happy with this whole trust anchor file
> > handling: at some point in the past the dnssec-root package has been added
> > to the tree and unbound depends on it.
> > And we compile unbound with
> > --with-rootkey-file="${EPREFIX}"/etc/dnssec/root-anchors.txt which makes
> > unbound-anchor and unbound-host use this file as default.
> > The man-page of unbound-anchor suggests to run unbound-anchor and then start
> > unbound with a config that lets auto-trust-anchor-file point to
> > /etc/dnssec/root-anchors.txt so its basedir would need to be writable by
> > unbound to make updates work, which is bad.
> > Additionally this breaks unbounds default chroot support because /etc/dnssec
> > is outside the unbound chroot.
> > So I will just patch the example config file to suggest
> > /etc/unbound/var/root-anchors.txt as value for auto-trust-anchor-file.
> 
> Which version did you push with this fix?


IIRC Robin pushed the fix that I suggested. Current state ist that both versions of unbound in the tree have the fix.

And looking at git log all versions >=1.6.8-r2 had the fix


-Marc
PS: Sorry for the delay :-/
Comment 14 GLSAMaker/CVETool Bot gentoo-dev 2019-04-02 04:20:58 UTC
This issue was resolved and addressed in
 GLSA 201904-03 at https://security.gentoo.org/glsa/201904-03
by GLSA coordinator Aaron Bauman (b-man).