OverTheWire is a fantastic website for learning about hacking and cybersecurity. For the first session in my school’s cybersecurity club, we’re getting started with the Bandit box.
Thanks so much to the team at OverTheWire for putting all of this together, and hosting it for free. I hope these solutions may be helpful to you, the reader.
I’ve come to find that there are lots of solutions out there. If mine are not satisfactory, you might also want to check out one of these.
Bandit Solutions
Start here for level 0:
Level 0
Level 1
ls
produces one file: -
Level 2
ls
produces the file spaces in this filename
Level 3
In the directory inhere
there is a hidden file named .hidden
Level 4
ls produces a bunch of data files with dashes in their names.
We can filter through these, but most are garbage.
Let’s use file to see what they are.
-file07
seems like the only interesting one, so let’s look at that.
and there’s the flag
Level 5
We get in the inhere
directory and find a bunch of files called maybehere{numbers}
As given by the prompt, we’re looking for a file that’s:
- human-readable
- 1033 bytes in size
- not executable
We can go through all of them, and cat the output with the following command.
Thus, we find the flag, along with lots of blank files.
Level 6
We know 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
We can just search the entire server for what we are looking for.
(The -print
stuff just gets rid of the permission denied errors.)
We can cat the output of the result of that command:
Level 7
This level has one file: data.txt
This file is over 90 thousand lines long, so it is impossible to parse by hand.
According to the page: The password for the next level is stored in the file data.txt next to the word millionth
Level 8
We find one file named data.txt
and it has one thousand lines of stuff.
The webpage says to find the line that appears only once, which we can do with the following command:
Level 9
There is a data.txt file that contains data. We are instructed to find a string in the file that is prepended by equals signs.
We can do that with the following command:
Level 10
This file has a b64 encoded file called data.txt
Level 11
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
We can use tr
to rotate all characters 13 positions back.
bandit11@bandit:~$ cat data.txt
Gur cnffjbeq vf 5Gr8L4qetPEsPk8htqjhRK8XSP6x2RHh
bandit11@bandit:~$ cat data.txt | tr "$(echo -n {A..Z} {a..z} | tr -d ' ')" "$(echo -n {N..Z} {A..M} {n..z} {a..m} | tr -d ' ')"
The password is JVNBBFSmZwKKOP0XbFXOoW8chDz5yVRv
Level 12
Because we are going to have to do more stuff to this file, we copy it into a temp file.
This file is first compressed as a hexdump, which we have to undo with
This is a gzip file, which we can undo with
That file is compressed with bzip2, which we undo with
We can reuse a previous command because it’s a .gz again.
There are a lot of different levels of compression, but they are all either tar
, bzip2
, or gzip
You can complete this challenge with:
The end result is
The password is wbWdlBxEir4CaE8LaPhauuOo6pwRmrDw
Level 13
This level has a sshkey that we need to use for the next level.
Open another terminal. We can use scp
to download this file, and use it for the next one.
We have to trust the key we downloaded:
chmod 400 sshkey.private
and then use it to login:
Level 14
After we are in from the previous problem, we can just cat the password file to port 3000
Level 15
We have to pass the current password to Port 30001 on localhost using SSL encryption.
I can tell that they have openssl on the system
This is a great cheatsheet for openssl.
Enter the current password into the openssl connection:
Level 16
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.
We have a range of ports, and I want to scan.
Nmap it is. Here’s a good guide if you’re not familiar: https://hackertarget.com/nmap-cheatsheet-a-quick-reference-guide/
bandit16@bandit:~$ nmap -p 31000-32000 localhost
Starting Nmap 7.40 ( https://nmap.org ) at 2020-07-06 00:11 CEST
Nmap scan report for localhost (127.0.0.1)
Host is up (0.00023s latency).
Not shown: 996 closed ports
PORT STATE SERVICE
31046/tcp open unknown
31518/tcp open unknown
31691/tcp open unknown
31790/tcp open unknown
31960/tcp open unknown
Nmap done: 1 IP address (1 host up) scanned in 0.09 seconds
Now, instead of 1000 ports to try, I have five.
Then find out which of those speak SSL 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.
bandit16@bandit:~$ openssl s_client -connect localhost:31046
(did not work)
I bet there’s an automated way of checking these, but there were only five so I didn’t bother researching it. I just tried to connect to each one.
bandit16@bandit:~$ openssl s_client -connect localhost:31790
[connection boilerplate removed]
JQttfApK4SeyHwDlI9SXGR50qclOAil1
Correct!
-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEAvmOkuifmMg6HL2YPIOjon6iWfbp7c3jx34YkYWqUH57SUdyJ
imZzeyGC0gtZPGujUSxiJSWI/oTqexh+cAMTSMlOJf7+BrJObArnxd9Y7YT2bRPQ
Ja6Lzb558YW3FZl87ORiO+rW4LCDCNd2lUvLE/GL2GWyuKN0K5iCd5TbtJzEkQTu
DSt2mcNn4rhAL+JFr56o4T6z8WWAW18BR6yGrMq7Q/kALHYW3OekePQAzL0VUYbW
JGTi65CxbCnzc/w4+mqQyvmzpWtMAzJTzAzQxNbkR2MBGySxDLrjg0LWN6sK7wNX
x0YVztz/zbIkPjfkU1jHS+9EbVNj+D1XFOJuaQIDAQABAoIBABagpxpM1aoLWfvD
KHcj10nqcoBc4oE11aFYQwik7xfW+24pRNuDE6SFthOar69jp5RlLwD1NhPx3iBl
J9nOM8OJ0VToum43UOS8YxF8WwhXriYGnc1sskbwpXOUDc9uX4+UESzH22P29ovd
d8WErY0gPxun8pbJLmxkAtWNhpMvfe0050vk9TL5wqbu9AlbssgTcCXkMQnPw9nC
YNN6DDP2lbcBrvgT9YCNL6C+ZKufD52yOQ9qOkwFTEQpjtF4uNtJom+asvlpmS8A
vLY9r60wYSvmZhNqBUrj7lyCtXMIu1kkd4w7F77k+DjHoAXyxcUp1DGL51sOmama
+TOWWgECgYEA8JtPxP0GRJ+IQkX262jM3dEIkza8ky5moIwUqYdsx0NxHgRRhORT
8c8hAuRBb2G82so8vUHk/fur85OEfc9TncnCY2crpoqsghifKLxrLgtT+qDpfZnx
SatLdt8GfQ85yA7hnWWJ2MxF3NaeSDm75Lsm+tBbAiyc9P2jGRNtMSkCgYEAypHd
HCctNi/FwjulhttFx/rHYKhLidZDFYeiE/v45bN4yFm8x7R/b0iE7KaszX+Exdvt
SghaTdcG0Knyw1bpJVyusavPzpaJMjdJ6tcFhVAbAjm7enCIvGCSx+X3l5SiWg0A
R57hJglezIiVjv3aGwHwvlZvtszK6zV6oXFAu0ECgYAbjo46T4hyP5tJi93V5HDi
Ttiek7xRVxUl+iU7rWkGAXFpMLFteQEsRr7PJ/lemmEY5eTDAFMLy9FL2m9oQWCg
R8VdwSk8r9FGLS+9aKcV5PI/WEKlwgXinB3OhYimtiG2Cg5JCqIZFHxD6MjEGOiu
L8ktHMPvodBwNsSBULpG0QKBgBAplTfC1HOnWiMGOU3KPwYWt0O6CdTkmJOmL8Ni
blh9elyZ9FsGxsgtRBXRsqXuz7wtsQAgLHxbdLq/ZJQ7YfzOKU4ZxEnabvXnvWkU
YOdjHdSOoKvDQNWu6ucyLRAWFuISeXw9a/9p7ftpxm0TSgyvmfLF2MIAEwyzRqaM
77pBAoGAMmjmIJdjp+Ez8duyn3ieo36yrttF5NSsJLAbxFpdlc1gvtGCWW+9Cq0b
dxviW8+TFVEBl1O4f7HVm6EpTscdDxU+bCXWkfjuRb7Dy9GOtt9JPsX8MBTakzh3
vBgsyi/sN3RqRBcGU40fOoZyfAMT8s1m/uYv52O6IgeuZ/ujbjY=
-----END RSA PRIVATE KEY-----
closed
bandit16@bandit:~$
Level 17
Copy the RSA key from last time into a file like level16ssh.private
Doing ls
we see 2 files: passwords.new
and passwords.old
.
This might seem like a completely secure way to save passwords, but apparently there is a weakness. /s
the password for the next level is in
passwords.new
and is the only line that has been changed betweenpasswords.old
and passwords.new
each one has 100 lines, which is way too many to do by hand.
hga5tuuCLF6fFzUpnagiMN8ssu9LFrdg
is the password. easy clap gg
Level 18
We can look around the home directory with the past user.
There is a .bash_logout
function that immediately logs you out if you are trying to log in, if "$SHLVL" = 1
.
We could probably do stuff with that, but why bother. We can just cat the file.
Here is what the whole level looks like.
sarge@sargebox >> ~$ ssh bandit18@bandit.labs.overthewire.org -p 2220 -t 'cat readme; bash -login'
This is a OverTheWire game server. More information on http://www.overthewire.org/wargames
bandit18@bandit.labs.overthewire.org's password:
awhqfNnAbc1naukrpqDYcF95h7HoMTrC
Byebye !
Connection to bandit.labs.overthewire.org closed.
Level 19
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.
as far as I can tell, I just want to cat /etc/bandit_pass/bandit20
I can use the setuid to do that.
that wasn’t too hard now, was it.
Here’s a video with more information on SUID and SGID
Level 20
For this one we basically need to use netcat to listen for a port, and establish a connection.
Shell 1:
bandit20@bandit:~$ nc -lvvp 8888
listening on [any] 8888 ...
connect to [127.0.0.1] from localhost [127.0.0.1] 42856
VxCazJaVykI6W36BkBU0mJTCM8rR95XT
NvEJF7oVjkddltPSrdKEFOllh9V1IBcq
sent 33, rcvd 33
Shell 2:
bandit20@bandit:~$ ./suconnect 8888
Read: VxCazJaVykI6W36BkBU0mJTCM8rR95XT
Password matches, sending next password
note that the -p is important with netcat. otherwise it will refuse to connect.
Level 21
Just to mention, this level was completed on my cellphone with a portable keyboard and the android app Termux. The portable keyboard works well.
We are told on the challenge page to look into the cronjobs on the system.
In bandit22, we see that it is running a shell script in /usr/bin
In this shell script, we see that it is sending the password to this level to /tmp/t7O6lds9S0RqQh9aMcz6ShpAoZKF7fgv
Level 22
According to the page:
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 find that /etc/cron.d/cronjob_bandit23
is running /usr/bin/cronjob_bandit23.sh
This is that script, with my comments
To be clear, you just need to run:
Level 23
Notes from 2020
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. This is a very big step and you should be proud of yourself when you beat this level!
NOTE 2: Keep in mind that your shell script is removed once executed, so you may want to keep a copy around…
/etc/cron.d/cronjob_bandit24
is running /usr/bin/cronjob_bandit24.sh
, which is pasted below.
i created a temporary directory in /tmp/zsarge
, in which i included the following script (named script.sh):
(you could also use mktemp -d
if you want. You have permission to make any directory in /tmp
)
and on a separate terminal instance, i started nc -lvvp 8899
Basically, I am running a shell script that reads the flag and passes it to a separate netcat connection, because writing permissions were getting weird.
I ran this all with:
The key solution here is to get a bash script to echo the password into something that is readable from another perspective. I imagine you could use a file readable by all users, but I’ll use a network connection, because I know it’ll work.
Open one shell as bandit23, and run:
Open another shell as bandit23, and run:
Then, after the minute turns, you should see your other terminal update with:
And thus you get the password.
Level 24
The prompt is:
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
Well, that seems relatively straightforward.
I kinda wish that Ruby was installed, but I’ll do my solution in Python:
Going in reverse saves a significant amount of time.
Just fyi, afterwards, I found another solution that used bash instead of Python.
Level 25
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.
Hmm, interesting. Here, we are just given one file:
We can copy it onto our local machine:
Let’s check what bandit26 is using as a shell:
Neat. So, it’s just using more
to read the file from text.txt
, has some nice little ascii art:
_ _ _ _ ___ __
| | | (_) | |__ \ / /
| |__ __ _ _ __ __| |_| |_ ) / /_
| '_ \ / _` | '_ \ / _` | | __| / / '_ \
| |_) | (_| | | | | (_| | | |_ / /| (_) |
|_.__/ \__,_|_| |_|\__,_|_|\__|____\___/
But, on super small screens, more
allows to scroll through each line individually (and also enter shell commands), so you’re going to need to either scrunch up your terminal super , so it’s only one or two lines tall.
You should get something like this:
_ _ _ _ ___ __
| | | (_) | |__ \ / /
| |__ __ _ _ __ __| |_| |_ ) / /_
--More--(50%)
And now you can enter Vim by pressing v
. From here on, you can make the screen bigger without worry.
In Vim, you can enter:
And you should see:
c7GvcKlw9mC7aUQaPx7nwFstuAIBw1o1
Remember not to exit this shell. You’ll want it for later.
You can also enter:
to enter bash.
Level 26
Let’s investigate bandit26:
Level 27
There is a git repository at
ssh://bandit27-git@localhost/home/bandit27-git/repo
via the port2220
. The password for the userbandit27-git
is the same as for the userbandit27
.Clone the repository and find the password for the next level.
Ok, seems relatively straightforward:
Level 28
Level 29
There is a git repository at ssh://bandit29-git@localhost/home/bandit29-git/repo via the port 2220. The password for the user bandit29-git is the same as for the user bandit29.
Clone the repository and find the password for the next level.
Level 30
Pretty similar:
There is a git repository at
ssh://bandit30-git@localhost/home/bandit30-git/repo
via the port2220
. The password for the userbandit30-git
is the same as for the userbandit30
.Clone the repository and find the password for the next level.
Level 31
There is a git repository at
ssh://bandit31-git@localhost/home/bandit31-git/repo
via the port2220
. The password for the userbandit31-git
is the same as for the userbandit31
.Clone the repository and find the password for the next level.
git gud
is not a command 😔
bandit31@bandit:~$ cd $(mktemp -d)
bandit31@bandit:/tmp/tmp.BE1pSk6O9E$ git clone ssh://bandit31-git@localhost:2220/home/bandit31-git/repo
Cloning into 'repo'...
The authenticity of host '[localhost]:2220 ([127.0.0.1]:2220)' can't be established.
ED25519 key fingerprint is SHA256:C2ihUBV7ihnV1wUXRb4RrEcLfXC5CXlhmAAM/urerLY.
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Could not create directory '/home/bandit31/.ssh' (Permission denied).
Failed to add the host to the list of known hosts (/home/bandit31/.ssh/known_hosts).
_ _ _ _
| |__ __ _ _ __ __| (_) |_
| '_ \ / _` | '_ \ / _` | | __|
| |_) | (_| | | | | (_| | | |_
|_.__/ \__,_|_| |_|\__,_|_|\__|
This is an OverTheWire game server.
More information on http://www.overthewire.org/wargames
bandit31-git@localhost's password:
remote: Enumerating objects: 4, done.
remote: Counting objects: 100% (4/4), done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 4 (delta 0), reused 0 (delta 0), pack-reused 0
Receiving objects: 100% (4/4), done.
bandit31@bandit:/tmp/tmp.BE1pSk6O9E$ ls
repo
bandit31@bandit:/tmp/tmp.BE1pSk6O9E$ cd repo
bandit31@bandit:/tmp/tmp.BE1pSk6O9E/repo$ ls
README.md
bandit31@bandit:/tmp/tmp.BE1pSk6O9E/repo$ cat README.md
This time your task is to push a file to the remote repository.
Details:
File name: key.txt
Content: 'May I come in?'
Branch: master
bandit31@bandit:/tmp/tmp.BE1pSk6O9E/repo$ echo 'May I come in?' > key.txt
bandit31@bandit:/tmp/tmp.BE1pSk6O9E/repo$ git add key.txt -f
bandit31@bandit:/tmp/tmp.BE1pSk6O9E/repo$ git status
On branch master
Your branch is up to date with 'origin/master'.
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: key.txt
bandit31@bandit:/tmp/tmp.BE1pSk6O9E/repo$ git commit -m "solve 31"
[master 9f5f592] solve 31
1 file changed, 1 insertion(+)
create mode 100644 key.txt
bandit31@bandit:/tmp/tmp.BE1pSk6O9E/repo$ git push
The authenticity of host '[localhost]:2220 ([127.0.0.1]:2220)' can't be established.
ED25519 key fingerprint is SHA256:C2ihUBV7ihnV1wUXRb4RrEcLfXC5CXlhmAAM/urerLY.
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Could not create directory '/home/bandit31/.ssh' (Permission denied).
Failed to add the host to the list of known hosts (/home/bandit31/.ssh/known_hosts).
_ _ _ _
| |__ __ _ _ __ __| (_) |_
| '_ \ / _` | '_ \ / _` | | __|
| |_) | (_| | | | | (_| | | |_
|_.__/ \__,_|_| |_|\__,_|_|\__|
This is an OverTheWire game server.
More information on http://www.overthewire.org/wargames
bandit31-git@localhost's password:
Enumerating objects: 4, done.
Counting objects: 100% (4/4), done.
Delta compression using up to 2 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 321 bytes | 321.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
remote: ### Attempting to validate files... ####
remote:
remote: .oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.
remote:
remote: Well done! Here is the password for the next level:
remote: rmCBvG56y58BXzv98yZGdO7ATVL5dW8y
remote:
remote: .oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.
remote:
To ssh://localhost:2220/home/bandit31-git/repo
! [remote rejected] master -> master (pre-receive hook declined)
error: failed to push some refs to 'ssh://localhost:2220/home/bandit31-git/repo'
Level 32
It’s worth noting that even with -t
(i.e. ssh bandit32@bandit.labs.overthewire.org -p 2220 -t /bin/bash
), you still get put in the “UPPERCASE SHELL”
WELCOME TO THE UPPERCASE SHELL
>> ls
sh: 1: LS: Permission denied
Ok, this took me a bit of researching, but apparently $0
is a standard way of escaping from restricted shells:
>> $0
$ ls
uppershell
$ pwd
/home/bandit32
$ cat /etc/bandit_pass/bandit33
odHo63fHiFqcWWJG9rLiLDtPm45KzUKy
Read more here:
Level 33
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!