OverTheWire: Bandit — Levels 0-6¶
Reference: https://overthewire.org/wargames/bandit/
What Is Bandit¶
Bandit is a wargame designed to teach Linux fundamentals for beginners. Each level gives you a password to log in, then you have to find the password for the next level. The challenges progressively introduce file system navigation, permissions, special filenames, searching, and more.
Level 0 — SSH Basics¶
Goal: Log into the game server via SSH.
Full breakdown:
| Part | What it does |
|---|---|
ssh |
Secure Shell — encrypted remote login |
-p 2220 |
Connect on port 2220 instead of the default SSH port (22). Bandit uses a non-standard port. |
bandit0 |
Username to log in as |
@bandit.labs.overthewire.org |
The host to connect to |
Once in, the password for the next level is somewhere on the filesystem. The challenge tells you where to look.
Level 0 → 1¶
Password: ZjLjTmM6FvvyRnrb2rfNWOZOTa6ip5If
Concept: Reading a file. The password is in ~/readme.
cat = concatenate and print. Reads a file and dumps its contents to stdout.
Level 1 → 2¶
Password: 263JGJPfgU6LtdEvgfWU1XP5yac29mFx
Concept: Files with special names — a file named -.
The file is literally called -. You can't just cat - because - means "read from stdin" to most Unix tools — it's a special convention, not a filename.
The fix — prefix with path:
./- = "the file named - in the current directory (.)." By giving it a path prefix, the shell treats it as a filename, not the stdin flag.
Alternative:
The pattern: any time you have a file that starts with - or has a name that collides with a flag, prefix it with ./:
Level 2 → 3¶
Password: MNk8KNH3Usiio41PRUEoDFPqfxLPlSmx
Concept: Files with spaces in the name.
The file is called spaces in this filename. Shell splits arguments on spaces, so cat spaces in this filename tries to open four separate files.
Fix — quote it:
Or escape each space:
Or use tab completion — type cat sp then press Tab. The shell auto-completes and escapes it for you.
The pattern: whenever a file has spaces, either quote it or use tab completion. In scripts, always quote variables: "$filename" not $filename.
Level 3 → 4¶
Password: 2WmrDFRmJIq3IPxneAaMGhap0pFhF3NJ
Concept: Hidden files — files starting with . are hidden from ls by default.
The password file is hidden inside the inhere directory.
cd inhere
ls -a # show ALL files including hidden ones
cat .hidden # or whatever the hidden file is named
ls flags:
| Flag | What it does |
|---|---|
-a |
Show all files including hidden (starting with .) |
-l |
Long format — permissions, owner, size, date |
-la or -al |
Both — long format including hidden files |
Why hidden files exist: on Unix, dotfiles (.bashrc, .ssh, .gitignore) are config files that don't need to clutter directory listings. It's a convention, not a permission restriction — the files are readable, just not shown by default.
Level 4 → 5¶
Password: 4oQYVPkxZOOEOO5pTW81FB8j8lxXGUQw
Concept: Finding the human-readable file among many binary files.
The inhere directory has files named -file00 through -file09. Only one contains ASCII text (the password). The rest are binary.
file = determines the type of a file by examining its contents (not its name).
Output:
./-file00: data
./-file01: data
./-file02: data
...
./-file07: ASCII text
./-file08: data
./-file09: data
Look for ASCII text — that's the human-readable one.
Then:
./* = glob pattern. Expands to all files in the current directory, each prefixed with ./ (so the - prefix problem from Level 1 is handled automatically).
Why file works this way: files don't have to have extensions on Linux. file reads the first few bytes (the "magic bytes") and uses a database to determine the type — regardless of what the file is named.
Level 5 → 6¶
Password: HWasnPhtq9AVKe0dmk45nxy20cvUa6EG
Concept: Using find with multiple conditions to locate a specific file.
Properties: - Human-readable - 1033 bytes in size - Not executable
Full breakdown:
| Part | What it does |
|---|---|
find . |
Search starting from the current directory (.) recursively |
-type f |
Only files (not directories, symlinks, etc.) |
-size 1033c |
Exactly 1033 bytes. c = bytes (chars). Other units: k=kilobytes, M=megabytes, G=gigabytes |
! -executable |
NOT executable. ! negates any condition |
To also verify human-readable:
-exec file {} \; = run the file command on each result. {} is replaced by the filename. \; ends the exec expression.
Level 6 → 7¶
Password: morbNTDkSW6jIlUc0ymOdMaLnOlFVAaj
Concept: Searching the entire system with user/group/size filters.
Properties:
- Owned by user bandit7
- Owned by group bandit6
- 33 bytes in size
Full breakdown:
| Part | What it does |
|---|---|
find / |
Search from the filesystem root — the entire system |
-user bandit7 |
Owned by user bandit7 |
-group bandit6 |
Owned by group bandit6 |
-size 33c |
Exactly 33 bytes |
2>/dev/null |
Redirect stderr to /dev/null — suppress "Permission denied" errors from directories you can't read |
Without 2>/dev/null you'd get flooded with permission denied messages from /proc, /sys, /root etc. Redirecting stderr (2>) to the null device (/dev/null) discards those errors silently while still showing stdout (the actual results).
Then read the file:
find — Full Reference¶
find is one of the most powerful and commonly used tools in CTFs and Linux admin. The pattern:
Conditions¶
# Type
-type f # file
-type d # directory
-type l # symlink
# Name
-name "*.txt" # exact match (case sensitive)
-iname "*.txt" # case insensitive
-name "-file*" # name starts with -file
# Size
-size 33c # exactly 33 bytes
-size +1M # more than 1 megabyte
-size -100k # less than 100 kilobytes
-size +1k -size -5k # between 1k and 5k
# Ownership
-user bandit7 # owned by user
-group bandit6 # owned by group
-nouser # no valid user (orphaned files)
# Permissions
-perm 644 # exactly these permissions
-perm -4000 # SUID bit set (4 = SUID in octal)
-perm -2000 # SGID bit set
-perm -u+w # writable by owner
-executable # executable by current user
! -executable # NOT executable
# Time
-mtime -7 # modified in last 7 days
-mtime +30 # modified more than 30 days ago
-newer reference.txt # newer than reference.txt
# Depth
-maxdepth 2 # don't go deeper than 2 levels
-mindepth 1 # skip the starting directory itself
Actions¶
-exec cmd {} \; # run cmd on each result (sequential)
-exec cmd {} + # run cmd on all results at once (faster)
-print # print path (default if no action given)
-delete # delete matching files (careful!)
CTF / Priv Esc Patterns¶
find / -perm -4000 2>/dev/null # SUID files — run as owner regardless of caller
find / -perm -2000 2>/dev/null # SGID files
find / -writable -type f 2>/dev/null # world-writable files
find / -writable -type d 2>/dev/null # world-writable directories
find . -type f -name "*.conf" # config files
find . -type f -name "*.log" # log files
find / -user root -perm -4000 2>/dev/null # SUID files owned by root
2>/dev/null is almost always appended when searching from / — without it, "Permission denied" messages from restricted dirs bury the actual results.
SSH Quick Reference¶
ssh user@host # default port 22
ssh -p 2220 user@host # custom port
ssh -i ~/.ssh/keyfile user@host # private key auth
ssh -l user host # alternative user syntax
# Copy files
scp -P 2220 bandit0@host:/path/file . # download (note uppercase -P for scp)
scp -P 2220 ./file bandit0@host:/path/ # upload
Note: ssh uses lowercase -p for port. scp uses uppercase -P. Classic trip-up.
Quick Command Reference¶
cat filename # print file contents
cat ./- or cat < - # file literally named -
cat "file with spaces" # file with spaces in name
ls -a # show hidden files
ls -la # long format + hidden
file ./* # show type of all files in current dir
file ./filename # show type of specific file
find . -type f -size 1033c ! -executable # by size + not executable
find / -user X -group Y -size 33c 2>/dev/null # by owner + size
find / -perm -4000 2>/dev/null # SUID files
find . -type f -exec file {} \; | grep ASCII # find human-readable files