Linux Privilege Escalation: User ID Manipulation
This skill helps you understand and analyze Linux privilege escalation vectors through user ID manipulation. It covers the core concepts of ruid, euid, suid, and how they interact with system calls and program execution.
Core Concepts
User Identification Variables
ruid(Real User ID): The user who initiated the process. This is the original user identity.euid(Effective User ID): The identity the system uses to determine process privileges. Normally equals ruid, but can differ with SetUID binaries.suid(Saved User ID): Preserves elevated privileges so a process can temporarily drop privileges and later restore them.
Critical Rule: A non-root process can only modify its euid to match its current ruid, euid, or suid.
Understanding set*uid Functions
| Function | Behavior | Privilege Requirements |
|---|---|---|
setuid(uid) |
Sets euid to uid. For privileged processes, also sets ruid and suid. | Root or CAP_SETUID for arbitrary values |
setreuid(ruid, euid) |
Sets both ruid and euid. | Root or CAP_SETUID for arbitrary values |
setresuid(ruid, euid, suid) |
Sets all three IDs. | Root or CAP_SETUID for arbitrary values |
Key Insight: setuid primarily modifies euid, not ruid. For privileged processes, it aligns all three IDs to the specified value.
Program Execution Mechanisms
execve System Call
- Replaces the current process with a new program
- Preserves ruid, euid, and supplementary group IDs
- Updates suid from euid post-execution
- If the new program has SetUID bit set, euid may change
system Function
- Creates a child process via
fork - Executes command via
/bin/sh -c <command> - Behaves like
execvebut in a child process context
Bash and Sh Behavior with SUID
bashwithout-p: Sets euid to ruid if they differ (drops privileges)bash -p: Preserves the initial euid (maintains privileges)sh: No-pequivalent; behavior varies by implementation
Practical Analysis Framework
Step 1: Identify the Execution Context
# Check current user IDs
id
# Output: uid=1000(user) gid=1000(user) euid=1000(user)
# Check SUID binaries
find / -perm -4000 -type f 2>/dev/null
# Check capabilities
getcap -r / 2>/dev/null
Step 2: Analyze the Binary
When examining a SUID binary:
- Check ownership:
ls -la /path/to/binary - Check permissions:
stat /path/to/binary - Determine execution method: Does it use
system(),execve(), or direct calls? - Check for privilege drops: Look for
setuid(),setreuid(),setresuid()calls
Step 3: Understand the Privilege Flow
Use this decision tree:
Process starts with SUID bit set
↓
euid = file owner (often root)
↓
Does the binary call setuid/setreuid/setresuid?
├─ Yes → What values are set?
│ ├─ setuid(1000) → euid becomes 1000, ruid/suid may follow
│ └─ setreuid(1000, 1000) → both ruid and euid become 1000
│
└─ No → euid remains elevated
↓
Does it call system() or execve()?
├─ system() → spawns /bin/sh -c <cmd>
│ └─ If sh→bash symlink: bash without -p drops euid to ruid
│
└─ execve() → preserves euid unless target has SUID
Common Exploitation Patterns
Pattern 1: setuid + system + bash
Vulnerability: When setuid is called but system() spawns bash without -p, privileges may be dropped.
Example:
setuid(1000); // Sets euid to 1000
system("id"); // Spawns bash, which drops euid to ruid
Result: If ruid was 99 (nobody), final euid becomes 99, not 1000.
Pattern 2: setreuid + system
Vulnerability: setreuid sets both ruid and euid, so bash preserves them.
Example:
setreuid(1000, 1000); // Sets both ruid and euid to 1000
system("id"); // Bash sees ruid==euid, preserves both
Result: Process runs as uid=1000.
Pattern 3: setuid + execve + bash -p
Vulnerability: Using execve with bash -p preserves the elevated euid.
Example:
setuid(1000);
execve("/bin/bash", "/bin/bash -p", NULL);
Result: Bash preserves euid=1000.
Testing and Verification
Quick Test Script
Use the check_user_ids.sh script to verify current user ID state:
./scripts/check_user_ids.sh
Analyzing SUID Binaries
Use the analyze_suid.sh script to find and analyze SUID binaries:
./scripts/analyze_suid.sh
References
- setuid man page
- setresuid man page
- execve man page
- system man page
- bash man page
- 0xdf's setuid rabbit hole
When to Use This Skill
Use this skill when:
- Analyzing SUID binaries for privilege escalation
- Understanding why a process has unexpected privileges
- Debugging setuid/setreuid/setresuid behavior
- Writing or auditing code that manipulates user IDs
- Investigating Linux security incidents involving privilege boundaries
- Preparing for security certifications or CTF challenges