This is the write-up of the OverTheWire Bandit wargame levels 0-20.
The goal of this level is for you to log into the game using SSH. The host to which you need to connect is bandit.labs.overthewire.org, on port 2220. The username is bandit0 and the password is bandit0. Once logged in, go to the Level 1 page to find out how to beat Level 1
First we ssh
into their machine using this command.
ssh -p 2220 bandit0@bandit.labs.overthewire.org
The password is bandit0
as provided in the problem statement
After this, we simply cat
out the readme
file which contains the password for the next level. But instead of directly hopping to the next level, let us tinker with the machine a bit.
We don't have write permissions in the home directory. So let us first find out the directories in which we have write permission. This will be useful for later stages.
For this we use the powerful find
command.
find / -type d -writable -print
This lists out all the directories in which we can write, the most noticeable one being the /tmp
directory
The password for the next level is stored in a file called - located in the home directory
The password is stored in the file named -
. We just need to cat
out its contents. But as -
is a special character in bash we will need a way to escape it. A visit to StackOverflow suggests that we can give the dashed filenames as arguments to a command preceded by --
to escape them like this
command -- $dashed_filename
This should work for most commands but apparently it does not work with cat
.
Another way is to simply rename the file.
mv -- - /tmp/passwd.txt
Well it turns out that this doesn't work either as we are not allowed to move the file.
Let's try cp
then
cp -- - /tmp/passwd.txt
And boom! It worked!
Now we simply cat
out /tmp/passwd.txt
.
The password for the next level is stored in a file called spaces in this filename located in the home directory
This one is simple. Just use quotes to escape the spaces in the filename.
cat "spaces in this filename"
The password for the next level is stored in a hidden file in the inhere directory.
Hmm hidden file? Let's try ls -al
.
bandit3@bandit:~/inhere$ ls -al
total 12
drwxr-xr-x 2 root root 4096 May 7 2020 .
drwxr-xr-x 3 root root 4096 May 7 2020 ..
-rw-r----- 1 bandit4 bandit3 33 May 7 2020 .hidden
And there we have it our .hidden
file. Simply cat
it out to get the password.
The password for the next level is stored in the only human-readable file in the inhere directory. Tip: if your terminal is messed up, try the “reset” command.
First let us do ls -al
bandit4@bandit:~/inhere$ ls -al
total 48
drwxr-xr-x 2 root root 4096 May 7 2020 .
drwxr-xr-x 3 root root 4096 May 7 2020 ..
-rw-r----- 1 bandit5 bandit4 33 May 7 2020 -file00
-rw-r----- 1 bandit5 bandit4 33 May 7 2020 -file01
-rw-r----- 1 bandit5 bandit4 33 May 7 2020 -file02
-rw-r----- 1 bandit5 bandit4 33 May 7 2020 -file03
-rw-r----- 1 bandit5 bandit4 33 May 7 2020 -file04
-rw-r----- 1 bandit5 bandit4 33 May 7 2020 -file05
-rw-r----- 1 bandit5 bandit4 33 May 7 2020 -file06
-rw-r----- 1 bandit5 bandit4 33 May 7 2020 -file07
-rw-r----- 1 bandit5 bandit4 33 May 7 2020 -file08
-rw-r----- 1 bandit5 bandit4 33 May 7 2020 -file09
An interesting observation is that all the relevant files are of the same size. This implies that they must contain the same number of characters / bytes. Given this we can use the strings
command to get the human readable characters from each of the files and then simply pick the one with the greatest number of such characters.
bandit4@bandit:~/inhere$ for f in `ls`; do
> echo `strings -- $f`
> done
!TQO
4c7u4lp455w0rdr3d4c73d
And there we have it, our password.
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
This one is a direct application of the find
command.
Just executing with the file size gives the result.
bandit5@bandit:~/inhere$ find . -type f -size 1033c -exec ls {} \;
./maybehere07/.file2
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
This once again is a direct application of the find
command.
Simply executing find / -group bandit6 -user bandit7
gives us the required file /var/lib/dpkg/info/bandit7.password
.
The password for the next level is stored in the file data.txt next to the word millionth
This one is just grep
bandit7@bandit:~$ cat data.txt | grep millionth
millionth 4c7u4lp455w0rdr3d4c73d
The password for the next level is stored in the file data.txt and is the only line of text that occurs only once
We need to find the only non-repeating line in the file data.txt
. Let's first do cat data.txt
.
bandit8@bandit:~$ cat data.txt
VkBAEWyIibVkeURZV5mowiGg6i3m7Be0
zdd2ctVveROGeiS2WE3TeLZMeL5jL7iM
sYSokIATVvFUKU4sAHTtMarfjlZWWj5i
---several hundred lines later--
gqyF9CW3NNIiGW27AtWVNPqp3i1fxTMY
flyKxCbHB8uLTaIB5LXqQNuJj3yj00eh
w4zUWFGTUrAAh8lNkS8gH3WK2zowBEkA
Ah! Looks terrible. So let's do this again but sort the output. Now it becomes much easier to find the odd one out by just skimming through the lines.
bandit8@bandit:~$ cat data.txt | sort
07KC3ukwX7kswl8Le9ebb3H3sOoNTsR2
07KC3ukwX7kswl8Le9ebb3H3sOoNTsR2
07KC3ukwX7kswl8Le9ebb3H3sOoNTsR2
------------snip----------------
UjsVbcqKeJqdCZQCDMkzv6A9X7hLbNE4
UjsVbcqKeJqdCZQCDMkzv6A9X7hLbNE4
UjsVbcqKeJqdCZQCDMkzv6A9X7hLbNE4
UsvVyFSfZZW4c7u4lp455w0rdr3d4c73d <----gotcha!
UVnZvhiVQECraz5jl8U14sMVZQhjuXia
UVnZvhiVQECraz5jl8U14sMVZQhjuXia
UVnZvhiVQECraz5jl8U14sMVZQhjuXia
------------snip----------------
zdd2ctVveROGeiS2WE3TeLZMeL5jL7iM
zdd2ctVveROGeiS2WE3TeLZMeL5jL7iM
zdd2ctVveROGeiS2WE3TeLZMeL5jL7iM
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.
This one is direct application of strings
. To refine the results given by strings
we use an additional grep
.
bandit9@bandit:~$ strings data.txt | grep "="
========== the*2i"4
=:G e
========== password
<I=zsGi
Z)========== is
A=|t&E
Zdb=
c^ LAh=3G
*SF=s
&========== truKL4c7u4lp455w0rdr3d4c73d
S=A.H&^
The password for the next level is stored in the file data.txt, which contains base64 encoded data
This one is a direct application of the base64
program.
bandit10@bandit:~$ base64 --decode data.txt
The password is 4c7u4lp455w0rdr3d4c73d
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
This one is a simple Rot13 cipher.
bandit11@bandit:~$ cat data.txt
Gur cnffjbeq vf 4p7h4yc455j0eqe3q4p73q
Do it by hand or use an online tool.
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. For this level it may be useful to create a directory under /tmp in which you can work using mkdir. For example: mkdir /tmp/myname123. Then copy the datafile using cp, and rename it using mv (read the manpages!)
First let us create a directory as instructed.
bandit12@bandit:~$ mkdir /tmp/tmp
Now we need to reverse the hexdump. This can be done by the xxd
command as follows
bandit12@bandit:~$ cat data.txt | xxd -r > /tmp/tmp/a
Now let's use the file command to figure out what type of file this is.
bandit12@bandit:/tmp/tmp$ file a
a: gzip compressed data, was "data2.bin", last modified: Thu May 7 18:14:30 2020, max compression, from Unix
This is a compressed gzip file. Let's decompress it.
bandit12@bandit:/tmp/tmp$ mv a a.gz
bandit12@bandit:/tmp/tmp$ gzip -d a.gz
bandit12@bandit:/tmp/tmp$ file a
a: bzip2 compressed data, block size = 900k
Oh! It turned out to be another compressed file. Let's decompress it again.
bandit12@bandit:/tmp/tmp$ mv a a.bz2
bandit12@bandit:/tmp/tmp$ bzip2 -d a.bz2
bandit12@bandit:/tmp/tmp$ file a
a: gzip compressed data, was "data4.bin", last modified: Thu May 7 18:14:30 2020, max compression, from Unix
Again?!
Many, many decompressions later We finally get a plain-text file.
bandit12@bandit:/tmp/tmp$ file a
a: ASCII text
bandit12@bandit:/tmp/tmp$ cat a
The password is 4c7u4lp455w0rdr3d4c73d
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. Note: localhost is a hostname that refers to the machine you are working on
We simply need to ssh into the next level using the given private sshkey.
First we copy the private sshkey to our local machine, set appropriate permissions for a private sshkey, i.e., chmod 600 sshkey.private
and then ssh into the next level using ssh -p 2220 -i sshkey.private bandit14@bandit.labs.overthewire.org
The password for the next level can be retrieved by submitting the password of the current level to port 30000 on localhost.
As given in the previous problem (Bandit 13), we can now get the password for the current level by simply cat
ing out /etc/bandit_pass/bandit14
.
We can submit the password using netcat.
bandit14@bandit:~$ nc localhost 30000
lvl144c7u4lp455w0rdr3d4c73d
Correct!
lvl154c7u4lp455w0rdr3d4c73d
The password for the next level can be retrieved by submitting the password of the current level to port 30001 on localhost using SSL encryption.
We simply need to connect to the port using ssl encryption. This can be done with the ncat
command as follows
bandit15@bandit:~$ ncat --ssl localhost 30001
lvl154c7u4lp455w0rdr3d4c73d
Correct!
lvl164c7u4lp455w0rdr3d4c73d
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 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
We simply do an nmap
scan of the server localhost with port range 31000-32000
bandit16@bandit:~$ nmap -p 31000-32000 localhost
Starting Nmap 7.40 ( https://nmap.org ) at 2021-04-17 15:42 CEST
Nmap scan report for localhost (127.0.0.1)
Host is up (0.00042s 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.10 seconds
Now we simply try connecting to each of these ports with ncat --ssl localhost $port_num
. One of these ports will provide us with the private sshkey to ssh into the next level.
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
This one is a direct application of the diff
command.
bandit17@bandit:~$ diff passwords.old passwords.new
42c42
< old4c7u4lp455w0rdr3d4c73d
---
> new4c7u4lp455w0rdr3d4c73d
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.
As mentioned in the problem statement, if we simply try to ssh into the level, we are immediately disconnected due to the execution of the .bashrc
script.
The .bashrc
script is executed when a new bash instance is started. This also happens when we ssh into a machine as a "pseudo-terminal" is allocated.
We can disable this "pseudo-terminal allocation" and simply send the command we wish to execute directly on the other side by using the -t
flag with the ssh
command.
ssh -t -p 2220 bandit18@bandit.labs.overthewire.org cat readme
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.
First we notice that there is an executable provided to us. Executing it without any arguments gives:
bandit19@bandit:~$ ./bandit20-do
Run a command as another user.
Example: ./bandit20-do id
So it says that it will execute the command we feed into it as another user. Let's check if that is actually the case.
bandit19@bandit:~$ whoami
bandit19
bandit19@bandit:~$ ./bandit20-do whoami
bandit20
So it runs the command we give to it as if it were being run by the user bandit20. Cool!
Running ./bandit20-do cat /etc/bandit_pass/bandit20
will yield the password.
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).
Technically, we just need to listen on a port and when a connection is established with the provided binary, we need to send the current level's password. But in order to do this, two terminal windows (or instances) are required: first we will need to execute netcat on one window, then execute the binary on the second window, and then send the password through the first window again. But we only have access to a single terminal instance. How can we achieve this?
Fortunately, there exists this screen
command which enables us to do so from within a single terminal instance.
First we enter in a new screen-instance by executing screen
. This will correspond to our first window. In this "window" we execute
bandit20@bandit:~$ nc -vlp 1234
listening on [any] 1234 ...
Then we "detach" this screen by pressing "Ctrl-A" followed by d.
Next, we create another screen-instance by again executing screen
.
Now in this window we execute
bandit20@bandit:~$ ./suconnect 1234
After that we "detach" this window by pressing "Ctrl-A" followed by d as before.
At this point we have two different windows. Let us list them.
bandit20@bandit:~$ screen -ls
There are screens on:
11167.pts-66.bandit (04/17/2021 06:18:26 PM) (Detached)
10707.pts-66.bandit (04/17/2021 06:17:40 PM) (Detached)
2 Sockets in /run/screen/S-bandit20.
We need to recover the window running nc. To do this, we note the pid of that window (the one which was instantiated first) and execute
screen -r 10707.pts-66.bandit
and we are teleported to this window
bandit20@bandit:~$ nc -vlp 1234
listening on [any] 1234 ...
connect to [127.0.0.1] from localhost [127.0.0.1] 54738
Finally we just type out the current level's password and we will receive the next level's password.
bandit20@bandit:~$ nc -vlp 1234
listening on [any] 1234 ...
connect to [127.0.0.1] from localhost [127.0.0.1] 54738
lvl204c7u4lp455w0rdr3d4c73d <--sent
lvl214c7u4lp455w0rdr3d4c73d <--received