Back to Writeups

Bandit Walkthrough

Levels 0 - 33 Solutions

Published: April 23, 2025 Difficulty: Beginner

Bandit is a wargame on OverTheWire that focuses on learning basic Linux skills, such as navigating the file system, using SSH, and working with permissions. This comprehensive walkthrough covers all levels with detailed explanations and learning outcomes.

Levels 0-9: Fundamentals

Bandit Level 0

Objective: Log in to the server and find the password for the next level.

First, log in to the server:

ssh bandit.labs.overthewire.org -p 2220 -l bandit0

When prompted, enter the password: bandit0

Once logged in, run the following commands:

  • ls – lists files in the current directory
  • cat readme – reads the contents of the file
🚩: ZjLjTmM6FvvyRnrb2rfNWOZOTa6ip5If

Key Learnings:

SSH lets you connect to a remote device. ls lists directories, and cat reads file contents.

Bandit Level 1

Objective: Read a file with a special name that causes command interpretation issues.

After logging in, list the files using ls.

You'll see a file named -.

A quick Google search reveals that running cat - treats - as standard input (stdin), not as a file.

To read the file correctly, specify the path to it by using this command:

cat ./-
🚩: 263JGJPfgU6LtdEvgfWU1XP5yac29mFx

Key Learnings:

When a file is named -, it's interpreted as stdin by default. Prepending ./ tells the shell it's a file in the current directory.

Bandit Level 2

Objective: Read a file with spaces in the filename.

After logging in, use ls to list the files.

You'll see a file with spaces in its name: spaces in this filename.

To read it with cat, start typing cat sp and press Tab for auto-completion.

The command should look like this:

cat spaces\ in\ this\ filename
🚩: MNk8KNH3Usiio41PRUEoDFPqfxLPlSmx

Key Learnings:

When working with filenames that contain spaces, use escape characters (\) or auto-complete with Tab to avoid errors.

Bandit Level 3

Objective: Find and read a hidden file.

Use ls to find a file named inhere.

Change into that directory with cd inhere.

Run ls again and you won't see anything. Try ls -a to show all hidden files.

You'll find a file named ...Hiding-From-You.

Read it using:

cat ...Hiding-From-You
🚩: 2WmrDFRmJIq3IPxneAaMGhap0pFhF3NJ

Key Learnings:

Use -a with ls to list hidden files, and remember hidden files often start with a dot.

Bandit Level 4

Objective: Find the only human-readable file among several files.

Navigate into the folder using cd inhere.

Run file ./* to display all files and their types.

You'll see that -file07 is an ASCII text file.

Read it with:

cat ./-file07
🚩: 4oQYVPkxZOOEOO5pTW81FB8j8lxXGUQw

Key Learnings:

Use ./ to reference files that start with a dash -, so commands interpret them as filenames, not options.

Bandit Level 5

Objective: Find a file with specific properties using the find command.

Use ls inhere to explore the directory.

There are multiple files to search through.

There is a hint on the bandit6 page.

Enter the directory by using cd inhere

Use find with the following properties: human-readable, 1033 bytes in size, and not executable:

find inhere -type f -size 1033c ! -executable

The result will be inhere/maybehere07/.file2.

Read the file with:

cat inhere/maybehere07/.file2
🚩: HWasnPhtq9AVKe0dmk45nxy20cvUa6EG

Key Learnings:

Use find with specific file search criteria like size and executable status to narrow down results efficiently.

Bandit Level 6

Objective: Find a file anywhere on the server with specific owner, group, and size properties.

Follow the instructions on the bandit7 page.

To search for a file, use find / with the following properties:

  • File type: -type f
  • Owned by bandit7: -user bandit7
  • Grouped by bandit6: -group bandit6
  • Exactly 33 bytes: -size 33c
  • Redirect errors to null: 2>/dev/null

Run the following command:

find / -type f -user bandit7 -group bandit6 -size 33c 2>/dev/null

The file you're looking for is /var/lib/dpkg/info/bandit7.password.

Read it with:

cat /var/lib/dpkg/info/bandit7.password
🚩: morbNTDkSW6jIlUc0ymOdMaLnOlFVAaj

Key Learnings:

Use find with specific criteria to locate files, and redirect error messages to /dev/null to avoid cluttering the output.

Bandit Level 7

Objective: Find a specific word in a large text file.

There's a file called data.txt that contains a lot of text.

According to the hint, the flag should be next to the millionth word.

To find it, use the following command:

cat data.txt | grep millionth
🚩: dfwvzFQi4mU0wfNbFOe9RoWskMLg7eEc

Key Learnings:

Use grep to search through large files for specific words or phrases, especially when you know a word's position in the text.

Bandit Level 8

Objective: Find the unique line in a file containing many duplicates.

The hint tells us that data.txt contains duplicates, and the flag appears only once.

To find the unique line (the flag), use the following commands:

sort data.txt | uniq -u
🚩: 4CKMh1JI91bUIZZPXDqGanal4xvAg0JM

Key Learnings:

Use sort followed by uniq -u to find unique lines in a file, especially when duplicates are present.

Bandit Level 9

Objective: Find human-readable strings in a binary file that are preceded by equals signs.

You need to find human-readable strings in the file that are preceded by several = characters.

Use the command:

strings data.txt | grep ===
🚩: FGUW5ilLVJrxX9kMYMmlN4MgbpfMiqey

Key Learnings:

strings extracts readable text from binary files, and grep can be used to filter specific patterns like ===.

Levels 10-19: Encoding & Network

Bandit Level 10

Objective: Decode base64 encoded data.

The content of the file is base64 encoded.

Use the base64 command with the -d flag to decode it.

base64 -d data.txt
🚩: dtR173fZKb0RRsDFSGsg2RWnpNVj3qRr

Key Learnings:

base64 -d decodes base64 encoded data and can be used to reveal hidden text in files.

Bandit Level 11

Objective: Decode ROT13 encoded text.

The text file contains a ROT13 encoded message.

View the content with: cat data.txt

Decode it using:

cat data.txt | tr 'A-Za-z' 'N-ZA-Mn-za-m'
🚩: 7x16WNeHIi5YkIhWsfFIqoognUTyj9Q4

Key Learnings:

tr 'A-Za-z' 'N-ZA-Mn-za-m' performs a ROT13 transformation on the input text by rotating each alphabet character by 13 positions.

Bandit Level 12

Objective: Handle multiple levels of file compression from a hexdump.

The file is a hexdump of a file that's been compressed multiple times.

Create a temp directory and copy the file:

cp ../../home/bandit12/data.txt .

Convert the hex dump back to binary:

xxd -r data.txt > data.bin

Use file to determine compression type, then decompress accordingly:

  • mv data.bin data.gz, gunzip data.gz
  • bunzip2, tar -xf, rename and repeat depending on file type

Eventually, view the content: cat data8

🚩: FO5dwFsc0cbaIiH0h8J2eUks2vdTDwAn

Key Learnings:

How to handle multiple levels of file compression and transform a hex dump back into a usable binary file using xxd -r.

Bandit Level 13

Objective: Use an SSH private key for authentication.

You are given a private SSH key and need to login to the next level user.

Use the SSH key to log in:

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

Once logged in, read the password file:

cat /etc/bandit_pass/bandit14
🚩: MU4VWeTyJk8ROof1qqmcBPaLh7lDCPvS

Key Learnings:

How to use an SSH private key for authentication with the -i flag and access restricted files from another user.

Bandit Level 14

Objective: Connect to a service using netcat.

Use netcat to connect to port 30000 and provide the password from Bandit13.

nc localhost 30000
🚩: 8xCjnmgoKbGLhHFAZlGE5Tmu4M2tKJQo

Key Learnings:

How to use nc (netcat) to connect to a TCP port and interact with a remote service.

Bandit Level 15

Objective: Connect to an SSL-enabled service.

Connect to an SSL-enabled port using OpenSSL and input the Bandit14 password.

openssl s_client -connect localhost:30001
🚩: kSkvUpMQ7lBYyCM4GBPvCvT1BfWRy0Dx

Key Learnings:

How to use openssl s_client to establish an SSL connection and send input.

Bandit Level 16

Objective: Port scan and identify the correct SSL service.

Scan for open ports between 31000 and 32000 using nmap.

nmap -p31000-32000 localhost

Try the open ports with openssl s_client -quiet -connect localhost:[port]

Port 31790 is the correct one.

Enter the Bandit15 flag to receive an SSH private key.

Save the key to a file and secure it with:

chmod 600 keys.private

Use the key to log in:

ssh -i keys.private bandit17@bandit.labs.overthewire.org -p 2220
🚩: EReVavePLFHtFlFsjn3hyzMlvSuSAcRD

Key Learnings:

How to scan for open ports, establish a secure connection, and use SSH keys for login.

Bandit Level 17

Objective: Compare two files to find differences.

Compare two password files to find the difference.

diff password.new password.old
🚩: x2gLTTjFwMOhQ8oWNbMN362QKxfRqGlO

Key Learnings:

The diff command can be used to find differences between two files, which is useful for identifying modified content.

Bandit Level 18

Objective: Bypass a logout script by executing commands via SSH.

The login script immediately logs you out, so pipe the command to print the README before getting kicked.

ssh bandit.labs.overthewire.org -p 2220 -l bandit18 cat readme
🚩: cGWpMaKXVwDUNgPAVJbWYuGHVn9zl3j8

Key Learnings:

How to use SSH with a command to bypass forced logout scripts.

Bandit Level 19

Objective: Use a setuid binary to read files as another user.

Use a special binary that runs as bandit20 to read the password file.

./bandit20-do cat /../../etc/bandit_pass/bandit20
🚩: 0qXahG8ZjOVMN9Ghs7iOWsCfZyXOUbYO

Key Learnings:

How to use setuid binaries to execute commands as another user.

Levels 20-29: Advanced Techniques

Bandit Level 20

Objective: Create a network service and interact with a binary that connects to it.

Run a TCP server with a specific response that matches the expected password input for the suconnect binary.

Start the listener:

echo '0qXahG8ZjOVMN9Ghs7iOWsCfZyXOUbYO' | nc -l -p [your port]

Then execute:

./suconnect [port]
🚩: EeoULMCra2q0dSkYj561DX7s1CpBuOBt

Key Learnings:

How to create a TCP server using nc and provide dynamic input to a binary expecting network interaction.

Bandit Level 21

Objective: Analyze cron jobs to find password files.

Investigate cron jobs to find a script that copies a password to a known location.

Check:

cat /usr/bin/cronjob_bandit22.sh

Then:

cat /tmp/t7O6lds9S0RqQh9aMcz6ShpAoZKF7fgv
🚩: tRae0UfB9v0UzbCdn9cY0gQnds9GF58Q

Key Learnings:

Cron jobs can be used to gain access to otherwise restricted files when scripts copy data to world-readable locations.

Bandit Level 22

Objective: Reverse engineer a cron script that creates dynamic filenames.

Another cron job but this one creates a hash based on the current username and copies that user's password to /tmp.

Generate the hash:

echo 'I am user bandit23' | md5sum | cut -d ' ' -f 1

Then:

cat /tmp/[hash]
🚩: 0Zf11ioIjMVN551jX3CmStKLYqjk54Ga

Key Learnings:

How to reverse-engineer cron scripts that create unique filenames dynamically using hashed usernames.

Bandit Level 23

Objective: Create a script that will be executed by a cron job.

To begin, write a script that will be activated every minute by a cron job.

Start by creating a space within /tmp holding the correct permissions for your text file to save. You can use the following commands:

mkdir -p /tmp/print
chmod 777 /tmp/print

Next, create a script in /var/spool/bandit24/foo/ with the following contents:

#!/bin/bash
echo "hi" > /tmp/print/hi.txt

Make the script executable:

chmod +x /var/spool/bandit24/foo/bandito.sh

Then run the script:

cat /tmp/print/hi.txt

Now, to copy the Bandit24 flag, modify the script to the following:

#!/bin/bash
cat /etc/bandit_pass/bandit24 > /tmp/print/flag.txt
🚩: gb8KRRCsshuZXI0tUuR6ypOFjiZbf3G8

Key Learnings:

By using a cron job, you can automate tasks such as copying files at regular intervals. This is a common method to periodically run scripts in Unix-like systems.

Bandit Level 24

Objective: Brute force a PIN code over a network connection.

This level requires brute-forcing a PIN code to gain access to the Bandit25 flag.

#!/bin/bash

flag="gb8KRRCsshuZXI0tUuR6ypOFjiZbf3G8"
host="localhost"
port="30002"

for pincode in {0000..9999}
do
    echo "$flag $pincode"
done | nc $host $port
🚩: iCi86ttT4KSNe1armKiwbQNmB3YJP3q4

Key Learnings:

When brute-forcing over a network connection, it's more efficient to maintain a single connection and pipe data into it, rather than reconnecting each time.

Bandit Level 25

Objective: Exploit the 'more' command in a restricted shell environment.

This level required logging in as bandit26 from bandit25 using an SSH key.

First, list the files and find the private key:

ls

Use the key to SSH into the next level:

ssh -i bandit26.sshkey bandit26@localhost -p 2220

Connection immediately closes after showing an ASCII logo. Upon inspection, the shell for bandit26 is not /bin/bash:

cat /etc/passwd

Find the shell points to a script: /usr/bin/showtext

#!/bin/sh
export TERM=linux
exec more ~/text.txt
exit 0

The script launches more, which can be exploited if the terminal window is small enough to trigger the --More-- prompt.

At the --More-- prompt:

  • Press v to open vi
  • Then enter :set shell=/bin/bash
  • And then run :shell

This drops you into a real shell where you can read the password:

cat /etc/bandit_pass/bandit26
🚩: s0773xxkk0MXfdqOfPRVr9L3jJBUOgCZ

Key Learnings:

Even restricted environments using limited shells (like more) can be exploited if interactive tools (like vi) are accessible. Small terminal tricks can lead to big escapes.

Bandit Level 26

Objective: Use a setuid wrapper to execute commands as another user.

This level continues from Bandit25. After logging in, list the files:

ls

You'll see a file named bandit27-do. Running it shows:

Run a command as another user.
Example: ./bandit27-do id

Use it to run the following command:

./bandit27-do cat /etc/bandit_pass/bandit27
🚩: upsNCc7vzaRDx6oZC6GiR6ERwe1MowGB

Key Learnings:

Binary wrappers like bandit27-do can be used to execute commands as another user—great for privilege escalation.

Bandit Level 27

Objective: Clone a Git repository over SSH.

This level involves cloning a Git repo over SSH.

Navigate to a writable directory first:

cd /tmp
mkdir gc
cd gc

Clone the Git repository using the appropriate SSH command:

git clone ssh://bandit27-git@localhost:2220/home/bandit27-git/repo

Then navigate into the cloned repository:

cd repo

Read the README file:

cat README
🚩: Yz9IpL0sBcCeuG7m9uQFt8ZNpS4HZRcN

Key Learnings:

You can use custom SSH commands with git clone to access restricted Git repos even when ports or auth methods are unusual.

Bandit Level 28

Objective: Find sensitive information in Git commit history.

Clone the repository using SSH:

git clone ssh://bandit28-git@localhost:2220/home/bandit28-git/repo

Navigate to the repo and view the file:

cd repo
cat README.md

The file lists credentials and hints at a prior commit leak.

Check the commit history:

git log

Find and inspect the commit with the message "fix info leak":

git show 674690a00a0056ab96048f7317b9ec20c057c06b
🚩: 4pT1t5DENaYuqnqvadYs1oE4QLCdjmJ7

Key Learnings:

Commit history can contain sensitive info even after being "fixed"—always check old commits in CTFs and real audits.

Bandit Level 29

Objective: Find information hidden in Git branches.

Clone the repository:

git clone ssh://bandit29-git@localhost:2220/home/bandit29-git/repo

List remote branches:

git branch -r

Switch to the dev branch:

git checkout dev
🚩: qp30ex3VLz5MDG1n91YowTv4Q8l7CDZL

Key Learnings:

CTF flags might be hidden in alternate Git branches—don't forget to check all of them, especially non-master ones.

Levels 30-33: Final Challenges

Bandit Level 30

Objective: Find information stored in Git tags.

Clone the repository:

git clone ssh://bandit30-git@localhost:2220/home/bandit30-git/repo

README.md contains a friendly message, but no flag.

Try exploring other Git features. This time, try tags:

git tag

A tag named secret appears. Show its contents:

git show secret
🚩: fb5S2xb7bRyFmAvQYQGEqsbhVyJqhnDy

Key Learnings:

Besides commits and branches, Git tags can also store hidden data or flags—great spot for secrets.

Bandit Level 31

Objective: Push a file to a Git repository while bypassing .gitignore.

Clone the Git repository:

git clone ssh://bandit31-git@localhost:2220/home/bandit31-git/repo

Create a file with the required message:

echo 'May I come in?' > key.txt

Add the file forcibly (some files might be ignored by .gitignore):

git add -f key.txt

Commit and push:

git commit -m "keys"
git push
🚩: 3O9RfhqyAlVBEZpVb6LYStshZoqoSx5K

Key Learnings:

Sometimes the solution is as simple as creating a file with the correct content and pushing it—knowing how to bypass .gitignore helps too.

Bandit Level 32

Objective: Escape a restricted shell environment.

This level restricts the use of many standard shell commands. Direct commands like ls or cat fail.

After several failed attempts (like using \ls or bash -c), the working solution is:

$0

This runs the script again in a cleaner shell environment. Once inside, simply run:

cat /etc/bandit_pass/bandit33
🚩: tQdtbs5D5i2vJwkO8mEyYEyTL8izoeJ0

Key Learnings:

When standard commands are blocked, re-triggering the shell script with $0 can reset the environment and bypass constraints.

Bandit Level 33

Objective: Congratulations! You've completed the Bandit wargame.

Hungry for more? Check out Leviathan for your next challenge.

What's Next:

Now that you've mastered the basics of Linux command line and security concepts, consider exploring:

  • Other OverTheWire challenges like Leviathan, Krypton, or Natas
  • HackTheBox machines for real-world penetration testing scenarios
  • TryHackMe rooms for structured cybersecurity learning paths