# Linux Capabilities and PrivEsc

> How Linux capabilities work in practice and how a misconfigured capability (CAP_SYS_ADMIN, CAP_DAC_READ_SEARCH, etc.) can lead to local privilege escalation, with hands-on examples.

Author: Elnur Badalov
Published: 2024-06-20
Updated: 2026-01-02
Tags: linux, cybersec
Source: https://elnurbda.com/posts/05-linux-capabilities-privesc/
License: CC BY 4.0, please cite the source URL.

---

# Intro

This article will show you how Linux Capabilities work and how to abuse them if there is a misconfiguration.

# Linux Capabilities

Instead of granting full access, you can use **Capabilities** to assign partial permissions. Integrated directly into the kernel starting from version 2.2, Capabilities divide privileges into separate components. For example, if a root user could perform tasks A, B, and C, Capabilities allow you to assign specific permissions to a process. This means you can grant a process only permission A, or a combination such as permissions A and C, without giving it full root access.

## Capabilities list

There a lot of different capabilities that you can check in Man Pages (source provided). I will include some examples:

- **CAP_AUDIT_WRITE** - allow writing kernel logs
- **CAP_CHOWN** - Make arbitrary changes to file UIDs and GIDs (like `chown` command)
- **CAP_KILL** - allows killing any processes
- **CAP_SETUID** - Make arbitrary manipulations of process UIDs
- **CAP_NET_ADMIN** - perform various network-related operations.
- **CAP_SETPCAP** - if a thread has this capability it can grant some of the capabilities it has to called thread.

and many others

## Thread capability sets

Capabilities have one or more of following sets:

- **Permitted**: This is the <u>maximum</u> set of capabilities a thread can use, and once a capability is removed, it can only be regained by running a privileged program.
- **Inheritable**: This set includes capabilities that stay with a program even after it runs another program, allowing these capabilities to be added to the permitted set if the new program allows it.
- **Effective**: These are the capabilities that are actively used by the kernel to check what the thread is allowed to do.
- **Bounding**: This set limits the capabilities a thread can gain when it runs another program.
- **Ambient**: These capabilities stay with a non-privileged program when it runs another program, but they must also be in the permitted and inheritable sets.

## File capabilities

An Executable file can have capabilities, and when it is executed, the process will have associated capabilities. Capabilities to the file is set via `setcap`. Not all sets can be assigned to the file, only the following can:

- **Permitted**
- **Inheritable**
- **Effective**

When only <u>Permitted</u> is set the process can potentially use the capability, but it is not active by default. It will be activated after <u>Effective</u> is set too.

## setcap

`setcap` - set file capabilities.

### Syntax

Let's examine commands

```bash
# Granting a specific capability to a file
sudo setcap <cap_name>=+<set> /path/to/executable
# Removing a specific capability from a file
sudo setcap <cap_name>=-<set> /path/to/executable
# Setting multiple capabilities
sudo setcap <cap_name_1>,<cap_name_2>=+<set> /path/to/executable
# Viewing the capabilities of a file
getcap /path/to/executable
# Clearing all capabilities from a file
sudo setcap -r /path/to/executable

# <cap_name>
# Capabilities that are defined in Man Page
# <set>
# Legal flags are: e, i and p for effective, inheritable and permitted, respectively
# You can use one flag or mupltiple. Example: <cap_name>=+e, <cap_name>=+ep
```

### Example

Let's say you want to run python server on port 80. Normally, you will receive following error:

![lincap01](/assets/05-linux-capabilities-privesc/lincap01.png)

To run on port below 1024 you will need to run it with `sudo`. However, you do not to give full access to the process. You can assign to it following capability:

- **CAP_NET_BIND_SERVICE** - Bind a socket to Internet domain privileged ports (port numbers less than 1024).

1. For the experiment, copy executable to some location.
2. Set the Capability
3. Test it

![lincap02](/assets/05-linux-capabilities-privesc/lincap02.png)

# PrivEsc with Capabilities

Sometimes Excutables are misconfigured and can have excessive capabilities, and these can be abused to get Privilege Escalation. For more Linux privilege escalation techniques, check out my [Pentester's Notes](/posts/07-pentester-notes/).

## Node with CAP_CHOWN

General technique is to **think logically**. For example, if some binary like `python`/`perl`/`node` has capability to change owner of the file: `CAP_CHOWN`. You can find a way to execute a command using the programming language to change ownership of sensitive file(for example `/etc/shadow`).

Lets setup the environment:

![lincap03](/assets/05-linux-capabilities-privesc/lincap03.png)

To abuse it, run the `node` command, it will prompt interactive command line. Next, use following JavaScript command, which can be easily googled (check sources):

```js
fs.chown(path, <uid>, <gid>, console.log);
// for root it would be 0 0
// and in our case if we want to read shadow file we can supply our user's id
fs.chown('/etc/shadow', 1001, 1001, console.log);
```

![lincap04](/assets/05-linux-capabilities-privesc/lincap04.png)

And Voila! You found root's password hash. Then crack it and escalate the privileges.

## VIM with CAP_SETUID

Some cases can be complicated, and we cannot know everything to find logic ways to abuse capabilities. So, just search in the internet, a good source would be **HackTrick** and **GTFOBins**.

Prepare the environment:

![lincap05](/assets/05-linux-capabilities-privesc/lincap05.png)

In those examples, we know where vulnerable files are located. However, you may think **how to find** them in unfamiliar environments. Following command can help:

```bash
getcap -r / 2>/dev/null
```

![lincap06](/assets/05-linux-capabilities-privesc/lincap06.png)

To abuse `vim`, we may check it in **GTFOBins** and find the following:

![lincap07](/assets/05-linux-capabilities-privesc/lincap07.png)

And running the command gives the shell

```bash
./vim -c ':py3 import os; os.setuid(0); os.execl("/bin/sh", "sh", "-c", "reset; exec sh")'
```

![lincap08](/assets/05-linux-capabilities-privesc/lincap08.png)

# Conclusion

I hope it helped to understand how Linux Capabilities work, and methods to abuse them. I covered only the general approach to abuse misconfigured Capabilities:

- Think Logicallly
- Search in the Internet

I believe it is a better way to learn PrivEsc instead of showing examples with 10 different Capabilities.

# References

- Man Pages:
  - Capabilities: <https://www.man7.org/linux/man-pages/man7/capabilities.7.html>
  - setcap: <https://www.man7.org/linux/man-pages/man8/setcap.8.html> - <https://www.man7.org/linux/man-pages/man3/cap_from_text.3.html>
- Priv Esc:
  - GTFOBins: <https://gtfobins.github.io/>
  - HackTricks: <https://book.hacktricks.xyz/linux-hardening/privilege-escalation/linux-capabilities>
  - JS Change Owner: <https://stackoverflow.com/questions/38624780/change-file-owner-in-node-js>