OverTheWire Bandit: Levels 0 to 15 Guide with Hints and Commands
Beat OverTheWire Bandit levels 0 to 15: what each level teaches, hints and the Linux commands that solve it, without spoiling the passwords.
OverTheWire Bandit is the first wargame almost everyone recommends for getting started in ethical hacking, and for good reason: it forces you to work in a real Linux terminal to find the password for each level. In this guide we go through levels 0 to 15 one by one: what each level asks, which Linux concept it teaches, a hint so you can try it yourself, and the commands that solve it. What you won't find here are the passwords: they change periodically, and copying them takes away exactly what the game is trying to teach you.
What OverTheWire Bandit is and why you should start here
OverTheWire is a community that runs several free wargames. Bandit is the most basic one: each level is a user on a Linux server (bandit0, bandit1, bandit2...) and your goal is to find the next user's password hidden somewhere on the system. There is nothing exotic to install and no graphical interface: just you, SSH and the terminal.
That makes it the best training for what comes next. Almost every CTF box and pentesting lab assumes you can list hidden files, search with find, filter with grep or decode Base64 without thinking about it. Bandit teaches you exactly that, step by step. If you are still unsure about the overall learning path, read how to learn ethical hacking from scratch first.
Before you start: connecting and working efficiently
You need an SSH client. It comes preinstalled on Linux and macOS, and on Windows 10/11 as well (from PowerShell). If you want a full practice environment, a Kali virtual machine works great: we cover it in Kali Linux for beginners.
ssh bandit0@bandit.labs.overthewire.org -p 2220
Note the -p 2220: the server does not listen on the standard port 22. The password for level 0 is given on the game's website. From there on, every password you find lets you log in as the next user: ssh bandit1@bandit.labs.overthewire.org -p 2220, and so on.
Three habits that will save you time:
- Write the passwords down in a file on your own computer, not on the server. If you log out, you can jump straight back to your last level.
- Read each level's page on the OverTheWire website. It lists the commands you will probably need, which is the best hint there is.
- Use
man.man findorman targives you the official answer. Learning to read manuals is part of the game.
Levels 0 to 5: navigating the file system
Level 0 → 1: reading a file
Goal: the password is in a file called readme in your home directory.
Concept: listing files and printing their contents. ls shows what is in a directory and cat prints a file to the screen.
ls
cat readme
Level 1 → 2: a file named "-"
Goal: the password is in a file called -.
Concept: to many programs, - is not a filename but "standard input". If you type cat -, the command just sits there waiting for you to type something.
Hint: give the command a path that cannot be mistaken for an option. ./ means "in the current directory".
cat ./-
Level 2 → 3: spaces (and dashes) in the name
Goal: the password is in a file whose name contains spaces. In the current version of the game it also starts and ends with dashes (--spaces in this filename--).
Concept: the shell splits arguments on spaces, so cat spaces in this filename tries to open four different files. You need to quote the name or escape each space with \. And if it starts with --, you also need to stop it from being parsed as an option.
Hint: type the first few letters and press Tab; autocompletion escapes the name for you.
cat ./"--spaces in this filename--"
# alternative: "--" tells cat there are no more options
cat -- "--spaces in this filename--"
Level 3 → 4: hidden files
Goal: the password is in a hidden file inside the inhere directory.
Concept: on Linux, any file whose name starts with a dot (.) is hidden and plain ls won't show it. The -a option shows everything, and -l adds permissions, owner and size.
ls -la inhere
cat inhere/<hidden_file_name>
You will type ls -la thousands of times: hidden files (configs, keys, shell histories) are among the first things you check on any machine.
Level 4 → 5: the only human-readable file
Goal: inhere contains ten files (-file00 to -file09) and only one of them holds readable text.
Concept: the file command identifies a file's type by looking at its contents, not its extension. The other files are binary data.
Hint: the names start with a dash again; you already know how to deal with that.
file ./inhere/*
cat ./inhere/-file0X # whichever one shows up as "ASCII text"
Level 5 → 6: searching by properties
Goal: the file is somewhere under inhere (there are lots of subdirectories). It is human-readable, exactly 1033 bytes in size and not executable.
Concept: find walks directories and filters by name, type, size, permissions or owner. In -size, the c suffix means bytes; without it, find counts in 512-byte blocks.
find inhere -type f -size 1033c ! -executable
Levels 6 to 11: searching, filtering and decoding
Level 6 → 7: searching the whole server
Goal: the file is "somewhere on the server", owned by user bandit7 and group bandit6, and is 33 bytes in size.
Concept: searching from the root / with owner and group filters. You will get hundreds of "Permission denied" errors; 2>/dev/null sends the error stream (file descriptor 2) into the void so you only see the results.
find / -user bandit7 -group bandit6 -size 33c 2>/dev/null
This exact technique is used in privilege escalation to locate files belonging to other users or binaries with special permissions.
Level 7 → 8: grep
Goal: the password is in data.txt, next to the word millionth.
Concept: the file is huge, so reading it with cat is impractical. grep prints only the lines that contain a pattern.
grep millionth data.txt
Level 8 → 9: the line that appears only once
Goal: in data.txt, the password is the only line that occurs exactly once.
Concept: pipes (|). uniq only detects adjacent duplicates, which is why you must sort first with sort. The -u option makes uniq print only unique lines.
sort data.txt | uniq -u
A very common mistake is running uniq -u data.txt without sorting and wondering why hundreds of lines come out.
Level 9 → 10: text inside a binary
Goal: data.txt is mostly binary; the password is one of the few human-readable strings and is preceded by several = characters.
Concept: strings extracts sequences of printable characters from any file. It is a basic tool in malware analysis and reverse engineering.
strings data.txt | grep "=="
Level 10 → 11: Base64
Goal: data.txt contains Base64-encoded data.
Concept: Base64 is not encryption; it is an encoding for carrying data as text, and anyone can reverse it. You will recognise it by its letters, digits, +, / and, often, trailing = signs.
base64 -d data.txt
Level 11 → 12: ROT13 with tr
Goal: in data.txt, every letter has been rotated by 13 positions.
Concept: ROT13 is a Caesar cipher with a shift of 13. Since the alphabet has 26 letters, applying it twice gives you back the original text. tr translates characters from one set to another: here A becomes N, B becomes O, and so on.
cat data.txt | tr 'A-Za-z' 'N-ZA-Mn-za-m'
Levels 12 to 15: compression, SSH keys and networking
Level 12 → 13: hexdump and layered compression
Goal: data.txt is a hexdump of a file that has been compressed several times.
Concept: xxd -r turns a hexdump back into binary. Then you use file to find out which format you have at each step (gzip, bzip2 or tar) and decompress it with the matching tool. It is the longest level so far, but it is just the same loop repeated.
Hint: you cannot write to your home directory. Create a temporary directory and work there.
cd "$(mktemp -d)"
cp ~/data.txt .
xxd -r data.txt > data
file data
# If it says "gzip compressed data":
mv data data.gz && gzip -d data.gz
# If it says "bzip2 compressed data":
mv data data.bz2 && bzip2 -d data.bz2
# If it says "POSIX tar archive":
tar xf data # then run file on whatever comes out
# Repeat "file" + decompress until you reach "ASCII text"
Watch the filenames: gzip -d insists on the .gz extension, which is why we rename first. With tar, the extracted file has a new name; check it with ls before carrying on.
Level 13 → 14: SSH private key authentication
Goal: this time there is no password, but an SSH private key (sshkey.private) that lets you log in as bandit14. bandit14's password lives in /etc/bandit_pass/bandit14, and only that user can read it.
Concept: SSH can authenticate with a key pair instead of a password: the server holds the public key and you prove you own the private one. SSH also refuses to use a private key that other users can read, so you have to lock down its permissions.
Copy the key to your own computer with scp (also on port 2220) and connect from there:
# from your machine, not from the server
scp -P 2220 bandit13@bandit.labs.overthewire.org:sshkey.private .
chmod 600 sshkey.private
ssh -i sshkey.private bandit14@bandit.labs.overthewire.org -p 2220
# once logged in as bandit14:
cat /etc/bandit_pass/bandit14
Note the difference: scp uses an uppercase -P for the port, while ssh uses a lowercase -p.
Level 14 → 15: talking to a port with nc
Goal: submit the current level's password to port 30000 on localhost.
Concept: a network service is just a program listening on a port. nc (netcat) opens a TCP connection and sends whatever you feed it on standard input. You will use it constantly to test services and for reverse shells.
cat /etc/bandit_pass/bandit14 | nc localhost 30000
Level 15 → 16: the same thing, but over TLS
Goal: submit the current level's password to port 30001 on localhost, which requires SSL/TLS.
Concept: netcat speaks plain text; if the service expects an encrypted connection, it fails. openssl s_client sets up the TLS session and then behaves like an encrypted netcat. It is the go-to tool for inspecting certificates and HTTPS services by hand.
cat /etc/bandit_pass/bandit15 | openssl s_client -connect localhost:30001 -quiet
Important hint: in interactive mode, s_client treats some lines starting with certain letters (such as R or Q) as its own commands rather than data. If a password starts with one of them, the connection behaves strangely. The -quiet option disables that behaviour and also hides all the certificate output.
Summary: what each level teaches you
| Level | Concept | Key command |
|---|---|---|
| 0 → 1 | Reading files | ls, cat |
| 1 → 2 | Names that look like options | cat ./- |
| 2 → 3 | Spaces in names | quotes, --, Tab |
| 3 → 4 | Hidden files | ls -la |
| 4 → 5 | File types | file |
| 5 → 6 | Search by size and permissions | find -size -executable |
| 6 → 7 | Search by owner | find / -user -group, 2>/dev/null |
| 7 → 8 | Filtering text | grep |
| 8 → 9 | Pipes and duplicates | sort | uniq -u |
| 9 → 10 | Text in binaries | strings |
| 10 → 11 | Encoding | base64 -d |
| 11 → 12 | Classical ciphers | tr (ROT13) |
| 12 → 13 | Hexdump and compression | xxd -r, gzip, bzip2, tar |
| 13 → 14 | SSH keys | scp, chmod 600, ssh -i |
| 14 → 15 | TCP connections | nc |
| 15 → 16 | TLS connections | openssl s_client |
Common beginner mistakes in Bandit
- Forgetting port 2220 and assuming the server is down.
- Copying the password with an extra space at the start or end. If it says the password is wrong, paste it into an editor and check.
- Looking up solutions before wrestling with the level. Give yourself at least 20-30 minutes and the
manpage before reading a hint. The frustration of those minutes is exactly where the learning happens. - Working in shared directories. On level 12, always use
mktemp -d; other players are on the same server.
Remember: Bandit is an environment built for practice. The search and connection techniques you learn here should only be used on your own systems or on platforms and engagements where you have explicit authorisation.
What to do after Bandit
Bandit has more levels (up to around 34) covering port scanning with nmap, cron jobs, Git and escaping restricted shells. It is worth finishing. After that, these are the logical next steps:
- Natas (also on OverTheWire): web security from your browser. Source code, cookies, injections and server-side logic.
- Leviathan: a short wargame focused on SUID binaries and figuring out what a program does without its source code.
- picoCTF: CTF challenges across every category (cryptography, forensics, web, reversing), designed for students with a gradual difficulty curve.
- TryHackMe: guided rooms with in-browser virtual machines, ideal for making the jump to pentesting full machines.
If you prefer a structured path with lessons and hands-on challenges in order, take a look at the Hackers en Acción Academy. And if you don't have a lab yet, start by installing Kali Linux in a virtual machine: you will need it as soon as you move beyond Bandit.