OverTheWire: Bandit

Bandit is a wargame aimed at beginners. These are my notes as I work through it. What I actually learned and what I got wrong. Mostly written for myself but maybe useful to someone else.

Level 0 → 1
ssh -p 2220 bandit0@bandit.labs.overthewire.org

Straightforward intro level. The password is given on the site, log in and read the readme file. Getting comfortable with SSH flags.

Level 1 → 2
cat ./-

The - character has three different interpretations in Linux. Here it is used as a filename, but you can't just run cat - because cat treats - as a special argument meaning stdin — so it just hangs waiting for input. To read a file literally named -, prefix it with a path: cat ./-.

Level 2 → 3
cat "./spaces in this filename"

First I ran ls -a to find the hidden file. Filenames with spaces need to be wrapped in quotes or have each space escaped with \ , otherwise the shell splits the name into multiple arguments. The file also starts with dashes so the ./ prefix is needed inside the quotes to stop it being read as a command flag.

Level 3 → 4
cat "...Hiding-From-You"

Hidden file with two extra dots before the actual dot that hides the file. Remember that hidden files in Linux start with a single . — this file uses multiple dots as part of its actual name. ls -a reveals it.

Level 4 → 5
find . -type f -exec file {} \; 2>/dev/null | grep ASCII

Didn't know this one going in. Breaking it down: . searches the current directory, -type f looks for files, -exec file {} \; runs the file command on each result to determine its type, {} is a placeholder for the found filename, \; ends the exec expression, 2>/dev/null hides permission errors, and | grep ASCII filters down to the human-readable file.

Level 5 → 6
find . -type f -size 1033c ! -executable

What I got wrong first: I used -type d instead of -type f because I was thinking directory, but we are still looking for a file inside it. The -size flag accepts c for bytes. The ! operator negates a condition ! -executable finds files that are not executable. You can also use -not but that is not POSIX compliant.

Level 6 → 7
find / -type f -group bandit6 -user bandit7 -size 33c -print 2>/dev/null
find / -type f -group bandit6 -size 33c -print 2>/dev/null | grep bandit7

This one was interesting. Use / instead of . to search the whole system rather than just the current directory. find has both -user and -group flags but I couldn't get the user filter working correctly at first learned that you can also pipe to grep to filter by username in the output path. Both commands above work. 2>/dev/null keeps the output clean by hiding all the permission denied errors.

Level 7 → 8
grep "millionth" data.txt

This one is a bit interesting because there are multiple ways to get here. I could go into vim and use /millionth, or run strings data.txt | grep "millionth", but the simplest is just grep directly on the file. strings is more useful when you don't know what kind of characters the file contains it extracts human-readable text from binaries or mixed-format files.

Level 8 → 9
sort data.txt | uniq -u

You must sort the file before piping to uniq because uniq only detects adjacent duplicate lines. The -u flag reports only lines that appear exactly once. You can also use -c to see the count of each line which helps visually spot the unique one.

Level 9 → 10
strings data.txt | grep ==

The password is stored alongside several = characters. strings extracts printable text from binary data, then grep == filters down to the relevant line. You can also use grep -E '=+' since we know there is at least one = but don't know exactly how many.

Level 10 → 11
base64 -d data.txt

The -d flag decodes a Base64-encoded file back to its original content. Straightforward once you recognise the encoding.