Linux Privilege Escalation - Capabilities for CTF Creators
Capabilities
In UNIX systems, there are two categories of processes:
Privileged Processes
- Effective UID is zero (0), referred to as root.
- Bypasses kernel permissions checks.
Unprivileged Processes
- Effective UID is nonzero.
- Full permissions checking is required.
Since the release of kernel 2.2, Linux has divided the privileges associated with the superuser into units known as capabilities. These capabilities can be enabled or disabled. For more information about capabilities, please refer to the official documentation.
Capabilities Commands
These are the commands that we can use for working with capabilities:
- setcap - Set File Capabilities
- setpcaps - Set Process Capabilities
- getcap - Get File Capabilities
- getpcaps – Get Process Capabilities
- capsh - Capability Shell Wrapper
Process Capabilities
We can find the capabilities of the current process with either of the following commands:
|
|
We can find the capabilities of another user with:
|
|
These can be decoded with capsh:
|
|
Dropping Capabilities with Capsh
If we drop the CAP_NET_RAW capabilities for ping, then the ping utility should no longer work:
|
|
Besides the output of capsh itself, the tcpdump command itself should also raise an error.
Working with Capabilities
We can use setcap to add capabilities to a file:
|
|
We can examine capabilities with getcap:
|
|
We can search for all capabilities:
|
|
We can remove capabilities with setcap:
|
|
Dangerous Capabilites
The following capabilities are particularly dangerous and should be investigated further if found enabled on a system:
Capabilities Name | Description |
---|---|
CAP_AUDIT_CONTROL | Allow to enable/disable kernel auditing |
CAP_AUDIT_WRITE | Helps to write records to kernel auditing log |
CAP_BLOCK_SUSPEND | This feature can block system suspends |
CAP_CHOWN | Allow user to make arbitrary change to files UIDs and GIDs |
CAP_DAC_OVERRIDE | This helps to bypass file read, write and execute permission checks |
CAP_DAC_READ_SEARCH | This only bypass file and directory read/execute permission checks |
CAP_FOWNER | This enables to bypass permission checks on operations that normally require the filesystem UID of the process to match the UID of the file |
CAP_KILL | Allow the sending of signals to processes belonging to others |
CAP_SETGID | Allow changing of the GID |
CAP_SETUID | Allow changing of the UID |
CAP_SETPCAP | Helps to transferring and removal of current set to any PID |
CAP_IPC_LOCK | This helps to lock memory |
CAP_MAC_ADMIN | Allow MAC configuration or state changes |
CAP_NET_RAW | Use RAW and PACKET sockets |
CAP_NET_BIND_SERVICE | SERVICE Bind a socket to internet domain privileged ports |
CAP_SYS_ADMIN | This means that you can mount/umount filesystems. |
CAP_SYS_PTRACE | This means that you can escape the container by injecting a shellcode inside some process running inside the host. |
CAP_SYS_MODULE | This means that you can insert/remove kernel modules in/from the kernel of the host machine. |
OTHERS….. |
Privilege Escalation via CAP_SETUID
The CAP_SETUID capability allows a process to set the user ID (UID) of a process. This is crucial for operations that require changing the effective user ID, real user ID, or saved set-user-ID of a process. Essentially, it enables a process to assume the identity of another user, which is typically necessary for tasks that require elevated privileges.
Perl Example
Copy the python3 binary to our current working directory:
|
|
Assign the cap_setuid
capability:
|
|
We can review the capability with the following:
|
|
Run a bash with uid
of 0
as shown in the variable $uid = 0
which is the root UID, and bash with exec("/bin/bash")
:
|
|
This will result in root:
|
|
Python Example
We’ll copy the python3 binary to our current working directory:
|
|
Then we’ll assign the cap_setuid
capability to the python3 executable that’s in the current folder:
|
|
We can review the capability with the following:
|
|
Run a bash shell with setuid
of 0
as shown in os.setuid(0)
which is the root UID, and bash with os.system("/bin/bash")
:
|
|
This will also result in root:
|
|
Privilege Escalation via CAP_SETGID
The CAP_SETGID capability allows a process to set the group ID (GID) of a process. This capability is similar to CAP_SETUID but applies to group IDs. It allows a process to change its effective group ID, real group ID, or saved set-group-ID. This is important for operations that need to change the group identity of a process, enabling it to perform actions on behalf of a different group.
Perl Example
Copy the Perl binary to the current folder:
|
|
The capability CAP_SETGID
allows us to set the EGID
of the created process.
|
|
View the groups:
|
|
Run this Perl code:
|
|
In this case, the shadow
group was impersonated so we can read the file /etc/shadow
:
|
|
Python Example
Copy the Python binary to the current folder:
|
|
The capability CAP_SETGID
allows us to set the EGID
of the created process.
|
|
View the groups:
|
|
Add this Python code:
|
|
In this case, the shadow
group was impersonated so we can read the file /etc/shadow
:
|
|
Privilege Escalation via CAP_SYS_ADMIN
The CAP_SYS_ADMIN capability is one of the most powerful and broad capabilities in the Linux system. It grants a wide range of administrative privileges that are not covered by other specific capabilities. Here are some of the key functions and permissions associated with CAP_SYS_ADMIN:
- Mounting and Unmounting Filesystems: Allows mounting and unmounting of filesystems.
- Setting Disk Quotas: Enables setting disk quotas for users.
- Modifying Kernel Parameters: Permits modification of certain kernel parameters.
- Performing System Reboots: Allows the system to be rebooted.
- Bypassing File Read, Write, and Execute Permissions: Grants the ability to bypass file permissions in certain contexts.
- Managing Namespaces: Allows creation and management of namespaces.
- Accessing Raw Sockets: Permits access to raw sockets, which can be used for network packet manipulation.
Due to its extensive range of permissions, CAP_SYS_ADMIN is often considered a “catch-all” capability, and it is crucial to use it with caution. Misuse or overuse of this capability can lead to significant security risks.
Mounting File System Example
This means that we can mount/umount filesystems.
|
|
Using Python we can mount a modified passwd
file on top of the real passwd
file:
|
|
Install the required modules:
|
|
Replace the /etc/passwd
file by creating the following Perl script:
|
|
In the above Perl code, we define a Perl subroutine named $mount
that wraps the libc.mount
function.
After that, we define the necessary variables ($source
, $target
, $filesystemtype
, $options
, and $mountflags
) with the corresponding values.
The code also includes a helper function, determine_syscall_number
, which attempts to determine the system call number for a given syscall name (mount in this case). It uses the syscall.ph
file, which should be present on your system, to determine the number. The code then invokes the system call using the determined number.
Please note that the determination of the system call number relies on the presence of the syscall.ph
file and the correct mapping of the syscall names. In some cases, additional steps may be required to ensure that the syscall.ph
file is available and up to date.
We could then mount the modified passwd file on /etc/passwd
:
|
|
Then we can switch to the root user with the password provided:
|
|
Privilege Escalation via CAP_FOWNER
The CAP_FOWNER
capability in Linux allows a process to bypass file ownership checks. This means that a process with this capability can perform operations on files as if it were the owner of those files. Here are some key points about CAP_FOWNER
:
- Bypass Ownership Checks: It allows processes to ignore the ownership of files when performing operations such as reading, writing, or executing.
- Modify File Attributes: Processes can change file attributes, such as permissions, without being the file owner.
- Override Restrictions: It can override certain restrictions that are normally enforced based on file ownership, providing greater flexibility in managing files.
This capability is particularly useful for system administrators and certain system processes that need to manage files across different users without being restricted by file ownership. However, it should be used with caution, as it can pose security risks if misused.
Perl Example
Copy the Perl binary to the current folder:
|
|
The capability CAP_FOWNER
allows us to change the permission of a file.
|
|
The original /etc/shadow
permissions are the following:
|
|
If Python has this capability we can modify the permissions of the shadow file, then change the root password, and as a result, elevate privileges:
|
|
Change the root password:
|
|
Elavate to the root user:
|
|
Python Example
The capability CAP_FOWNER
allows us to change the permission of a file.
|
|
The original /etc/shadow
permissions are the following:
|
|
If Python has this capability we can modify the permissions of the shadow file, then change the root password, and as a result, elevate privileges:
|
|
Change the root password:
|
|
Elevate to the root user:
|
|
Privilege Escalation via CAP_CHOWN
The capability CAP_CHOWN
allows us to change the ownership of any file.
|
|
Let’s suppose the Python binary has this capability, we can change the owner of the shadow file, change the root password, and escalate privileges:
|
|
Now we can read the /etc/shadow file:
|
|
Defense
Defending against capabilities can be challenging. Here are some key points to consider:
- Avoid using unnecessary capabilities: Only enable capabilities that are essential for the task at hand.
- Ensure capabilities cannot be exploited: Regularly review and audit capabilities to prevent potential abuse.