Openwall GNU/*/Linux - a small security-enhanced Linux distro for servers
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Date: Thu, 18 Apr 2019 12:43:55 +0200
From: Matthias Gerstner <mgerstner@...e.de>
To: oss-security@...ts.openwall.com
Subject: Security issues in snapcraft snap-confine set*id binary

Hello,

a couple of security issues have been found in the snapcraft package
manager [1] during the course of a security review for inclusion of
snapcraft in openSUSE [2]. The basis for this review was upstream
version 2.37.4.

snapcraft uses a setuid/setgid root program called `snap-confine` to
setup namespace based containers for snap packages. While the program's
code is generally of good quality the following moderate security issues
have been found:

1) Up and including to version 2.37.4 the /tmp directory within a snap
  container was owned by the first user that entered the container. Since
  snap containers can be used by multiple users at the same time or a
  privileged program or daemon may run in a container, the security of
  files and directories in /tmp is compromised.  An attacker can remove
  or replace files and directories belonging to other users within the
  container's /tmp to achieve an unspecified impact.

  This issue was recently fixed by upstream via commit [3].

2) The `sc_join_preserved_ns()` function along with a number of other
  function remembers the current working directory (CWD) of the calling
  user outside of the container and attempts to restore this CWD again
  within the container. The `chdir()` operation to restore the CWD is
  performed with root privileges within the container and is prone to
  symlink attacks. Therefore an unprivileged user can enter arbitrary
  directories within the container. Example PoC:

  ```
  user1 $ snap run --shell opera
    user1 $ cd /tmp
    user1 $ umask 077
    user1 $ mkdir user1_private
    user1 $ cd user1_private
    user1 $ umask 022
    user1 $ mkdir subdir
    user1 $ cd subdir
    user1 $ echo secret >file

  user2 $ cd /tmp
  user2 $ mkdir -p user1_private/subdir
  user2 $ ln -s /tmp/user1_private/subdir user2_private
  user2 $ cd user2_private
  user2 $ snap run --shell opera
    user2 $ /tmp/user1_private/subdir
    user2 $ cat file
    secret
  ```

  In this example user2 enters the public sub-directories of a private
  tmp directory of user1 within the application container. Basically
  this can also be used to enter /root or /var/lib/snapd/hostfs/root/.config
  and so on.

  The severity of this issue is reduced, because snap-confine employs
  extensive AppArmor profiles that prevent many file system accesses
  beyond classic DAC permission checks.

  This issue is addressed by an upstream PR [4].

3) In function `sc_parse_mountinfo_entry()` the pseudo file
  /proc/self/mountinfo is parsed. In the subsequently called helper
  function `parse_next_string_field()` most of the content of each line
  from that file is parsed. This helper function uses `sscanf()` with a
  "%s%n" format. %s in `sscanf()` extracts a whitespace delimited
  string. While the kernel protects e.g. against newlines found in
  directory names by encoding them specially in the mountinfo file,
  there are whitespace characters that are not protected against.
  Unprivileged users can use mechanisms like FUSE based file systems
  like sshfs to mount file systems onto such strangely named
  directories:

  ```
  user $ cd /tmp
  user $ mkdir `echo -e "strange\rdir"`
  user $ sshfs localhost:/tmp strange?dir
  ```

  The result will be an entry in /proc/self/mountinfo that looks like
  this:

  ```
  111 107 0:49 / /tmp/strange\rdir rw,nosuid,nodev,relatime shared:59 - fuse.sshfs localhost:/tmp/ rw,user_id=1000,group_id=100\n
  ```

  The parsing logic in snap-confine will wrongly treat "/tmp/strange" as
  the `mount_dir` and continue parsing "the next field" after the
  carriage return.  Basically this allows the attacker to provide the
  rest of the fields parsed by snap-confine via the directory name. In
  my tests no failure was detected by `sc_parse_mountinfo()`, since
  parsing "%s" always works as long there is data left to parse.

  I don't see any viable attack vector here at the moment. To actually
  control the behaviour of snap-confine we'd need to control the field
  (4) of the mountinfo file. This field is only available to
  unprivileged users if they can perform a bind mount. Maybe there is a
  setuid tool around that allows such things, then it would be a tool to
  further influence what snap-confine does. In such a case it could e.g.
  be used to force triggering of the discard-ns logic of snap-confine.

  This issue is addressed by an upstream PR [5].

I've asked upstream to assign CVEs for issues 1) and 2) but they're not
available yet.

Best Regards

Matthias

[1]: https://snapcraft.io/
[2]: https://bugzilla.suse.com/show_bug.cgi?id=1127368
[3]: https://github.com/snapcore/snapd/commit/bdbfeebef03245176ae0dc323392bb0522a339b1
[4]: https://github.com/snapcore/snapd/pull/6642
[5]: https://github.com/snapcore/snapd/pull/6605

-- 
Matthias Gerstner <matthias.gerstner@...e.de>
Dipl.-Wirtsch.-Inf. (FH), Security Engineer
https://www.suse.com/security
Phone: +49 911 740 53 290
GPG Key ID: 0x14C405C971923553

SUSE Linux GmbH
GF: Felix Imendörffer, Mary Higgins, Sri Rasiah
HRB 21284 (AG Nuernberg)

Download attachment "signature.asc" of type "application/pgp-signature" (834 bytes)

Powered by blists - more mailing lists

Your e-mail address:

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.