0xnhl

OTW: Bandit Writeup

/ Update
30 min read
Writeup on the Bandit challenges series by Over The Wire

Platform: Linux
Link: https://overthewire.org/wargames/bandit/
Over The Wire-Bandit-78805a22

SSH Information
Host: bandit.labs.overthewire.org
Port: 2220

You start at Level 0 and try to “beat” or “finish” it. Finishing a level results in information on how to start the next level.
Username is the level that you are currently in. ie username for level 1 is bandit1

Level 0#

Hint: The password for the next level is stored in a file called readme located in the home directory.

ssh bandit0@bandit.labs.overthewire.org -p 2220 ` 
password: bandit0

bandit0@bandit:~$ ls
readme
bandit0@bandit:~$ pwd 
/home/bandit0
bandit0@bandit:~$ cat readme 
Congratulations on your first steps into the bandit game!!
Please make sure you have read the rules at https://overthewire.org/rules/
If you are following a course, workshop, walkthrough or other educational activity,
please inform the instructor about the rules as well and encourage them to
contribute to the OverTheWire community so we can keep these games free!

The password you are looking for is: ####REDACTED####
plaintext

Level 1#

Hint: The password for the next level is stored in a file called - located in the home directory

Level 2#

Hint: The password for the next level is stored in a file called --spaces in this filename-- located in the home directory.

ssh bandit2@bandit.labs.overthewire.org -p 2220
bandit2@bandit:~$ pwd
/home/bandit2
bandit2@bandit:~$ ls -la
total 24
-rw-r-----   1 bandit3 bandit2   33 Jun 24 14:59 --spaces in this filename--
drwxr-xr-x   2 root    root    4096 Jun 24 14:59 .
drwxr-xr-x 150 root    root    4096 Jun 24 15:02 ..
-rw-r--r--   1 root    root     220 Feb 13 12:16 .bash_logout
-rw-r--r--   1 root    root    3851 Jun 24 14:50 .bashrc
-rw-r--r--   1 root    root     807 Feb 13 12:16 .profile
bandit2@bandit:~$ cat ./--spaces\ in\ this\ filename-- 
####REDACTED####
plaintext

Level 3#

Hint: The password for the next level is stored in a hidden file in the inhere directory.

Level 4#

Hint: The password for the next level is stored in the only human-readable file in the inhere directory.

The command tail -n +1 outputs the entire contents of a file starting from the very first line

The command grep -I -H "" ./* will search for “everything” in a file with grep. -I tells grep to ignore binary files completely. -H forces it to print the filename.

bandit4@bandit:~/inhere$ grep -I -H "" ./*
./-file07:====REDACTED====
plaintext

Level 5#

Hint: The password for the next level is stored in a file somewhere under the inhere directory and has all of the following properties:

  • human-readable
  • 1033 bytes in size
  • not executable
bandit5@bandit:~$ ls
inhere
bandit5@bandit:~/inhere$ ls 
maybehere00  maybehere02  maybehere04  maybehere06  maybehere08  maybehere10  maybehere12  maybehere14  maybehere16  maybehere18
maybehere01  maybehere03  maybehere05  maybehere07  maybehere09  maybehere11  maybehere13  maybehere15  maybehere17  maybehere19
bandit5@bandit:~/inhere$ ls maybehere00
-file1  -file2  -file3  spaces file1  spaces file2  spaces file3
plaintext

Each folder contains files like this.
We can use find command to find the file matching our criteria.

bandit5@bandit:~/inhere$ find . -type f -size 1033c ! -executable
./maybehere07/.file2
bandit5@bandit:~/inhere$ cat ./maybehere07/.file2
====REDACTED====
plaintext
  • -type f: Filters the search to regular files only,
  • -size 1033c: Matches files that are exactly 1033 bytes in size (c stands for bytes).

Level 6#

Hint: The password for the next level is stored somewhere on the server and has all of the following properties:

  • owned by user bandit7
  • owned by group bandit6
  • 33 bytes in size
bandit6@bandit:~$ ls -la
total 20
drwxr-xr-x   2 root root 4096 Jun 24 14:58 .
drwxr-xr-x 150 root root 4096 Jun 24 15:02 ..
-rw-r--r--   1 root root  220 Feb 13 12:16 .bash_logout
-rw-r--r--   1 root root 3851 Jun 24 14:50 .bashrc
-rw-r--r--   1 root root  807 Feb 13 12:16 .profile
plaintext

There’s nothing useful in the home folder.
Lets use the find command:

bandit6@bandit:~$ find / -type f -user bandit7 -group bandit6 -size 33c 2>/dev/null
/var/lib/dpkg/info/bandit7.password
cat /var/lib/dpkg/info/bandit7.password
====REDACTED====
plaintext
  • -user filters by file owner and -group filter file group.
  • 2>/dev/null is used to silence error messages by redirecting them to /dev/null.

Level 7#

Hint: The password for the next level is stored in the file data.txt next to the word millionth

bandit7@bandit:~$ ls
data.txt
bandit7@bandit:~$ grep "millionth" data.txt 
millionth	====REDACTED====
plaintext

Level 8#

Hint: The password for the next level is stored in the file data.txt and is the only line of text that occurs only once

bandit8@bandit:~$ ls 
data.txt
bandit8@bandit:~$ sort data.txt | uniq -u
====REDACTED====
plaintext
  • sort: Rearranges the lines alphabetically. This is required because the next command (uniq) only compares consecutive lines.
  • uniq -u: Filters the list and prints only the unique lines that appear exactly once in the file. -c will display count of every line.

Level 9#

Hint: The password for the next level is stored in the file data.txt in one of the few human-readable strings, preceded by several ‘=’ characters.

bandit9@bandit:~$ strings data.txt | grep ====
cL0========== the
========== password
>========== is
R========== ====REDACTED====
plaintext
  • strings - print the sequences of printable characters in files

Level 10#

Hint: The password for the next level is stored in the file data.txt, which contains base64 encoded data

bandit10@bandit:~$ ls 
data.txt
bandit10@bandit:~$ base64 -d data.txt 
The password is ====REDACTED====
plaintext

Level 11#

Hint: The password for the next level is stored in the file data.txt, where all lowercase (a-z) and uppercase (A-Z) letters have been rotated by 13 positions

bandit11@bandit:~$ ls
data.txt
bandit11@bandit:~$ cat data.txt 
Gur cnffjbeq vf TEBbmJCB8DlA0zTewHxVQ0JPLxMvDkeA
bandit11@bandit:~$ cat data.txt | tr 'A-Za-z' 'N-ZA-Mn-za-m'
The password is ====REDACTED====
plaintext
  • tr: Replaces characters from the first set with characters in the matching position of the second set.
  • A-Za-z: Defines the source alphabet (uppercase A-Z, lowercase a-z).
  • N-ZA-Mn-za-m: Defines the target alphabet shifted by 13 spaces (starting at N, wrapping around to A).

Level 12#

Hint: The password for the next level is stored in the file data.txt, which is a hexdump of a file that has been repeatedly compressed.

bandit12@bandit:~$ mktemp -d
/tmp/tmp.iyflICIAxQ
bandit12@bandit:~$ cp data.txt /tmp/tmp.iyflICIAxQ
bandit12@bandit:~$ cd /tmp/tmp.iyflICIAxQ
bandit12@bandit:/tmp/tmp.iyflICIAxQ$ ls
data.txt
plaintext
  • The xxd command converts binary files into hexadecimal dumps for inspection and debugging. We can also converts hexadecimal dumps back into the original binary files by using xxd -r
bandit12@bandit:/tmp/tmp.iyflICIAxQ$ mv data.txt hex.txt
bandit12@bandit:/tmp/tmp.iyflICIAxQ$ xxd -r hex.txt > comp_bin
bandit12@bandit:/tmp/tmp.iyflICIAxQ$ file comp_bin 
comp_bin: gzip compressed data, was "data2.bin", last modified: Wed Jun 24 14:58:58 2026, max compression, from Unix, original size modulo 2^32 578
plaintext

We get a gzip file.

bandit12@bandit:/tmp/tmp.iyflICIAxQ$ gunzip -c comp_bin > data1
bandit12@bandit:/tmp/tmp.iyflICIAxQ$ file data1
data1: bzip2 compressed data, block size = 900k
plaintext

We get a bzip file.

bandit12@bandit:/tmp/tmp.iyflICIAxQ$ bunzip2 -c data1 > data2
bandit12@bandit:/tmp/tmp.iyflICIAxQ$ file data2
data2: gzip compressed data, was "data4.bin", last modified: Wed Jun 24 14:58:58 2026, max compression, from Unix, original size modulo 2^32 20480
plaintext

We get a gzip file.

bandit12@bandit:/tmp/tmp.iyflICIAxQ$ gunzip -c data2 > data3
bandit12@bandit:/tmp/tmp.iyflICIAxQ$ file data3
data3: POSIX tar archive (GNU)
plaintext

We get a tar file.

bandit12@bandit:/tmp/tmp.iyflICIAxQ$ tar -xf data3
bandit12@bandit:/tmp/tmp.iyflICIAxQ$ ls
comp_bin  data1  data2  data3  data5.bin  hex.txt
bandit12@bandit:/tmp/tmp.iyflICIAxQ$ file data5.bin 
data5.bin: POSIX tar archive (GNU)
plaintext

Again a tar file

bandit12@bandit:/tmp/tmp.iyflICIAxQ$ tar -xf data5.bin
bandit12@bandit:/tmp/tmp.iyflICIAxQ$ ls
comp_bin  data1  data2  data3  data5.bin  data6.bin  hex.txt
bandit12@bandit:/tmp/tmp.iyflICIAxQ$ file data6.bin
data6.bin: bzip2 compressed data, block size = 900k
plaintext

A bzip file

bandit12@bandit:/tmp/tmp.iyflICIAxQ$ bunzip2 -c data6.bin > data7.bin
bandit12@bandit:/tmp/tmp.iyflICIAxQ$ file data7.bin 
data7.bin: POSIX tar archive (GNU)
plaintext

A tar file

bandit12@bandit:/tmp/tmp.iyflICIAxQ$ tar -xf data7.bin
bandit12@bandit:/tmp/tmp.iyflICIAxQ$ ls
comp_bin  data1  data2  data3  data5.bin  data6.bin  data7.bin  data8.bin  hex.txt
bandit12@bandit:/tmp/tmp.iyflICIAxQ$ file data8.bin
data8.bin: gzip compressed data, was "data9.bin", last modified: Wed Jun 24 14:58:58 2026, max compression, from Unix, original size modulo 2^32 49
plaintext

A gzip file

bandit12@bandit:/tmp/tmp.iyflICIAxQ$ gunzip -c data8.bin > data9.bin
bandit12@bandit:/tmp/tmp.iyflICIAxQ$ file data9.bin 
data9.bin: ASCII text
plaintext

Finally a text file!!!

bandit12@bandit:/tmp/tmp.iyflICIAxQ$ cat data9.bin 
The password is ====REDACTED====
plaintext

Level 13#

Hint: The password for the next level is stored in /etc/bandit_pass/bandit14 and can only be read by user bandit14. For this level, you don’t get the next password, but you get a private SSH key that can be used to log into the next level. Look at the commands that logged you into previous bandit levels, and find out how to use the key for this level.
If you need help with this level: a hint file can be found in the home directory.
Make sure to read the error messages as they are informative.

bandit13@bandit:~$ ls
HINT  sshkey.private
bandit13@bandit:~$ ls -la /etc/bandit_pass/bandit14
-r-------- 1 bandit14 bandit14 33 Jun 24 14:58 /etc/bandit_pass/bandit14
bandit13@bandit:~$ cat /etc/bandit_pass/bandit14
cat: /etc/bandit_pass/bandit14: Permission denied
plaintext

On local machine:

> scp -P 2220 bandit13@bandit.labs.overthewire.org:sshkey.private .
> ls -la
.rw-r-----@ 2.6k neo  neo   26 Jul 18:47  sshkey.private
> chmod 600 sshkey.private
> ssh bandit14@bandit.labs.overthewire.org -p 2220 -i sshkey.private
plaintext

Now you are in bandit14.

bandit14@bandit:~$ cat /etc/bandit_pass/bandit14
====REDACTED====
plaintext

Level 14#

Hint: The password for the next level can be retrieved by submitting the password of the current level to port 30000 on localhost.

bandit14@bandit:~$ telnet localhost 30000
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
====REDACTED====    # Enter password of current level here.
Correct!
====REDACTED====

Connection closed by foreign host.
plaintext

We can also use netcat:

bandit14@bandit:~$ netcat localhost 30000
====REDACTED====
Correct!
====REDACTED====
plaintext

Level 15#

Hint: The password for the next level can be retrieved by submitting the password of the current level to port 30001 on localhost using SSL/TLS encryption.

ncat is an alternative implementation of netcat/nc by nmap.

bandit15@bandit:~$ ncat localhost 30001 --ssl
====REDACTED====   # Enter password of current level here.
Correct!
====REDACTED====
plaintext

We can also use the openssl tool.

Level 16#

Hint: The credentials for the next level can be retrieved by submitting the password of the current level to a port on localhost in the range 31000 to 32000. First find out which of these ports have a server listening on them. Then find out which of those speak SSL/TLS and which don’t. There is only 1 server that will give the next credentials, the others will simply send back to you whatever you send to it.

Connecting to port 31790

bandit16@bandit:~$ ncat localhost 31790 --ssl
kS0Hf0u5HiXFwKMKFqXvPdOTNGGa0X8V
Correct!
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABlwAAAAdzc2gtcn
====REDACTED_FOR_BREVITY====
Pfos/2C+rbNuHjAAAADnJ1ZHlAbG9jYWxob3N0AQIDBA==
-----END OPENSSH PRIVATE KEY-----
plaintext

Level 17#

Hint: There are 2 files in the homedirectory: passwords.old and passwords.new. The password for the next level is in passwords.new and is the only line that has been changed between passwords.old and passwords.new
Copy the ssh key from the previous level.

nano sshkey.private.17
chmod 600 sshkey.private.17                                                                                                                        ssh bandit17@bandit.labs.overthewire.org -p 2220 -i sshkey.private.17
plaintext

Logged into bandit17

bandit17@bandit:~$ ls 
passwords.new  passwords.old
bandit17@bandit:~$ diff passwords.old passwords.new 
42c42
< icUh23IUytZLIYhcCaXL18agiSIqymBc
---
> OQxXZjELndr====REDACTED====
plaintext

Level 18#

Hint: The password for the next level is stored in a file readme in the homedirectory. Unfortunately, someone has modified .bashrc to log you out when you log in with SSH.
We can use scp

Level 19#

Hint: To gain access to the next level, you should use the setuid binary in the homedirectory. Execute it without arguments to find out how to use it. The password for this level can be found in the usual place (/etc/bandit_pass), after you have used the setuid binary.

bandit19@bandit:~$ ls -l
total 16
-rwsr-x--- 1 bandit20 bandit19 14880 Jun 24 14:59 bandit20-do
plaintext

We can see that the file is called bandit20-do and when we list the details of the file we can see that the binary file can be executed by the current user (bandit19) and it is owned by bandit20.

bandit19@bandit:~$ ./bandit20-do 
Run a command as another user.
  Example: ./bandit20-do whoami
bandit19@bandit:~$ ./bandit20-do whoami
bandit20
plaintext

We observe that when we use the binary file we are assigned the uid for bandit20 as well which means we can run commands as if we are bandit20

bandit19@bandit:~$ ./bandit20-do cat /etc/bandit_pass/bandit20 
4pIjcu====REDACTED====
plaintext

Level 20#

Hint: There is a setuid binary in the homedirectory that does the following: it makes a connection to localhost on the port you specify as a commandline argument. It then reads a line of text from the connection and compares it to the password in the previous level (bandit20). If the password is correct, it will transmit the password for the next level (bandit21).

bandit20@bandit:~$ ls -l
total 16
-rwsr-x--- 1 bandit21 bandit20 15604 Jun 24 14:59 suconnect
bandit20@bandit:~$ ./suconnect 
Usage: ./suconnect <portnumber>
This program will connect to the given port on localhost using TCP. If it receives the correct password from the other side, the next password is transmitted back.
plaintext

So we need to set up a listener that will return the previous level password if we connect to it.

bandit20@bandit:~$ echo 4pIjcunZ0====REDACTED==== | nc -lp 1234 &
[1] 186
plaintext

We use & at the end of the command to run it in the background.

bandit20@bandit:~$ jobs
[1]+  Running                    echo 4pIjcunZ0f====REDACTED==== | nc -lp 1234 &
plaintext

Connecting to it using the given binary.

bandit20@bandit:~$ ./suconnect 1234
Read: 4pIjcunZ0fK2====REDACTED====
Password matches, sending next password
bW9kBv5WC3====REDACTED====
[1]+  Done                       echo 4pIjcunZ0fK2====REDACTED==== | nc -lp 1234
plaintext

Level 21#

Hint: A program is running automatically at regular intervals from cron, the time-based job scheduler. Look in /etc/cron.d/ for the configuration and see what command is being executed.

We can see it copies the password to a file at /tmp/t7O6lds9S0RqQh9aMcz6ShpAoZKF7fgv

bandit21@bandit:~$ ls -l /tmp/t7O6lds9S0RqQh9aMcz6ShpAoZKF7fgv
-rw-r--r-- 1 bandit22 bandit22 33 Jul 26 17:51 /tmp/t7O6lds9S0RqQh9aMcz6ShpAoZKF7fgv
bandit21@bandit:~$ cat /tmp/t7O6lds9S0RqQh9aMcz6ShpAoZKF7fgv
RYVux2rHEm9tiXHmLFzuR7Vhx6AZQMEz
plaintext

Level 22#

Hint: A program is running automatically at regular intervals from cron, the time-based job scheduler. Look in /etc/cron.d/ for the configuration and see what command is being executed.

bandit22@bandit:~$ ls /etc/cron.d
behemoth4_cleanup  clean_tmp  cronjob_bandit22  cronjob_bandit23  cronjob_bandit24  e2scrub_all  leviathan5_cleanup  manpage3_resetpw_job  otw-tmp-dir
bandit22@bandit:~$ cat /etc/cron.d/cronjob_bandit23
@reboot bandit23 /usr/bin/cronjob_bandit23.sh  &> /dev/null
* * * * * bandit23 /usr/bin/cronjob_bandit23.sh  &> /dev/null
plaintext

We can see a script

bandit22@bandit:~$ ls -l /usr/bin/cronjob_bandit23.sh
-rwxr-x--- 1 bandit23 bandit22 211 Jun 24 14:59 /usr/bin/cronjob_bandit23.sh
bandit22@bandit:~$ cat /usr/bin/cronjob_bandit23.sh
#!/bin/bash

myname=$(whoami)
mytarget=$(echo I am user $myname | md5sum | cut -d ' ' -f 1)

echo "Copying passwordfile /etc/bandit_pass/$myname to /tmp/$mytarget"

cat /etc/bandit_pass/$myname > /tmp/$mytarget
plaintext

It copies the password to file in /tmp. To get file name, we have to know the $mytarget which is the value of $(echo I am user $myname | md5sum | cut -d ' ' -f 1) where $myname is the output of $whoami which will be bandit23 since the file is owned by user bandit23.

bandit22@bandit:~$ echo I am user bandit23 | md5sum | cut -d ' ' -f 1
8ca319486bfbbc3663ea0fbe81326349
bandit22@bandit:~$ cat /tmp/8ca319486bfbbc3663ea0fbe81326349
gKXDTA====REDACTED====
plaintext

Level 23#

Hint: A program is running automatically at regular intervals from cron, the time-based job scheduler. Look in /etc/cron.d/ for the configuration and see what command is being executed.
NOTE: This level requires you to create your own first shell-script.

bandit23@bandit:~$ ls /etc/cron.d/
behemoth4_cleanup  clean_tmp  cronjob_bandit22  cronjob_bandit23  cronjob_bandit24  e2scrub_all  leviathan5_cleanup  manpage3_resetpw_job  otw-tmp-dir
bandit23@bandit:~$ cat /etc/cron.d/cronjob_bandit24
@reboot bandit24 /usr/bin/cronjob_bandit24.sh &> /dev/null
* * * * * bandit24 /usr/bin/cronjob_bandit24.sh &> /dev/null
bandit23@bandit:~$ ls -l /usr/bin/cronjob_bandit24.sh
-rwxr-x--- 1 bandit24 bandit23 438 Jun 24 14:59 /usr/bin/cronjob_bandit24.sh
plaintext

Any script we write in /var/spool/bandit24/foo will be run by the cronjob script as the bandit24 user.
save the following script at /var/spool/bandit24/foo/script.sh

#!/bin/bash
myname=$(whoami)
cat /etc/bandit_pass/$myname > /tmp/bandit_24_temp_pass
bash
bandit23@bandit:~$ nano /var/spool/bandit24/foo/script.sh
Unable to create directory /home/bandit23/.local/share/nano/: No such file or directory
It is required for saving/loading search history or cursor positions.

bandit23@bandit:~$ chmod +x /var/spool/bandit24/foo/script.sh
bandit23@bandit:~$ ls -l /var/spool/bandit24/foo/script.sh
-rwxrwxr-x 1 bandit23 bandit23 73 Jul 26 18:18 /var/spool/bandit24/foo/script.sh
plaintext

Now when the cronjob runs, the script will get executed and the passwrod will be written to the /tmp/bandit_24_temp_pass file.

bandit23@bandit:~$ cat /tmp/bandit_24_temp_pass
hVQMk3lJNs====REDACTED====
plaintext

Level 24#

Hint: A daemon is listening on port 30002 and will give you the password for bandit25 if given the password for bandit24 and a secret numeric 4-digit pincode. There is no way to retrieve the pincode except by going through all of the 10000 combinations, called brute-forcing.
You do not need to create new connections each time

bandit24@bandit:~$ netcat localhost 30002
I am the pincode checker for user bandit25. Please enter the password for user bandit24 and the secret pincode on a single line, separated by a space.
hVQMk3lJNsmQ7VF3ubyrNNBom7BOgVXv 1234
Wrong! Please enter the correct current password and pincode. Try again.
^C
plaintext

We need to bruteforce the pin by looping from 0000 to 9999. We can use the following command:

for i in {0000..9999}; do echo "hVQMk3lJNsmQ7VF3ubyrNNBom7BOgVXv $i"; done | nc localhost 30002
bash
bandit24@bandit:~$ for i in {0000..9999}; do echo "hVQMk3lJNsmQ7VF3ubyrNNBom7BOgVXv $i"; done | nc localhost 30002
I am the pincode checker for user bandit25. Please enter the password for user bandit24 and the secret pincode on a single line, separated by a space.
Wrong! Please enter the correct current password and pincode. Try again.
Wrong! Please enter the correct current password and pincode. Try again.
Wrong! Please enter the correct current password and pincode. Try again.
Wrong! Please enter the correct current password and pincode. Try again.
...
Wrong! Please enter the correct current password and pincode. Try again.
Correct!
The password of user bandit25 is SoHfqMOEqI====REDACTED====
plaintext

Level 25#

Hint: Logging in to bandit26 from bandit25 should be fairly easy… The shell for user bandit26 is not /bin/bash, but something else. Find out what it is, how it works and how to break out of it.

bandit25@bandit:~$ ls
bandit26.sshkey
plaintext

We can see an ssh key for bandit26 in home.
To know what shell bandit26 is using we can check the /etc/passwd file.

bandit25@bandit:~$ cat /etc/passwd | grep bandit26
bandit26:x:11026:11026:bandit level 26:/home/bandit26:/usr/bin/showtext
plaintext

Inspecting /usr/bin/showtext

bandit25@bandit:~$ cat /usr/bin/showtext
#!/bin/sh

export TERM=linux

exec more ~/text.txt
exit 0
plaintext

We can see showtext is a script that opens a file called ’text.txt’ with the more program.

Let’s try logging into bandit26:

scp -P 2220 bandit25@bandit.labs.overthewire.org:bandit26.sshkey . 
chmod 600 bandit26.sshkey
ssh bandit26@bandit.labs.overthewire.org -p 2220 -i bandit26.sshkey
...
  _                     _ _ _   ___   __  
 | |                   | (_) | |__ \ / /  
 | |__   __ _ _ __   __| |_| |_   ) / /_  
 | '_ \ / _` | '_ \ / _` | | __| / / '_ \ 
 | |_) | (_| | | | | (_| | | |_ / /| (_) |
 |_.__/ \__,_|_| |_|\__,_|_|\__|____\___/ 
Connection to bandit.labs.overthewire.org closed.
plaintext

When trying to log in, we see that the connection is closed because ‘/usr/bin/showtext’ is executed.

The text in ’text.txt’ is very short, meaning the whole text can immediately be displayed. more does not need to go into command/interactive mode. If we make the terminal window smaller, more will go into command mode. We can then use v to go into vim.

Now rescale the terminal window and try connecting.
Vim is now opened as bandit26 and we can do different things to retrieve the password.
With :e /etc/bandit\_pass/bandit26 we can open the password file and read the password.
If we want a shell, we can use the :shell command that vim offers. This command, however, uses the user’s default shell. What we need to do instead is to set the default shell of the user in vim to a useful shell, like \bin\bash by running :set shell=/bin/bash and then use :shell. We have a bash shell as bandit26.

bandit26@bandit:~$ whoami
bandit26
bandit26@bandit:~$ cat /etc/bandit_pass/bandit26
jHdv2ELQh====REDACTED====
plaintext

To exit from the shell, type exit first to exit from bash and then you will reach vim, press esc and then type :q! to exit, if still in more, press the spacebar.

Level 26#

Hint: Good job getting a shell! Now hurry and grab the password for bandit27!

Use the shell from the previous level to continue.

Level 27#

Hint: There is a git repository at ssh://bandit27-git@bandit.labs.overthewire.org/home/bandit27-git/repo via the port 2220. The password for the user bandit27-git is the same as for the user bandit27.
From your local machine (not the OverTheWire machine!), clone the repository and find the password for the next level. This needs git installed locally on your machine.

❯ cd repo 
❯ ls -la          
drwxr-xr-x@  - neo 27 Jul 00:44 .git/
.rw-r--r--@ 68 neo 27 Jul 00:44 README
❯ cat README 
The password to the next level is: y8Yd2ssKc====REDACTED====
plaintext

Level 28#

Hint: There is a git repository at ssh://bandit28-git@bandit.labs.overthewire.org/home/bandit28-git/repo via the port 2220. The password for the user bandit28-git is the same as for the user bandit28.
From your local machine (not the OverTheWire machine!), clone the repository and find the password for the next level. This needs git installed locally on your machine.

Checking git logs

Checking out to prev commit

❯ git checkout 2678cfadd8f2a347bc23e1ea491f702e5b184709
❯ git status                                           
HEAD detached at 2678cfa
nothing to commit, working tree clean
❯ cat README.md
# Bandit Notes
Some notes for level29 of bandit.

## credentials

- username: bandit29
- password: Em7eGtqaMyS====REDACTED====
plaintext

Level 29#

Hint: There is a git repository at ssh://bandit29-git@bandit.labs.overthewire.org/home/bandit29-git/repo via the port 2220. The password for the user bandit29-git is the same as for the user bandit29.
From your local machine (not the OverTheWire machine!), clone the repository and find the password for the next level. This needs git installed locally on your machine.

Let’s check git properties

❯ git log --oneline                                                                                 
b607fba (HEAD -> master, origin/master, origin/HEAD) fix username
84c16f8 initial commit of README.md
❯ git branch -a
* master
  remotes/origin/HEAD -> origin/master
  remotes/origin/dev
  remotes/origin/master
  remotes/origin/sploits-dev
plaintext

There’s a dev branch. Let’s check it out:

Level 30#

Hint: There is a git repository at ssh://bandit30-git@bandit.labs.overthewire.org/home/bandit30-git/repo via the port 2220. The password for the user bandit30-git is the same as for the user bandit30.
From your local machine (not the OverTheWire machine!), clone the repository and find the password for the next level. This needs git installed locally on your machine.

❯ cd bandit30_repo
❯ ls              
README.md
❯ cat README.md          
just an epmty file... muahaha
❯ git log --oneline                                                                                 
929c564 (HEAD -> master, origin/master, origin/HEAD) initial commit of README.md
❯ git branch -a     
* master
  remotes/origin/HEAD -> origin/master
  remotes/origin/master
❯ git tag    
secret
❯ git show secret       
82NkymblpG====REDACTED====
plaintext

Level 31#

Hint: There is a git repository at ssh://bandit31-git@bandit.labs.overthewire.org/home/bandit31-git/repo via the port 2220. The password for the user bandit31-git is the same as for the user bandit31.
From your local machine (not the OverTheWire machine!), clone the repository and find the password for the next level. This needs git installed locally on your machine.

Edit the .gitignore file and remove the *.txt line. Create a new file named key.txt and add the text May I come in?.

We get the key in the push error message.

Level 32#

Hint: After all this git stuff, it’s time for another escape. Good luck!

❯ ssh bandit32@bandit.labs.overthewire.org -p 2220
...
WELCOME TO THE UPPERCASE SHELL
>> ls
sh: 1: LS: Permission denied
plaintext

When using ssh to get access to the machine, we are greeted with a slightly different shell. So every command we type seems to be made uppercase and executed and thus is not working.
The one thing in Linux that is uppercase is variables. Specifically, the variable $0 has a reference to a shell.
Let’s use it to break out of the uppercase shell:

>> $0
$ whoami
bandit33
$ pwd
/home/bandit32
$ ls -la
total 36
drwxr-xr-x   2 root     root      4096 Jun 24 14:59 .
drwxr-xr-x 150 root     root      4096 Jun 24 15:02 ..
-rw-r--r--   1 root     root       220 Feb 13 12:16 .bash_logout
-rw-r--r--   1 root     root      3851 Jun 24 14:50 .bashrc
-rw-r--r--   1 root     root       807 Feb 13 12:16 .profile
-rwsr-x---   1 bandit33 bandit32 15136 Jun 24 14:59 uppershell
$ cat /etc/bandit_pass/bandit33
u4P2CyPOwPGLe====REDACTED====
plaintext

Level 33#

Hint: At this moment, level 34 does not exist yet.

❯ ssh bandit33@bandit.labs.overthewire.org -p 2220
bandit33@bandit.labs.overthewire.org's password:
Welcome to OverTheWire!
...
  Enjoy your stay!
plaintext

This is the last level.

bandit33@bandit:~$ ls 
README.txt
bandit33@bandit:~$ cat README.txt 
Congratulations on solving the last level of this game!

At this moment, there are no more levels to play in this game. However, we are constantly working
on new levels and will most likely expand this game with more levels soon.
Keep an eye out for an announcement on our usual communication channels!
In the meantime, you could play some of our other wargames.

If you have an idea for an awesome new level, please let us know!
plaintext

Congratulations!! We have completed the Bandit Challenge. 🎉

OTW: Bandit Writeup
https://nahil.xyz/vault/writeups/over-the-wire/bandit/
AuthorNahil Rasheed
Published atJuly 26, 2026
CopyrightCC BY 4.0
DisclaimerThis content is provided strictly for educational purposes only.