Linux capabilities break the all-or-nothing power of root into smaller units (around 40 of them) that can be assigned to an individual executable, so a program can do one privileged thing without being fully SUID-root. The risk is that some capabilities are as good as root: cap_setuid lets a program change to UID 0, cap_dac_read_search reads any file, cap_sys_admin is near-omnipotent. A binary carrying one of these, especially an interpreter, is a straightforward escalation.
What capabilities are
Traditionally a process was either root (all powers) or not. Capabilities divide root’s authority into discrete units that can be attached to a file, so a program gets exactly the privilege it needs.
That is good for least privilege, a ping binary can hold only the capability to open raw sockets instead of being SUID-root. The danger is granting a powerful capability to a program that can run arbitrary code.
The abuse and payload
The attacker lists capabilities and abuses dangerous ones:
- Enumerate:
getcap -r / 2>/dev/null - A Python binary with cap_setuid:
./python -c 'import os; os.setuid(0); os.system("/bin/sh")' - A binary with cap_dac_read_search can read protected files like
/etc/shadoweven without root. - Perl, Ruby, and other interpreters with cap_setuid escalate the same way.
Check GTFOBins for the capability-specific one-liner. Documented techniques shown for defenders.
How to defend
- Enumerate capabilities with
getcap -r /and remove unneeded ones:setcap -r <file>. - Never grant powerful capabilities to interpreters (python, perl, ruby) or shells.
- Prefer the minimum capability that achieves the task rather than a broad one.
- Patch and review custom binaries that carry capabilities.
- Monitor for new capability assignments.
References
- [1]Linux man-pages: capabilities(7)(man7.org)
- [2]MITRE ATT&CK: Privilege Escalation (TA0004)(MITRE)
- [3]NIST SP 800-115 Technical Guide to Security Testing(NIST)