Introduction
Notes to kernel developers: The goal of capabilities is divide the power of superuser into pieces, such that if a program that has one or more capabilities is compromised, its power to do damage to the system would be less than the same program running with root privilege. Capabilities(7) — Linux manual page
Capabilities are a fine-grained access control mechanism in Linux, allowing more granular permissions than the traditional superuser (root) model. Capabilities divide the privileges typically associated with the root user into distinct units that can be independently enabled or disabled for different processes. This allows for more secure and controlled privilege management.
For example, a process may need permission to bind to privileged ports but not require any other elevated permissions.
Understanding Capabilities
To see how many capabilities our Linux host is aware of, we can query the file cap_last_cap inside the /proc directory:
The capsh --print command displays the current capabilities and related settings of the shell or the process invoking the command. When executing this command on our Linux host, we see the full list of capabilities.
Each capability corresponds to a specific privileged action.
Backdooring Python
The command setcap sets file capabilities on an executable. The cap_setuid capability allows a process to make arbitrary manipulations of user IDs (UIDs), including setting the UID to a value that would otherwise be restricted (i.e. UID 0, the root user). setcap takes a set of parameters, where
- e: Effective means the capability is activated
- p: Permitted means the capability can be used/is allowed.
Putting this together, we’re adding the cap_setuid capabilities to the Python binary:
One can find a list of supported capabilities here:
Testing
For testing purposes, we created a new user (malmoeb) and switched to the context of this user (useradd && su):
Using the following command line, we set the UID of the bash shell we are calling with Python to 0 (UID 0 == root), effectively spawning a root shell:
The exciting thing about this technique is that we have not set a suid bit on a binary, or changed the Python binary. By setting the capabilities, we, as attackers, can build a powerful backdoor.
Hunting
Traditionally, system administrators and security professionals have focused on finding SUID (Set User ID) and SGID (Set Group ID) files, because these files can be used to escalate privileges under certain conditions. However, with the introduction of POSIX capabilities, it is now equally important to hunt for files with capabilities set, as demonstrated above.
Enumerating all binaries with capabilities set is possible with the command getcap -r:
Inside the /proc directory:
where:
- CapInh = Inherited capabilities
- CapPrm = Permitted capabilities
- CapEff = Effective capabilities
- CapBnd = Bounding set
- CapAmb = Ambient capabilities set
Utilising the command capsh, we decode the capabilities as follows:
Or with the command getpcaps, passing the PID as an argument:
Remove the capabilities from a binary with setcap -r
LinPeas
LinPEAS, the Linux Privilege Escalation Awesome Script, also performs some checks to find (interesting) capabilities. Following the commands taken directly from the relevant script:
- Current shell capabilities: cat "/proc/$$/status"
- Parent process capabilities: cat "/proc/$PPID/status"
- Files with capabilities: getcap -r / 2>/dev/null
Besides checking for suid files, LinPEAS does an excellent job here for searching for (hidden) capabilities discussed so far.
Elastic rule: Process Capability Set via setcap Utility
Elastic “detects the use of the setcap utility to set capabilities on a process.” See here for the full description.
security.capability
Extended permissions—such as access control lists (ACLs) set with setfacl and capability flags set with setcap are stored in the same location as traditional permission bits and setuid/setgid flags configured via chmod: the file’s inode.
The ls command does not display capability flags set by setcap. To view them, use getcap. To list all extended attributes, you can use getfattr -d -m -. The attribute setcap uses is security.capability, and it’s stored in a binary format that getcap conveniently decodes for you.
Conclusion
While traditional SUID/SGID checks are still crucial, modern security practices must include hunting for files with specific capabilities set. Capabilities provide a more granular and potentially stealthy way to grant necessary privileges, and if not monitored, they can introduce significant security risks. Using tools like getcap to search the file system for these capabilities recursively is essential to ensure a comprehensive security audit and to mitigate potential exploitation vectors.
We have not touched upon user capabilities, which are stored in the /etc/security/capability.conf configuration file, or the service files, where you can specify AmbientCapabilities. The following section presents two good resources for an in-depth discussion of this topic.
References
Here are two recommended websites if you want to dig deeper into this topic: