June 30, 2026
OverTheWire Bandit Walkthrough — Level 26 → 27 | 30-Day Cybersecurity Learning Journey (Day 26)
Breaking out of a restricted shell and using a SUID binary to read a password that was never meant to be accessible from a low-privilege…

By William | Cybersecurity & SOC Analyst
7 min read
Breaking out of a restricted shell and using a SUID binary to read a password that was never meant to be accessible from a low-privilege account.
Introduction
Day 26. Bandit Level 26 to Level 27. Two ideas that appeared separately across this series now collide in a single level. The restricted shell from Day 25 and the setuid binary first encountered back in Day 19. Getting from bandit26 to bandit27 is not about one clever command. It is about chaining a shell escape into a privilege boundary that someone left slightly open.
The core challenge is privilege escalation through a SUID helper program. The bandit26 account runs an unusual login shell rather than bash, so the first job is breaking out into something usable. Once inside a real shell, a small binary named bandit27-do becomes the key to the next level. It is a direct continuation of the setuid concept and seeing it again after building up to it over several levels is what makes this one satisfying.
By the end of this article you will understand why a file owned by another user with the SUID bit set is one of the first things worth flagging during host triage, and you will see exactly how the shell escape and the privilege boundary connect into a working solution.
Level Objective
Good job getting a shell. Now hurry and grab the password for bandit27. The official page assumes the restricted shell escape has already been completed and that the current task is finding and using what is available in the home directory to reach the next account. The commands suggested include ls and anything relevant to SUID binary usage.
Approach
I connected to bandit26 using the SSH key recovered in the previous level. Before connecting I used stty rows 5 to shrink the terminal to five lines tall. This forces the pager that bandit26's custom shell runs into interactive mode rather than allowing it to print and exit immediately:
stty rows 5
ssh -i ~/key26 bandit26@bandit.labs.overthewire.org -p 2220stty rows 5
ssh -i ~/key26 bandit26@bandit.labs.overthewire.org -p 2220The banner loaded and the pager paused, waiting for input. I pressed v to launch vim from inside the pager. Inside vim I set the shell to bash and spawned a real prompt:
:set shell=/bin/bash
:shell
OR
:!bin/bash:set shell=/bin/bash
:shell
OR
:!bin/bash
Once I had a real bash shell as bandit26 I ran ls -la to inspect the home directory:
ls -lals -laTwo files stood out immediately. A file called bandit27-do with permissions -rwsr-x---, owned by bandit27 with group bandit26. That lowercase s in the owner execute position is the SUID bit. It means the binary executes with bandit27's privileges regardless of who launches it. I also confirmed my own password file at /etc/bandit_pass/bandit26 was readable, which verified I was in the correct context.
With that confirmed I used bandit27-do to run cat against the bandit27 password file. Because the binary carries the SUID bit and is owned by bandit27, the cat command executes with bandit27's effective permissions and reads a file my bandit26 account could never open directly:
./bandit27-do cat /etc/bandit_pass/bandit27./bandit27-do cat /etc/bandit_pass/bandit27The password for Level 27 printed to the terminal immediately.
Commands Used
# Shrink terminal height so the pager stays open instead of exiting
stty rows 5
# Connect to bandit26 using the recovered private key
ssh -i ~/key26 bandit26@bandit.labs.overthewire.org -p 2220
# Press v inside the paused pager to open vim
v
# Inside vim: set the shell to bash instead of the restricted shell
:set shell=/bin/bash
# Inside vim: spawn a real bash shell
:shell
# List the home directory with full permissions and ownership
ls -la
# Use the SUID binary to read bandit27's password file as bandit27
./bandit27-do cat /etc/bandit_pass/bandit27# Shrink terminal height so the pager stays open instead of exiting
stty rows 5
# Connect to bandit26 using the recovered private key
ssh -i ~/key26 bandit26@bandit.labs.overthewire.org -p 2220
# Press v inside the paused pager to open vim
v
# Inside vim: set the shell to bash instead of the restricted shell
:set shell=/bin/bash
# Inside vim: spawn a real bash shell
:shell
# List the home directory with full permissions and ownership
ls -la
# Use the SUID binary to read bandit27's password file as bandit27
./bandit27-do cat /etc/bandit_pass/bandit27Command Breakdown
stty rows 5 Sets the terminal height to five rows before connecting. The bandit26 login shell pipes its output through a pager and a short terminal forces that pager to pause rather than exiting immediately. This pause is the window needed for the escape.
ssh -i ~/key26 bandit26@bandit.labs.overthewire.org -p 2220 Connects to bandit26 using the private key recovered in the previous level. The -i flag specifies the identity file. No password is used.
v inside the pager A built-in keybinding in more that launches the editor configured in the environment, typically vim. This is standard pager functionality being used as an escape route rather than a reading aid.
:set shell=/bin/bash A vim command that overrides which shell vim uses when spawning subprocesses. Without this step, vim would inherit the same restricted shell from the bandit26 session.
:shell A vim command that spawns an interactive shell subprocess using the path defined by :set shell. After the previous step this opens a full bash session running as bandit26.
./bandit27-do cat /etc/bandit_pass/bandit27 Runs the SUID binary and passes cat /etc/bandit_pass/bandit27 as the command to execute. Because bandit27-do is owned by bandit27 and carries the SUID bit, it executes with bandit27's effective user ID and can read the password file that bandit26 alone cannot access.
-rwsr-x--- The permission string on bandit27-do. The lowercase s in the owner execute position is the SUID bit. It signals that any execution of this file runs with the file owner's privileges rather than the calling user's privileges.
Lesson Learned
The main technical takeaway is that a shell escape and a SUID binary are two separate weaknesses that become significantly more dangerous when chained. The restricted shell tries to contain the session. The SUID helper quietly offers elevated execution to anyone who can reach it. Together they produce a working privilege escalation path that neither weakness alone would provide.
What made this level satisfying was recognising the SUID bit immediately because of Day 19. That recognition is the entire skill. The first time -rwsr-x--- appears in a listing it looks like noise. The second time it looks like an opportunity. Building that visual instinct is what repetition through this series is designed to do.
Going forward the habit is locked: run ls -la immediately after getting any shell, scan the permission column for s in execute positions and check the owner before anything else. That single habit answers most privilege escalation questions before any further enumeration is needed.
ls -la— expose full permissions and hidden files in any directory immediately after shell accessfind / -perm -4000 -type f 2>/dev/null— enumerate all SUID binaries across the entire systemid— verify the real and effective user IDs to confirm which context a command runs instat filename— inspect a file's exact permission mode and ownership in detailfile filename— confirm whether a SUID candidate is a compiled binary or a script./binary command— execute a command through a SUID binary to inherit its owner's privileges
🔴 SOC Analyst Insight
In a real environment an attacker who lands a low-privilege shell does almost exactly what this level demonstrates. They look for a fast path upward and SUID binaries are one of the most consistently reliable local privilege escalation paths on Linux. A misconfigured or custom SUID helper like bandit27-do, sitting in a user home directory rather than a standard system location, is precisely the kind of artefact that turns a contained foothold into a broader compromise.
During host triage after a suspected breach one of the first sweeps worth running is a full enumeration of every SUID file on the system, compared against a known-good baseline. Anything unexpected gets investigated immediately regardless of what it is named.
# Enumerate all SUID binaries on the system and list each one with its owner
find / -perm -4000 -type f 2>/dev/null -exec ls -la {} \;# Enumerate all SUID binaries on the system and list each one with its owner
find / -perm -4000 -type f 2>/dev/null -exec ls -la {} \;The command above walks the entire file system, finds files with the SUID bit set and lists each one with full ownership and permission detail. Legitimate SUID binaries live in predictable locations like /usr/bin and /usr/sbin and there are a finite number of them. A custom binary owned by a service account sitting in a user home directory does not belong in that list and should trigger an immediate escalation during incident response.
Understanding why bandit27-do works, owner privileges carried through the SUID bit to every execution, is what makes it possible to tell the difference between a normal system file and an attacker-placed escalation tool at a glance. During live response that distinction needs to happen in seconds, not minutes.
Key Takeaway
A SUID binary runs with its owner's privileges regardless of who launches it, which makes it a reliable escalation path for attackers and a high-priority item for defenders to audit. Escaping a restricted shell only matters once something worth escalating with has been found, and in this level those two pieces connected directly. Learning to read the permission string at a glance and recognising s in the execute field as an immediate investigation trigger is one of the most practically valuable habits this series builds.
30-Day Cybersecurity Learning Journey — Progress
🟢 Open Day — Setup & Series Introduction | OverTheWire Bandit
✅ Day 0. — Bandit Level 0 | First Login
✅ Day 1. — Bandit Level 1 → 2 | Special Characters
✅ Day 2. — Bandit Level 2 → 3 | Spaces in Filenames
✅ Day 3. — Bandit Level 3 → 4 | Hidden Files
✅ Day 4. — Bandit Level 4 → 5 | File Types
✅ Day 5. — Bandit Level 5 → 6 | find with Properties
✅ Day 6. — Bandit Level 6 → 7 | find across Filesystem
✅ Day 7. — Bandit Level 7 → 8 | grep
✅ Day 8. — Bandit Level 8 → 9 | sort and uniq
✅ Day 9. — Bandit Level 9 → 10 | strings and grep
✅ Day 10. — Bandit Level 10 → 11 | base64
✅ Day 11. — Bandit Level 11 → 12 | ROT13 and tr
✅ Day 12. — Bandit Level 12 → 13 | hexdump and compression
✅ Day 13. — Bandit Level 13 → 14 | SSH keys
✅ Day 14. — Bandit Level 14 → 15 | Netcat
✅ Day 15. — Bandit Level 15 → 16 | SSL and OpenSSL
✅ Day 16. — Bandit Level 16 → 17 | Port Scanning
✅ Day 17. — Bandit Level 17 → 18 | diff
✅ Day 18. — Bandit Level 18 → 19 | SSH command execution
✅ Day 19. — Bandit Level 19 → 20 | Setuid binaries
✅ Day 20. — Bandit Level 20 → 21 | Network services
✅ Day 21. — Bandit Level 21 → 22 | Cron jobs
✅ Day 22. — Bandit Level 22 → 23 | Cron and bash scripting
✅ Day 23. — Bandit Level 23 → 24 | Writing cron scripts
✅ Day 24. — Bandit Level 24 → 25 | Brute forcing and loops
✅ Day 25. — Bandit Level 25 → 26 | Restricted shells
✅ Day 26. — Bandit Level 26 → 27 | SUID privilege escalation ← today
⬜ Day 27. — Bandit Level 27 → 28 | coming next🟢 Open Day — Setup & Series Introduction | OverTheWire Bandit
✅ Day 0. — Bandit Level 0 | First Login
✅ Day 1. — Bandit Level 1 → 2 | Special Characters
✅ Day 2. — Bandit Level 2 → 3 | Spaces in Filenames
✅ Day 3. — Bandit Level 3 → 4 | Hidden Files
✅ Day 4. — Bandit Level 4 → 5 | File Types
✅ Day 5. — Bandit Level 5 → 6 | find with Properties
✅ Day 6. — Bandit Level 6 → 7 | find across Filesystem
✅ Day 7. — Bandit Level 7 → 8 | grep
✅ Day 8. — Bandit Level 8 → 9 | sort and uniq
✅ Day 9. — Bandit Level 9 → 10 | strings and grep
✅ Day 10. — Bandit Level 10 → 11 | base64
✅ Day 11. — Bandit Level 11 → 12 | ROT13 and tr
✅ Day 12. — Bandit Level 12 → 13 | hexdump and compression
✅ Day 13. — Bandit Level 13 → 14 | SSH keys
✅ Day 14. — Bandit Level 14 → 15 | Netcat
✅ Day 15. — Bandit Level 15 → 16 | SSL and OpenSSL
✅ Day 16. — Bandit Level 16 → 17 | Port Scanning
✅ Day 17. — Bandit Level 17 → 18 | diff
✅ Day 18. — Bandit Level 18 → 19 | SSH command execution
✅ Day 19. — Bandit Level 19 → 20 | Setuid binaries
✅ Day 20. — Bandit Level 20 → 21 | Network services
✅ Day 21. — Bandit Level 21 → 22 | Cron jobs
✅ Day 22. — Bandit Level 22 → 23 | Cron and bash scripting
✅ Day 23. — Bandit Level 23 → 24 | Writing cron scripts
✅ Day 24. — Bandit Level 24 → 25 | Brute forcing and loops
✅ Day 25. — Bandit Level 25 → 26 | Restricted shells
✅ Day 26. — Bandit Level 26 → 27 | SUID privilege escalation ← today
⬜ Day 27. — Bandit Level 27 → 28 | coming nextFollow along with the series as I document each level, command and lesson learned.
The most dangerous file on a host is rarely the one with the scary name. It is the quiet one with an s where you were not looking.