HomeThe Stash

Lab 05 — Bandit 10 to 15: encodings and your first SSH key

LabSeptember 14, 2026

BeginnerTime 30–45 minTarget OverTheWire BanditLevels 10 → 15Needs Lab 03

0 / 5 steps

The goal

Starting from your Bandit level 10 login, work through five short challenges to reach level 15. Each one hands you the password for the next level once you solve it — you are not told any of them here.

Where this runs. Everything below happens on OverTheWire's Bandit server, which they built and maintain specifically for this. You log in with credentials they issue level by level. This lab teaches you the commands; it publishes none of their passwords and none of their challenge text — that is their content, and their rules ask contributors not to reproduce it. If you land somewhere unfamiliar, OverTheWire's own Bandit page is the source of truth.

What changes at level 10. Levels 10 through 15 move you from reading files by eye to actually transforming them — decoding, peeling apart, and finally proving who you are with a key instead of a password. This is where the wargame stops being “look at the file” and starts being “process the file”, which is most of what real recon and forensics work actually is.

Before you start. You should already have a working Linux VM from Lab 00 and be sitting at a Bandit level 10 prompt — meaning you solved levels 0 through 10 yourself, or picked up from wherever Lab 02 and Lab 03 left you. If you are not there yet, work through those two first; this lab assumes the login pattern and basic navigation are already comfortable.

Steps

01Base64: the one that is not really encryption

In your level 10 home directory there is a file whose contents look like meaningless text — letters, numbers, and a trailing = or two. That trailing padding is the tell: you are looking at base64.

Base64 is not encryption. It is a way of representing binary-safe data as plain ASCII text, originally so binary files could survive being emailed through systems that only trusted plain text. Anyone can reverse it instantly — it is an encoding, not a secret.

$ base64 -d data.txt

Swap in the actual filename you find in your home directory. The -d flag means decode. What comes back out is the level 11 password.

Why this matters. Base64 shows up constantly in real work — email attachments, API tokens, data embedded in HTML or JSON, malware droppers hiding a payload in plain sight. Recognising “letters, numbers, ending in = padding” on sight, and knowing it is a ten-second decode rather than a mystery, is a genuinely useful reflex.

02ROT13: Caesar's cipher, still turning up

Log into level 11 with the password step 1 gave you. This time the file in your home directory is readable text — but it is gibberish. Look closely and the letter frequencies feel almost like English. That is the signature of a rotation cipher.

ROT13 shifts every letter 13 places through the alphabet. Because the alphabet has 26 letters, applying it twice gets you back to the original — it is its own inverse, which is exactly why it was never meant to be real security. It is used online mostly to hide spoilers or puzzle answers from a casual glance, not from anyone who tries.

$ tr 'A-Za-z' 'N-ZA-Mn-za-m' < data.txt

tr translates characters one for one — here, each letter to the one 13 places further on, wrapping around. Numbers and punctuation pass through untouched, which is why password-shaped output still looks password-shaped after decoding.

Why this matters. ROT13 itself is trivial, but the skill underneath — recognising a substitution cipher by its statistical fingerprint and reaching for tr instead of a GUI tool — generalises to the more serious classical ciphers you will meet in CTFs.

03Hex and repeated compression: peeling an onion

Level 12's file is the biggest jump in this lab: a hexdump of data that has been compressed several times over, stacked. You will not solve this with one command — you will solve it with a loop of the same two commands, repeated until it stops.

First, copy the file somewhere you can make a mess. You do not want to overwrite your only copy while experimenting, and Bandit is a shared machine, so let the system pick a directory name nobody else will collide with:

$ mkdir -p /tmp/$(whoami) && cd $(mktemp -d -p /tmp/$(whoami)) && cp ~/data.txt ./data && pwd

mktemp -d creates a directory with a random name and hands you the path, which is the right habit on any machine you share with other people — a fixed name like /tmp/mywork is one you can be pushed out of. /tmp is scratch space that clears on reboot, exactly right for throwaway work like this. The trailing pwd prints where you landed, so note it down.

Reverse the hexdump back to raw bytes:

$ xxd -r data > data2

xxd normally turns bytes into a hex dump for humans to read; -r runs it backwards, turning a hex dump back into the original bytes.

Now find out what you actually have:

$ file data2

The file command inspects the first few bytes of a file — its magic number — and tells you the real format, regardless of what the filename claims. It will report something like gzip compressed data, bzip2 compressed data, or POSIX tar archive. Whatever it says, that is your next move: gunzip, bunzip2, or tar -xf accordingly, renaming the output each time so you do not collide with the previous round.

A tool that insists on a particular extension will take one if you rename the file first — mv data3 data3.gz then gunzip data3.gz is a normal part of this loop, not a sign you took a wrong turn.

Repeat: reverse, identify, extract — running file after every single round, not just the first — until it finally reports ASCII text. That text is the level 13 password.

Then clean up after yourself. You are a guest on a machine thousands of other people are using, and that scratch directory is still holding a pile of half-decompressed files. Swap in the path pwd printed for you at the start of this step:

$ cd ~ && rm -rf /tmp/bandit12/tmp.AbC123XyZ

Leaving scratch files behind is not a crime, but tidying up is the habit you want on any shared or production box — and on a machine like this one it is simple good manners.

Why this matters. “Identify the file type, then act accordingly” is the actual job in a lot of forensics and malware-triage work — you are rarely told up front what format you are holding. This step is slower on purpose: the loop is the lesson, not a shortcut around it.

04Your first SSH key

Log into level 13. This time your home directory holds no password file at all — it holds a private SSH key. That key, not a password, is how you get into level 14.

SSH key authentication proves identity with a matched pair of keys: a private key you keep and never share, and a public key installed on the server. The server challenges your client to prove it holds the private key, without the private key ever crossing the network. It is the same mechanism that secures the vast majority of real production server access — this is your first hands-on encounter with it, not a toy version.

Fix the file permissions first. SSH refuses to use a private key that other users on the system could read, and on a shared box like this one that refusal is doing its job:

$ chmod 600 sshkey.private

Substitute the real filename. 600 means only the file's owner can read or write it — nobody else, not even others in the same group.

Then connect using the key instead of a password:

$ ssh -i sshkey.private -p 2220 bandit14@localhost

-i points SSH at the identity file to use, and -p 2220 is the non-standard port Bandit listens on — the same one you have been using to log in from your own machine, and easy to forget when the destination is the box you are already sitting on. All of Bandit's levels live on that one machine, which is why every level from here on is reachable this way.

Once you are in as level 14, that level's own password is readable at /etc/bandit_pass/bandit14 — a file each level can read only for itself. You need it for the next step, so read it now.

Why this matters. Key-based auth is how you will actually reach most servers, cloud instances and CI systems in real work — password SSH is routinely disabled outright. Getting comfortable with -i, with permissions on key files, and with reading key-based errors now saves real confusion later.

05Talking to a local port

Level 14 asks you to do something different again: a service is listening on a port on the same machine, and submitting the current level's password to it — as plain input, not as a login — hands back the next one.

$ nc localhost PORT

Replace PORT with the port number Bandit's own level 14 page gives you — that number belongs to the challenge and is not something to guess at. nc (netcat) opens a raw connection to it; once connected, paste in the level 14 password you read in step 4 and press Enter. The service reads it, checks it, and if it is right prints the level 15 password back to you.

If nothing comes back, the usual cause is a stray newline or a truncated paste rather than a wrong password — check you copied the whole string.

Why this matters. This is the shape of countless real services: a listener on a port that expects a specific input and answers. nc is the tool you reach for to probe exactly that, well beyond this wargame — testing whether a port is even open, speaking a text-based protocol by hand, or catching a reverse shell.

Lab complete

You have decoded base64, reversed a rotation cipher, peeled apart stacked compression by reading file signatures, authenticated with your first SSH key pair, and talked directly to a listening service. That is five real techniques, not five trivia answers — and the “identify the format, then act” pattern from step 3 will come back constantly.

Before you leave — prove it

Without scrolling up: one, why is base64 not a way of hiding anything? Two, in the step 3 loop, what tells you which decompression command to reach for next? Three, why does SSH refuse to use a private key that is readable by other users?

If the second answer is “whatever file just said”, you have understood the part of this lab that generalises.

What you learned

  • base64 — an encoding, not encryption, and reversible in one command
  • ROT13 and tr — character-for-character substitution from the shell
  • xxd -r — turning a hex dump back into the bytes it describes
  • file — magic numbers over file extensions, every round of the loop
  • SSH keys-i, key permissions, and why the private key never crosses the network
  • nc — speaking to a listening port directly

NextNatas 6 to 10: LFI, decoding, and command injection

Go deeper

Original walkthrough. The wargame belongs to the OverTheWire community; this page reproduces none of their level text and none of their passwords, in line with their rules for content creators. Commands were checked against their documented behaviour — but Bandit changes, so if a step here no longer matches what you see, tell me and I will fix it.