| name | linux-privilege-escalation |
| description | How to analyze and exploit Linux privilege escalation through user ID manipulation (ruid, euid, suid). Use this skill whenever the user mentions privilege escalation, SUID binaries, setuid/setreuid/setresuid functions, execve/system calls, or needs to understand how Linux user IDs work in security contexts. Make sure to use this skill for any Linux security analysis involving user identity, privilege boundaries, or binary execution mechanisms. |
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
execve but in a child process context
Bash and Sh Behavior with SUID
bash without -p: Sets euid to ruid if they differ (drops privileges)
bash -p: Preserves the initial euid (maintains privileges)
sh: No -p equivalent; behavior varies by implementation
Practical Analysis Framework
Step 1: Identify the Execution Context
id
find / -perm -4000 -type f 2>/dev/null
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);
system("id");
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);
system("id");
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
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