Bandit
Write-up.
General
The general concept is that in level x
you will find the password for level x + 1
. We will connect to the hosts using ssh
.
An ssh
connection can be established using ssh username@host
from the command line if the default port is 22, else another port can be specified using the -p
flag.
When a password has been found for the next level, the procedure is to terminate the current ssh connection using the exit
command and connect to the next level with the new username, e.g., bandit7
, and the password which has just been found.
Level 0
SSH into the host with the username and password being bandit0
ssh [email protected] -p 2220
Level 0 -> Level 1
Doing a ls
after the connection is established will reveal a readme
file. Get the content of that file using e.g., cat readme
and the password for level 1 should be achieved being boJ9jbbUNNfktd78OOpsqOltutMc3MY1
.
Level 1 -> Level 2
After connecting to level 1, doing a ls
will reveal something named -
. In order to point to a file named as such, one must refer to the full path.
Doing file ./-
will return ./-: ASCII text
, hence we can get the content using cat ./-
which gives us the password CV1DtqXWVFXTvM2F0k09SHz0YwRINYA9
.
Level 2 -> Level 3
After connecting to level 2, ls
will return something called spaces in this filename
, and if we utilize auto-completion using the TAB button, the spaces will be escaped with \
automatically.
bandit2@bandit:~$ file spaces\ in\ this\ filename
spaces in this filename: ASCII text
As per above we can just cat spaces\ in\ this\ filename
, which returns UmHadQclWmgdLOKQ3YNgjWxGoRMb5luK
for level 3.
Level 3 -> Level 4
After connecting to level 3, ls
will return a folder called inhere
. Enter the folder by cd inhere
.
Doing a ls
inside that folder seems to do nothing, hence a ls -a
might be a good idea to show hidden files as well. This reveals a file named .hidden
.
From here we can just cat .hidden
to get the password for level 4, pIwrPrtPN36QITSp3EQaw936yaFoFgAB
.
Level 4 -> Level 5
After connecting to level 4, ls
will again return a folder called inhere
. This folder seems to contain multiple files with the names -file00
, -file01
, ...
, -file09
. To narrow it down, we can try and use the file
command on all files, which can be done using an *
. As the files start with an -
, we must remember to point to the full location.
bandit4@bandit:~/inhere$ file ./*
./-file00: data
./-file01: data
./-file02: data
./-file03: data
./-file04: data
./-file05: data
./-file06: data
./-file07: ASCII text
./-file08: data
./-file09: data
cat ./-file07
gives us the password for level 5, koReBOKuIDDepwhWk7jZC0RTdopnAYKh
.
Level 5 -> Level 6
We know the following about the file
human-readable
1033 bytes in size
a non-binary
We are again presented to a folder named inhere
. Within that folder, there are multiple folders, maybehere00
, maybehere01
,...
, maybehere19
.
Utilizing the find
command, the correct file is found rather easily
bandit5@bandit:~/inhere$ find . -size 1033c
./maybehere07/.file2
The c
indicates the unit, which in this case is for bytes. Another example could have been k
for kilobytes.
cat maybehere07/.file2
reveals the password for level 6, DXjZPULLxYr17uwoI01bNLQbtFemEgo7
.
Level 6 -> Level 7
We know the following about the file
it is somewhere on the server
owned by user bandit7
owned by group bandit6
33 bytes in size
It is necessary to call find / ...
, as we don't know exactly where to look on the server, hence we start at the root of the machine.
bandit6@bandit:~$ find / -user bandit7 -group bandit6 -size 33c
find: ‘/root’: Permission denied
find: ‘/home/bandit28-git’: Permission denied
find: ‘/home/bandit30-git’: Permission denied
...
...
...
find: ‘/var/tmp’: Permission denied
find: ‘/var/lib/apt/lists/partial’: Permission denied
find: ‘/var/lib/polkit-1’: Permission denied
/var/lib/dpkg/info/bandit7.password
find: ‘/var/log’: Permission denied
find: ‘/var/cache/apt/archives/partial’: Permission denied
The information given is used to find the appropriate file. In between all the clutter we see /var/lib/dpkg/info/bandit7.password
, which contains the password for level 7, HKBPTKQnIay4Fw76bEy8PVxKEDQRKTzs
.
Level 7 -> Level 8
We know the password is next to the word millionth
in the file data.txt
, hence grep
will do the trick.
bandit7@bandit:~$ grep millionth data.txt
millionth cvX2JJa4CFALtqS87jk27qwqGhBM9plV
Leaving us with the password for level 8, cvX2JJa4CFALtqS87jk27qwqGhBM9plV
.
Level 8 -> Level 9
We know the password is the only line that occurs once in the file data.txt
. The approach here is to first sort the file and then find unique lines.
bandit8@bandit:~$ sort data.txt | uniq -u
UsvVyFSfZZWbi6wgC7dAFyFuR6jQQUhR
Revealing the password for level 9, UsvVyFSfZZWbi6wgC7dAFyFuR6jQQUhR
.
Level 9 -> Level 10
We know the password is stored in the file data.txt
in one of the few human-readable strings, preceded by several =
characters.
strings
will find and print human-readable strings in a file, and as data.txt
is a binary, we cannot rely 100% on grep
.
bandit9@bandit:~$ strings data.txt | grep ==
========== the*2i"4
========== password
Z)========== is
&========== truKLdjsbJ5g7yyJ2X2R0o3a5HQJFuLk
There we have the password for level 10, truKLdjsbJ5g7yyJ2X2R0o3a5HQJFuLk
.
Level 10 -> Level 11
We know the password is stored in the file data.txt
which contains base64 encoded data. Decoding the data must then reveal the password
bandit10@bandit:~$ base64 -d data.txt
The password is IFukwKGsFW8MOq3IRFqrxE1hxTNEbUPR
Revealing the password for level 11, IFukwKGsFW8MOq3IRFqrxE1hxTNEbUPR
.
Level 11 -> Level 12
We know all lowercase a-z
and uppercase A-Z
have been rotated 13 positions, hence this smells like ROT13
. This means that an a
becomes a n
, b
becomes an o
and so on. The pattern can be specified as arguments to tr
which will then do the translation. However tr
needs some input text, hence the cat data.txt
being piped into it.
bandit11@bandit:~$ cat data.txt | tr 'a-zA-Z' 'n-za-mN-ZA-M'
The password is 5Te8Y4drgCRfCx8ugdwuEX8KFC6k2EUu
And the password for level 12 is found, 5Te8Y4drgCRfCx8ugdwuEX8KFC6k2EUu
.
Level 12 -> Level 13
We know the password is stored in the file data.txt
. We also know the file is a hexdump of a file that has been repeatedly compressed. I created a folder at /tmp/bob
to work within as suggested.
cat data.txt
prints a hexdump and file data.txt
just tells us that it contains ASCII text.
First, convert the hexdump back to its binary form by xxd -r data.txt > data_reversed
.
Then find out which type of file data_reversed
is.
bandit12@bandit:/tmp/bob$ file data_reversed
data_reversed: gzip compressed data, was "data2.bin", last modified: Thu May 7 18:14:30 2020, max compression, from Unix
As gunzip
requires the correct file extension, data_reversed
must be renamed to data_reversed.gz
, before it can be unzipped.
bandit12@bandit:/tmp/bob$ mv data_reversed data_reversed.gz
bandit12@bandit:/tmp/bob$ gunzip data_reversed.gz
bandit12@bandit:/tmp/bob$ ls
data_reversed data.txt
We are now left with data_reversed
which we will need to find out which type of file that is.
bandit12@bandit:/tmp/bob$ file data_reversed
data_reversed: bzip2 compressed data, block size = 900k
bandit12@bandit:/tmp/bob$ bunzip2 data_reversed
bunzip2: Can't guess original name for data_reversed -- using data_reversed.out
bunzip2
does not require any file extension, hence it can be unzipped straight away. This leaves us with data_reversed.out
, which we then need to find the type for.
bandit12@bandit:/tmp/bob$ file data_reversed.out
data_reversed.out: gzip compressed data, was "data4.bin", last modified: Thu May 7 18:14:30 2020, max compression, from Unix
bandit12@bandit:/tmp/bob$ mv data_reversed.out data_reversed.gz
bandit12@bandit:/tmp/bob$ gunzip data_reversed.gz
bandit12@bandit:/tmp/bob$ ls
data_reversed data.txt
As it is a gzip
file, the extension must be corrected as mentioned per above, before unzipping is possible. We are now left with a new data_reversed
file, which we again need to find the type for.
bandit12@bandit:/tmp/bob$ file data_reversed
data_reversed: POSIX tar archive (GNU)
bandit12@bandit:/tmp/bob$ mv data_reversed data_reversed.tar
bandit12@bandit:/tmp/bob$ tar -xvf data_reversed.tar
data5.bin
A tar
archive can be decompressed using the -xvf
flag. x
for extract, v
for verbose and f
for file. We now have what seems to be a binary, data5.bin
, which we need to explore further.
bandit12@bandit:/tmp/bob$ file data5.bin
data5.bin: POSIX tar archive (GNU)
bandit12@bandit:/tmp/bob$ tar -xvf data5.bin
data6.bin
Apparently it is just another tar
archive, hence we repeat what we just did and look into the new data6.bin
.
bandit12@bandit:/tmp/bob$ file data6.bin
data6.bin: bzip2 compressed data, block size = 900k
bandit12@bandit:/tmp/bob$ bunzip2 data6.bin
bunzip2: Can't guess original name for data6.bin -- using data6.bin.out
This time we still did not have a binary, but a bzip2
compressed file. Decompressed using bunzip2
, which gives a data6.bin.out
to investigate.
bandit12@bandit:/tmp/bob$ file data6.bin.out
data6.bin.out: POSIX tar archive (GNU)
bandit12@bandit:/tmp/bob$ tar -xvf data6.bin.out
data8.bin
Another tar
archive, hence the same procedure as previously. data8.bin
is up next.
bandit12@bandit:/tmp/bob$ file data8.bin
data8.bin: gzip compressed data, was "data9.bin", last modified: Thu May 7 18:14:30 2020, max compression, from Unix
bandit12@bandit:/tmp/bob$ mv data8.bin data8.gz
bandit12@bandit:/tmp/bob$ gunzip data8.gz
bandit12@bandit:/tmp/bob$ file data8
data8: ASCII text
bandit12@bandit:/tmp/bob$ cat data8
The password is 8ZjyCRiBWFYkneahHwxCv3wb2a1ORpYL
And there we have it, the password for lvl 13, 8ZjyCRiBWFYkneahHwxCv3wb2a1ORpYL
.
See the full history below.
bandit12@bandit:/tmp/bob$ file data_reversed
data_reversed: gzip compressed data, was "data2.bin", last modified: Thu May 7 18:14:30 2020, max compression, from Unix
bandit12@bandit:/tmp/bob$ mv data_reversed data_reversed.gz
bandit12@bandit:/tmp/bob$ gunzip data_reversed.gz
bandit12@bandit:/tmp/bob$ ls
data_reversed data.txt
bandit12@bandit:/tmp/bob$ file data_reversed
data_reversed: bzip2 compressed data, block size = 900k
bandit12@bandit:/tmp/bob$ bunzip2 data_reversed
bunzip2: Can't guess original name for data_reversed -- using data_reversed.out
bandit12@bandit:/tmp/bob$ file data_reversed.out
data_reversed.out: gzip compressed data, was "data4.bin", last modified: Thu May 7 18:14:30 2020, max compression, from Unix
bandit12@bandit:/tmp/bob$ mv data_reversed.out data_reversed.gz
bandit12@bandit:/tmp/bob$ gunzip data_reversed.gz
bandit12@bandit:/tmp/bob$ ls
data_reversed data.txt
bandit12@bandit:/tmp/bob$ file data_reversed
data_reversed: POSIX tar archive (GNU)
bandit12@bandit:/tmp/bob$ mv data_reversed data_reversed.tar
bandit12@bandit:/tmp/bob$ tar -xvf data_reversed.tar
data5.bin
bandit12@bandit:/tmp/bob$ file data5.bin
data5.bin: POSIX tar archive (GNU)
bandit12@bandit:/tmp/bob$ tar -xvf data5.bin
data6.bin
bandit12@bandit:/tmp/bob$ file data6.bin
data6.bin: bzip2 compressed data, block size = 900k
bandit12@bandit:/tmp/bob$ bunzip2 data6.bin
bunzip2: Can't guess original name for data6.bin -- using data6.bin.out
bandit12@bandit:/tmp/bob$ file data6.bin.out
data6.bin.out: POSIX tar archive (GNU)
bandit12@bandit:/tmp/bob$ tar -xvf data6.bin.out
data8.bin
bandit12@bandit:/tmp/bob$ file data8.bin
data8.bin: gzip compressed data, was "data9.bin", last modified: Thu May 7 18:14:30 2020, max compression, from Unix
bandit12@bandit:/tmp/bob$ mv data8.bin data8.gz
bandit12@bandit:/tmp/bob$ gunzip data8.gz
bandit12@bandit:/tmp/bob$ file data8
data8: ASCII text
bandit12@bandit:/tmp/bob$ cat data8
The password is 8ZjyCRiBWFYkneahHwxCv3wb2a1ORpYL
Level 13 -> Level 14
We know the password is stored in /etc/bandit_pass/bandit14
and this file is only readable by user bandit14
. We are also provided with a private SSH key, that can be used to login to the next level.
bandit13@bandit:~$ ls
sshkey.private
We must specify this private key when trying to login to bandit14@localhost
.
ssh -i sshkey.private bandit14@localhost
From here it is just to read the file given in the initial description
bandit14@bandit:~$ cat /etc/bandit_pass/bandit14
4wcYUJFw0k0XLShlDzztnTBHiqxU3b3e
Hence the password for level 14 must be 4wcYUJFw0k0XLShlDzztnTBHiqxU3b3e
.
Level 14 -> Level 15
We have been informed that the password for the next level can be retrieved by submitting the password of the current level to port 30000 on localhost.
I used netcat
for this as follows
bandit14@bandit:~$ netcat localhost 30000
4wcYUJFw0k0XLShlDzztnTBHiqxU3b3e
Correct!
BfMYroe26WYalil77FoDi9qh59eK5xNr
And there we have the password for level 15, BfMYroe26WYalil77FoDi9qh59eK5xNr
.
Level 15 -> Level 16
We know 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, hence the use of openssl s_client
here.
We can echo
a string into openssl
like so
echo BfMYroe26WYalil77FoDi9qh59eK5xNr | openssl s_client -connect localhost:30001 -ign_eof
The flag -ign_eof
will inhibit shutting down the connection when end of input is reached, in other words; it will allow server to send something in return.
The password for lvl 16 is returned, cluFn7wTiGryunymYOu4RcffSxQluehd
.
Level 16 -> Level 17
We know 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 are then told to find out which of these ports have a server listening on them. Then find out which of those speak SSL. Only 1 of the servers will give the correct response.
To find open ports in the provided range,
bandit16@bandit:~$ nmap -p 31000-32000 localhost
Starting Nmap 7.40 ( https://nmap.org ) at 2021-09-16 22:41 CEST
Nmap scan report for localhost (127.0.0.1)
Host is up (0.00025s 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
Now we must focus on these 5 ports. We can try to scan for services and versions using the -sV
tag and providing only these ports as the ones to be scanned.
bandit16@bandit:~$ nmap -sV -p 31046,31518,31691,31790,31960 localhost
Starting Nmap 7.40 ( https://nmap.org ) at 2021-09-16 22:45 CEST
Nmap scan report for localhost (127.0.0.1)
Host is up (0.00042s latency).
PORT STATE SERVICE VERSION
31046/tcp open echo
31518/tcp open ssl/echo
31691/tcp open echo
31790/tcp open ssl/unknown
31960/tcp open echo
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
SF-Port31790-TCP:V=7.40%T=SSL%I=7%D=9/16%Time=6143ACF8%P=x86_64-pc-linux-g
SF:nu%r(GenericLines,31,"Wrong!\x20Please\x20enter\x20the\x20correct\x20cu
SF:rrent\x20password\n")...
...
...
At first sight we can rule out 31046, 31691 and 31960. Looking more closely on line 13, something indicates the port we are looking for must be 31790, hence we try to send the password just as we did in the previous level.
This returns with a private SSH key, which we copy the contents of. Terminate the session and copy the private SSH key into a file, say ssh.private
.
Trying to ssh -i ssh.private [email protected] -p 2220
yields the following error
This is a OverTheWire game server. More information on http://www.overthewire.org/wargames
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: UNPROTECTED PRIVATE KEY FILE! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Permissions 0644 for 'ssh.private' are too open.
It is required that your private key files are NOT accessible by others.
This private key will be ignored.
Load key "ssh.private": bad permissions
Okay, so what if we make the file only read-writable by us and no one else? This is done by chmod 600 filename
.
If we then try ssh
again, we succeed!
Level 17 -> Level 18
We see 2 files as we login, passwords.old
and passwords.new
. We are told the password for the next level is in passwords.new
and is the only line that has been changed between the two files.
bandit17@bandit:~$ diff passwords.new passwords.old
42c42
< kfBf3eYk5BPBRzwjqutbbfE887SVc5Yd
---
> w0Yfolrc5bwjS4qw5mq1nnQi6mF03bii
Lines starting with <
comes from the first file and lines starting with >
comes from the second file.
Since we know the password is in passwords.new
, which is the first provided file, the password for the next level must be kfBf3eYk5BPBRzwjqutbbfE887SVc5Yd
.
Level 18 -> Level 19
We know the password for the next level is stored in ~/readme
. But, we will be logged out instantly when trying to SSH our way in.
However, we can send a command along with the ssh
request as follows
ssh [email protected] -p 2220 "cat readme"
Which will reveal the password for the next level, IueksS7Ubh8G3DCwVzrTd8rAVOwq3M5x
.
Level 19 -> Level 20
We have been informed to find out how to use the setuid binary in the homefolder, and then to use it reading the password from etc/bandit_pass/bandit20
.
./bandit20-do
didn't give much, but ./bandit20-do --help
did.
After reading through the manpage, the password for the next level was retrieved by
./bandit20-do env bandit19=bandit20 cat /etc/bandit_pass/bandit20
GbKksEFF4yrVs6il55v6gwY5aVje5f0j
The password for level 20 being GbKksEFF4yrVs6il55v6gwY5aVje5f0j
.
Level 20 -> Level 21
We have been informed that the setuid binary, suconnect
, 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).
We are also given the hint to try connecting to your own network daemon to see if it works as we think.
I used tmux
for this, in order to listen and thereby open a port in one window, such that suconnect
is able to connect and read from it from another window.
We need to somehow echo
the password for level 20, such that suconnect
can read it and compare it.
We can do this as follows
echo GbKksEFF4yrVs6il55v6gwY5aVje5f0j | netcat -v -l -p 42420
The above will pipe the password for level 20 into the listener, which will listen on port 42420, such that when suconnect
connects to port 42420, the line being read will be the password.
-v
is for verbose mode, -l
is for listen mode and -p
specifies the port to listen on.
If we then do ./suconnect 42420
from another window, we should receive the password sent by suconnect
in the window where the listener is running.
bandit20@bandit:~$ ./suconnect 42420
Read: GbKksEFF4yrVs6il55v6gwY5aVje5f0j
Password matches, sending next password
We see the echo
from the first command made sure the password reached suconnect
, and if we look in the window where the listener is running, we should now see the following
bandit20@bandit:~$ echo GbKksEFF4yrVs6il55v6gwY5aVje5f0j | netcat -v -l -p 42420 │ -G num source-routing pointer: 4, 8, 12, ...
listening on [any] 42420 ... │ -h this cruft
connect to [127.0.0.1] from localhost [127.0.0.1] 42866 │ -i secs delay interval for lines sent, ports scanned
gE269g2h3mw3pwgrj0Ha9Uoqen1c9DGr
And there we have the password for the next level, gE269g2h3mw3pwgrj0Ha9Uoqen1c9DGr
.
Level 21 -> Level 22
We have been given a hint regarding the folder /etc/cron.d/
, for some configuration and see what command is being executed in regular intervals from cron
.
At first, figure out what is inside this folder,
bandit21@bandit:~$ ls /etc/cron.d
cronjob_bandit15_root cronjob_bandit22 cronjob_bandit24
cronjob_bandit17_root cronjob_bandit23 cronjob_bandit25_root
The cronjob_bandit22
could be interesting.
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
Okay. So cronjob_bandit22
appears to be a system wide crontab file given its syntax, opposite to the individual user crontab file. In system wide crontab files, the username
must be specified, which in this case is bandit22
. So 2 cronjobs are specified here, respectively on line 2 and 3.
@reboot
will, as far as I know, run the following shell script every time the system boots. So at every boot, the shell script /usr/bin/cronjob_bandit22.sh
will get executed.
At line 3 the * * * * *
part specifies the interval for when to execute the same shell script as above.
A *
means any value, and * * * * *
basically means to execute the shell script at every minute.
First value specifies at which minute
Second value specifies at which hour
Third value specifies at which day with regards to the month
Fourth value specifies at which month
Fifth value specifies at which day with regards to the week
For further clarification, try have a look here https://crontab.guru/.
Anyway, let's see what this shell scripts does.
bandit21@bandit:~$ cat /usr/bin/cronjob_bandit22.sh
#!/bin/bash
chmod 644 /tmp/t7O6lds9S0RqQh9aMcz6ShpAoZKF7fgv
cat /etc/bandit_pass/bandit22 > /tmp/t7O6lds9S0RqQh9aMcz6ShpAoZKF7fgv
So at first it executes chmod 644 /tmp/t7O6lds9S0RqQh9aMcz6ShpAoZKF7fgv
, which gives the owner read and write rights. The group and others will only have read rights. Apparently, we should be able to read the contents of this file.
bandit21@bandit:~$ cat /tmp/t7O6lds9S0RqQh9aMcz6ShpAoZKF7fgv
Yk7owGAcWjwMVRwrTesJEwB7WVOiILLI
There we have the password for level 22, Yk7owGAcWjwMVRwrTesJEwB7WVOiILLI
.
Level 22 -> Level 23
A lot from the previous level will count for this level as well. In general most of this is the same, except we should now look into /etc/cron.d/cronjob_bandit23
instead.
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
Which leads us to /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
Lets try the following,
bandit22@bandit:~$ echo I am user bandit23 | md5sum | cut -d ' ' -f 1
8ca319486bfbbc3663ea0fbe81326349
bandit22@bandit:~$ cat /tmp/8ca319486bfbbc3663ea0fbe81326349
jc1udXuA1tiHqjIsL8yaapX5XIAI6i0n
And the password for the next level is found, jc1udXuA1tiHqjIsL8yaapX5XIAI6i0n
.
Level 23 -> Level 24
We are given the hint to look into /etc/cron.d/
once again, where the file cronjob_bandit24
turns out to be relevant for this level.
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
Hence, lets look into /usr/bin/cronjob_bandit24.sh
which contains the following,
#!/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
So it will, as far as I'm aware, execute any script with the owner bandit23
. However, we have to make this script executable for bandit24
, and give write rights to bandit24
to some location, if we want to store the output.
As every script inside /var/spool/bandit24
will get removed, we will make a folder foo
, such that we can work inside /var/spool/bandit24/foo
.
With inspiration from the previous scripts, the following could be tempting
#!/bin/bash
cat /etc/bandit_pass/bandit24 > /var/spool/bandit24/foo/dump
For this to work, we have to make sure bandit24
can execute foo.sh
and write to /var/spool/bandit24/foo/
.
This is achieved by
bandit23@bandit:/var/spool/bandit24/foo$ chmod o+x foo.sh
bandit23@bandit:/var/spool/bandit24$ chmod o+w foo
This gives the class Others
rights to execute foo.sh
and to write into foo
, as we need bandit24
to create the dump
file for us.
Waiting a short period of time would make sure the script has been executed and voila.
bandit23@bandit:/var/spool/bandit24/foo$ ls
dump foo.sh
bandit23@bandit:/var/spool/bandit24/foo$ cat dump
UoMYTrfrBFHyQXmg6gzctqAwOmw1IohZ
There we have the password for the next level, UoMYTrfrBFHyQXmg6gzctqAwOmw1IohZ
.
Level 24 -> Level 25
We have been told that 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. Moreover, the pincode must be bruteforced.
As we are not allowed to create files within /home/bandit24
, I changed directory to the previously created /var/spool/bandit24/bob
.
At first I just tried the following, in order to see if something was returned.
bandit24@bandit:~$ echo 0000 | 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.
Fail! You did not supply enough data. Try again.
As the message says, we must provide the messages in a specific format.
Then I created the following bashscript, namely bruteforce.sh
#!/bin/bash
#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.
#Fail! You did not supply enough data. Try again.
password='UoMYTrfrBFHyQXmg6gzctqAwOmw1IohZ'
for i in {0000..9999}
do
echo "${password} ${i}"
done
And then ./bruteforce.sh | netcat localhost 30002
, which at some point yielded the password for the next level.
...
Wrong! Please enter the correct pincode. Try again.
Wrong! Please enter the correct pincode. Try again.
Wrong! Please enter the correct pincode. Try again.
Wrong! Please enter the correct pincode. Try again.
Correct!
The password of user bandit25 is uNG9O58gUE7snukf3bvZ0rxhtnjzSGzG
Exiting.
The password for lvl 25 being uNG9O58gUE7snukf3bvZ0rxhtnjzSGzG
.
Level 25 -> Level 26 -> Level 27
We are told the shell for bandit26
is not /bin/bash
, but something else. Shells different users can be seen in /etc/passwd
:
bandit25@bandit:~$ cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
...
bandit24:x:11024:11024:bandit level 24:/home/bandit24:/bin/bash
bandit25:x:11025:11025:bandit level 25:/home/bandit25:/bin/bash
bandit26:x:11026:11026:bandit level 26:/home/bandit26:/usr/bin/showtext
bandit27:x:11027:11027:bandit level 27:/home/bandit27:/bin/bash
bandit28:x:11028:11028:bandit level 28:/home/bandit28:/bin/bash
...
We see the shell for bandit26
is /usr/bin/showtext
, which contains the following
#!/bin/sh
export TERM=linux
more ~/text.txt
exit 0
Moreover, we find a file bandit26.sshkey
within /home/bandit25
, which must be used in order to login to bandit26
.
Logging in to bandit26
using the following (assumed bandit26.sshkey
is saved locally), will just kick us back out.
ssh -i bandit26.sshkey [email protected] -p 2220
We know more
is used, so lets minimize the terminal window, such that the whole content of ~/text.txt
cannot be seen, and we have to page through it. From more
we can open vi
by pressing v, and from there we can get a shell.
In order to get a shell from vi
, one must do the following:
Initiate vi
-command-mode by pressing :
, and from there:
:set shell=/bin/sh
:shell
$ ls
bandit27-do text.txt
We have a shell and can now get the password for level 27.
$ ./bandit27-do env bandit26=bandit27 cat /etc/bandit_pass/bandit27
3ba3118a22e93127a4ed485be72ef5ea
Being 3ba3118a22e93127a4ed485be72ef5ea
.
Level 27 -> Level 28
We are given the git repository at ssh://bandit27-git@localhost/home/bandit27-git/repo
. Moreover, we know the password for the user bandit27-git
is the same as for the user bandit27
.
I just created the folder /tmp/bob/
and cloned into this
git clone ssh://bandit27-git@localhost/home/bandit27-git/repo
bandit27@bandit:/tmp/bob$ ls
repo
bandit27@bandit:/tmp/bob$ cd repo/
bandit27@bandit:/tmp/bob/repo$ ls
README
bandit27@bandit:/tmp/bob/repo$ cat README
The password to the next level is: 0ef186ac70e04ea33b4c1853d2526fa2
And there the password for the next level is, 0ef186ac70e04ea33b4c1853d2526fa2
.
Level 28 -> Level 29
We are given the git repository at ssh://bandit28-git@localhost/home/bandit28-git/repo
. Moreover, we know the password for the user bandit28-git
is the same as for the user bandit28
.
I just created the folder /tmp/foo/
and cloned into this
git clone ssh://bandit28-git@localhost/home/bandit28-git/repo
We see a file README.md
within repo
with the following content
# Bandit Notes
Some notes for level29 of bandit.
## credentials
- username: bandit29
- password: xxxxxxxxxx
If we look into git log
, we get the following
commit edd935d60906b33f0619605abd1689808ccdd5ee
Author: Morla Porla <[email protected]>
Date: Thu May 7 20:14:49 2020 +0200
fix info leak
commit c086d11a00c0648d095d04c089786efef5e01264
Author: Morla Porla <[email protected]>
Date: Thu May 7 20:14:49 2020 +0200
add missing data
commit de2ebe2d5fd1598cd547f4d56247e053be3fdc38
Author: Ben Dover <[email protected]>
Date: Thu May 7 20:14:49 2020 +0200
initial commit of README.md
Lets git checkout c086d11a00c0648d095d04c089786efef5e01264
, just before an info leak was fixed and see what README.md
contains then.
# Bandit Notes
Some notes for level29 of bandit.
## credentials
- username: bandit29
- password: bbc96594b4e001778eee9975372716b2
And there we have the password for level 29, bbc96594b4e001778eee9975372716b2
.
Level 29 -> Level 30
We are given the git repository at ssh://bandit29-git@localhost/home/bandit29-git/repo
. Moreover, we know the password for the user bandit29-git
is the same as for the user bandit29
.
I just created the folder /tmp/bar/
and cloned into this
git clone ssh://bandit29-git@localhost/home/bandit29-git/repo
The README.md
within repo
contains the following
# Bandit Notes
Some notes for bandit30 of bandit.
## credentials
- username: bandit30
- password: <no passwords in production!>
So, lets check for other branches with git branch -a
, giving us both local and remote branches.
bandit29@bandit:/tmp/bar/repo$ git branch -a
* master
remotes/origin/HEAD -> origin/master
remotes/origin/dev
remotes/origin/master
remotes/origin/sploits-dev
Okay. Let's start with git checkout remotes/origin/dev/
, and look into README.md
.
# Bandit Notes
Some notes for bandit30 of bandit.
## credentials
- username: bandit30
- password: 5b90576bedb2cc04c86a9e924ce
And there we have the password for the next level, 5b90576bedb2cc04c86a9e924ce42faf
.
Level 30 -> Level 31
We are given the git repository at ssh://bandit30-git@localhost/home/bandit30-git/repo
. Moreover, we know the password for the user bandit30-git
is the same as for the user bandit30
.
I just created the directory /tmp/baz/
and cloned into this.
README.md
just contains the string just an epmty file... muahaha
, so no luck there.
There is no relevant branches to checkout and the log is pretty much empty.
git tag
reveals something called secret
. So lets try git show secret
.
bandit30@bandit:/tmp/baz/repo$ git show secret
47e603bb428404d265f59c42920d81e5
This seems like the password to the next level, 47e603bb428404d265f59c42920d81e5
.
Level 31 -> Level 32
We are given the git repository at ssh://bandit31-git@localhost/home/bandit31-git/repo
. Moreover, we know the password for the user bandit31-git
is the same as for the user bandit31
.
I just created the folder /tmp/baz/
and cloned into this.
repo
has a README.md
and a .gitignore
file.
README.md
contains the following
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
.gitignore
contains the following
*.txt
Okay. So lets remove this .gitignore
as it prevents us from completing the task.
Next, lets create the required file.
The procedure for pushing a file to the remote repository is:
git add .
in order to add everything.git commit -m "commit message"
to commit changes.git push
to push changes to remote repository.
bandit31@bandit:/tmp/bat/repo$ git push
...
Counting objects: 3, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 283 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 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: 56a9bf19c63d650ce78e6ec0354ee45e
remote:
remote: .oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.
...
Which reveals the password for the next level, 56a9bf19c63d650ce78e6ec0354ee45e
.
Level 32 -> Level 33
We are just told that after all this git
stuff its time for another escape. Good luck!
After logging in, we are introduced to the UPPERCASE SHELL.
WELCOME TO THE UPPERCASE SHELL
>> ls
sh: 1: LS: not found
As we have an interactive shell, lets see if we can get the values of environment variables
>> $USER
sh: 1: bandit32: not found
It appears to be the case, hence we can invoke /bin/bash
through $0
.
>> $0
$ ls
uppershell
And now we have a shell, from where we can get our password
$ cat /etc/bandit_pass/bandit33
c9c3199ddf4121b10cf581a98d51caee
And there we have the password for level 33, c9c3199ddf4121b10cf581a98d51caee
.
So far, there are no more levels, hence we are done with Bandit for now.
Last updated