Linux Capabilities and how to avoid being root

In recent articles, we have talked about access control mechanisms and the role that they play in the security of multi-user operating systems. Through these mechanisms, the system creates a work context for each user where they perform their tasks with the privileges assigned to them. However, to provide some specific functionalities, it is necessary for a non-privileged user to occasionally temporarily acquire a superuser (root) profile to perform a specific task.
This functionality is achieved mainly by attributing privileges through sudo, or assigning special set user-id or setuid permissions to an executable file. This mechanism allows the users to adopt the role of file owner when they execute it, acquiring the same privileges as the latter. This type of permission is identified with the attribute “s” when executable files are listed, which indicates that the setuid bit is active.
It is possible to check the files that have setuid permission with the following command:
find / -perm -4000 -exec ls -l {} \; 2>/dev/null
- Searching for files with setuid in the system. Observe the indicative “s”-
It is important to bear in mind that risks are inherent in these mechanisms due to the change of context of privileges that occurs during the execution. This circumstance constitutes a security breach when there is a vulnerability in the executable file that allows someone to take control of the execution, thus escaping the security context of the process while maintaining the privileges.
- Privilege elevation: sudo, setuid… are they secure? -
This is why both the permissions attributed by sudo and by setuid must be carefully administered and given with caution due to the security risk that they entail.
In Linux, to control these circumstances, there are additional security mechanisms that make use of the LSM (Linux Security Modules) framework available since kernel version 2.6. An example of this is Mandatory Access Control (MAC), such as the implementations SELinux or AppArmor.
However, and despite these protections, assuming the role of a privileged user with all that this entails carries great risks and clashes with the principle of least privilege,which must always be considered as axiomatic in terms of security.
Don’t be root, use the capabilities
Capabilities is a concept provided by a security system that allows root privileges to be “divided up” into different values. These values can be assigned independently to processes so that to perform a privileged operation, this process may only contain the privilege necessary, without the need to assume the identity of superuser.
Due to the granularity that the capabilities provide and the lack of requirement to acquire root identity, they are a very useful method for assigning privileged permissions to specific tasks. For example, capabilities are a fundamental security element in virtualization systems such as Docker or Linux containers for the management of security contexts.
Despite being present since Linux kernel version 2.2, the use of capabilities is not common, and, in general, it is unknown by administrators and/or users.
Capabilities are a good tool for securing Linux systems when we know the possibilities that a particular capability provides. If there is not this knowledge, random assigning may be used to perform an operation that is, a priori, not envisaged.
Knowing the capabilities
There is currently an extensive list of capabilities available, defined in the capability library.
Without going into too much detail, we can say that the files and processes of the system have a set of 3 flags for the capabilities, which are: P (Permitted), E (Effective) and I (Inheritable), which are used to decide, through an algorithm, the final privilege to apply in the execution. The description of these flags and the algorithm can be consulted in detail at the following link: POSIX Capabilities & File POSIX Capabilities
In essence, by assigning a capability to a file with flags E and P, we can say that the resulting process in the execution will have this capability without it being extended to potential child processes.
What do we gain from it? We basically avoid allowing a process to elevate privileges to the superuser level when it really doesn’t require more than certain permissions for a specific operation. By way of example, the CAP_SYS_TIME capability can be assigned for any non-privileged user to change the system date without becoming root. Logically, it is not a good idea to allow this for any user, but it is useful for explaining its basic operation.
By assigning the CAP_SYS_TIME capability with the appropriate flags to the command date, we are authorising its execution to allow the process to acquire the system’s time change privilege:
- Effect of assigning the CAP_SYS_TIME capability to /bin/date –
As such, a privileged operation can take place without assuming the identity of superuser.
Using the capabilities, it is possible for the users or processes to carry out privileged tasks with greater granularity when assigning the necessary permissions. If in the case of using a setuid to give a privilege to /bin/date, a vulnerability in the bit allowed an attacker to obtain a shell in the execution, the result would be a shell with root privileges… game over. However, in the foregoing case, only the cap_sys_time privilege would be obtained, or even no privilege, when it is not specified as inheritable.
Operation of capabilities
The Linux packets libcap and libcap-bin incorporate the libraries and bits necessary for the use and administration of capabilities.
The commands provided are:
getcap: List of capabilities of a file
setcap: It assigns/deletes capabilities to/from a file
getpcaps: It lists the capabilities of a process
capsh: It provides an interface of a command line to test and explore the use of capabilities
Additionally, the libpam-cap packet provides support to PAM (Pluggable Authentication Modules). The use of capabilities in combination with PAM further increases the possibilities so it is possible to assign capabilities depending on the user who logs in, thus avoiding attributing a capability to a file that can be executed by anyone.
In conclusion, capabilities contribute granularity, which facilitates the perennially complicated task of securing a system. For system administrators, they are a very valuable tool for designing a more advanced and precise security strategy in a multi-user setting with different privilege levels. This mechanism contributes to laying the ground for applying the security “dogma” represented by the principle of least privilege. However, and as always, the assigning of any type of privilege must be analysed with the utmost care.
To implement a robust capabilities-based security strategy, its integration with the other security layers of the system must be borne in mind: MAC, PAM, SELinux and DAC access control.