Category Icon
security
|
31.08.2023

No Love for Negative Permissions

TL;DR: Avoid using negative permissions; on modern Linux systems, they can be circumvented.

Linux offers a diverse range of methods for implementing file permissions. In addition to the traditional discretionary access control (DAC), it also supports access control lists (ACL) and mandatory access control (MAC). Typically, all of these methods operate in a positive manner, meaning that each established permission configuration grants power. By default, nothing is permitted. This approach is also occasionally termed white or allow listing. However, both DAC and ACL do allow the implementation of negative permissions. Negative permissions deny access to certain users or groups while everybody else retains access. This practice is much less common and is widely seen as a poor security practice within the community.

With the advent of Linux containers, the landscape has shifted, rendering negative permissions not only a poor practice but also susceptible to bypass attacks. In contemporary Linux systems, there’s a significant likelihood that users can sidestep negative permissions and potentially gain entry to protected files.

Example of Negative Permissions

Let’s consider a scenario where everyone has access to the /usr/share/games folder. However, there’s a desire to prevent specific users from playing games. To achieve this, a new group called nogames is established, and a negative permission is implemented to deny access for members belonging to this group.

1
2
3
4
5
root@host$ groupadd nogames
root@host$ usermod -G nogames bob
root@host$ usermod -G nogames john
root@host$ chown root:nogames /usr/share/games/
root@host$ chmod u=rwx,g=,o=rx-w /usr/share/games/

Now, users bob and john are effectively restricted from accessing the /usr/share/games directory. This outcome is achieved due to the priority sequence: user DAC entries take precedence over group, and group takes precedence over other. Given that both bob and john belong to the nogames group, the permissions established for the nogames group take precedence, resulting in no granted permissions for them. Conversely, for all other users, either the user or the other entities come into play. The same objective can also be accomplished using Access Control Lists (ACLs) in place of discretionary access control (DAC). For instance, you can implement an ACL using a command like setfacl -m g:nogames:--- /usr/share/games.

Exploiting the Problem

Certainly, if a user manages to remove themselves from the nogames group, access would be restored. The setgroups()1 system call enables the modification of supplementary groups associated with the current process. Naturally, such an operation requires privileged capabilities, specifically the CAP_SETGID capability. This mechanism highlights the significance of managing privileges and group memberships to effectively uphold the desired access controls.

With the advent of Linux containers, particularly user namespaces, the dynamics have shifted. In a user namespace, an unprivileged user possesses all capabilities. However, every action taking place within the namespace is associated with the user and group IDs of the namespace’s creator. For enabling rootless container engines like podman, the shadow-utils package includes a lesser-known toolkit: newuidmap2 and newgidmap3. These tools are either set-uid-root or possess the file capability CAP_SETGID. By utilizing these tools, users can establish a fresh user namespace and set up UID and GID mappings that target distinct IDs from those of the invoking task. These mappings are maintained in /etc/subuid and /etc/subgid. When a user is created, the useradd tool configures these designated subordinate IDs.

Having multiple group ID mappings in place empowers a process within a user namespace once again to employ the setgroups() syscall, allowing it to shed supplementary groups at its discretion!

1
2
3
4
bob@host$ ls /usr/share/games
ls: cannot open directory '/usr/share/games': Permission denied
bob@host$ unshare -G 0 --map-groups=100000,0,1 ls /usr/share/games
atc  boggle quiz

The unshare tool internally employs newuidmap and newgidmap. By consulting /etc/subgid, we know that the user named bob can utilize the subordinate group ID 100000.

1
2
3
4
bob@host$ ls /usr/share/games
ls: cannot open directory '/usr/share/games': Permission denied
bob@host$ podman run --rm -it -v /:/xxx/ docker.io/bash ls /xxx/usr/share/games
atc  boggle quiz

podman in rootless mode can also be utilized to achieve the same result.

User based Negative Permissions

An attentive reader might wonder about negative permissions based on users, as we’ve mostly talked about groups so far. Consider a scenario involving negative ACLs like this: let’s say we want to prevent user bob from accessing games using an ACL command like setfacl -m u:bob:--- /usr/share/games. Once again, using unshare along with newuidmap proves to be effective. However, this time, it doesn’t involve dropping additional groups. Instead, it works by changing the effective user ID to one within a specific range.

1
2
3
4
bob@host$ ls /usr/share/games
ls: cannot open directory '/usr/share/games': Permission denied
bob@host$ unshare -S 0 --map-users=100000,0,1 ls /games
atc  boggle quiz

Background and History

At first, the idea that dropping or changing group memberships might cause problems wasn’t considered when user namespaces were added. This was mainly because people didn’t think about situations where permissions work in a negative way. It was assumed that if you leave a group, you’d have less power, and on Linux diminishing one’s own authority is usually okay. Yet, it didn’t take long to realize4 that dropping groups could actually give more power when dealing with negative permissions. This discovery led to an issue known as CVE-2014-8989, which was quickly fixed in Linux version 3.19.

In 2018, it was discovered that version 4.5 of the shadow-utils package introduced a new tool named newgidmap. This tool can be used to create more complex mappings for group IDs within user namespaces. Consequently, it reinstates the ability to drop group memberships using the setgroups() syscall5. This issue was given the tracking identifier CVE-2018-7169. The resolution adopted by some Linux distributions was to exclude this tool from their packages. Furthermore, newuidmap assists users in changing their user ID to one within an authorized range, as configured in /etc/subid6. This maneuver can also serve to circumvent negative permissions based on user settings.

Though this problem wasn’t a kernel bug, it became evident that rectifying this vulnerability without disrupting established programs like podman would require a non-trivial kernel change78.

Other potential solutions also focused on the shadow-utils package itself9, but as of now, they haven’t gained significant traction. Ultimately, by 2021, a general agreement was reached to move away from supporting negative permissions and to acknowledge the reality that they can be circumvented10.

In 2023, Richard rediscovered the problem and opted to comprehensively document it across multiple Linux manual pages11.

Summary

Negative permissions have consistently been regarded as bad practice and often treated as theoretical concept. With the incorporation of Linux containers, negative permissions can now be evaded.

If you find yourself reliant on them, consider one of the following actions:

  • Restructure your permissions into proper allow rules; this is the most recommended approach.
  • Ensure that neither newuidmap nor newgidmap is present. As of 2023, these two tools are the primary gateways for bypassing such permissions. However, this situation might change in the future.
  • Completely disable user namespaces by setting the user.max_user_namespaces sysctl to 0.
  • On Ubuntu-based systems, you can also use the kernel.unprivileged_userns_clone to disable user namespaces only for unprivileged users.

Finally, it is worth noting that there is still effort to tame newgidmap and newuidmap12.

Publish date

31.08.2023

Category

security

Authors

Richard Weinberger

Icon with a waving hand

Get in touch

+43 5 9980 400 00

sigma star gmbh
Eduard-Bodem-Gasse 6, 1st floor
6020 Innsbruck | Austria

LinkedIn logo
sigma star gmbh logo