Over The Wire (Bandit) 🧑💻 (2024-07-17)
This is a wargame or ctf game that has the player interact with and penetrate a Linux system. The goal of each level is to retrieve a password or key located somewhere on a server. This can be used to access this next level, which is a user on the server.
SPOILER WARNING
I will provide the prompt and hints to each level and my answers. I may describe my methodology, reasoning, or solution if it is warranted. Do not read if you intend on playing yourself.
Level 0
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.
Solution
ssh bandit0@bandit.labs.overthewire.org -p 2220
- Once logged in
cat readme
will output password to level 1. - Password:
ZjLjTmM6FvvyRnrb2rfNWOZOTa6ip5If
Level 1
The password for the next level is stored in a file called - located in the home directory
ssh bandit1@bandit.labs.overthewire.org -p 2220
- The name of the file containing the password needs to be referenced as a file as
-
is reserved for other uses in the shell. cat ./-
will do the trick- Password:
263JGJPfgU6LtdEvgfWU1XP5yac29mFx
Level 2
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
- This is a similar issue as whitespace has a reserved use is shells as well. The file must be referenced by encasing it with quotes,
cat "spaces in this filename"
or by escaping the spaces,cat spaces\ in\ this\ filename
. - Password:
MNk8KNH3Usiio41PRUEoDFPqfxLPlSmx
Level 3
The password for the next level is stored in a hidden file in the inhere directory.
ssh bandit3@bandit.labs.overthewire.org -p 2220
cat inhere/...Hiding-From-You
- Password:
2WmrDFRmJIq3IPxneAaMGhap0pFhF3NJ
Level 4
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.
ssh bandit4@bandit.labs.overthewire.org -p 2220
- This is the first level that doesn't essentially have a single solution. Essentially do whatever you need to to determine which file is human readable or cat everything to a file and sift through garbage until you see the password.
- Using
file
and a wildcard:
bandit4@bandit:~$ file inhere/*
inhere/-file00: data
inhere/-file01: data
inhere/-file02: data
inhere/-file03: data
inhere/-file04: data
inhere/-file05: data
inhere/-file06: data
inhere/-file07: ASCII text
inhere/-file08: data
inhere/-file09: data
Looks to be inhere/-file07
.
bandit4@bandit:~$ cat inhere/-file07
4oQYVPkxZOOEOO5pTW81FB8j8lxXGUQw
Level 5
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
- Most automated solution is probably just using
find
find . -size 1033c \! -executable
bandit5@bandit:~$ find . -size 1033c \! -executable
./inhere/maybehere07/.file2
- Can cat this in a one liner by running
find
in a subshell:
bandit5@bandit:~$ cat $(find . -size 1033c \! -executable)
HWasnPhtq9AVKe0dmk45nxy20cvUa6EG
Level 6
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
- Same deal as last level except different switches and searching from root.
- After running I also redirected
stderr
to/dev/null
because there were too many permission denials getting in the way of reading output
bandit6@bandit:~$ find / -user bandit7 -group bandit6 -size 33c 2>/dev/null
/var/lib/dpkg/info/bandit7.password
bandit6@bandit:~$
- And we can cat it in a one liner for fun
bandit6@bandit:~$ cat $(find / -user bandit7 -group bandit6 -size 33c 2>/dev/null)
morbNTDkSW6jIlUc0ymOdMaLnOlFVAaj
bandit6@bandit:~$
Level 7
The password for the next level is stored in the file data.txt next to the word millionth
- First instinct is to
cat
then pipe intogrep
for "millionth".
cat data.txt | grep millionth
millionth dfwvzFQi4mU0wfNbFOe9RoWskMLg7eEc
bandit7@bandit:~$
- Yup
Level 8
The password for the next level is stored in the file data.txt and is the only line of text that occurs only once
- First instinct is to cat then pipe into uniq maybe.
- My first instinct,
cat data.txt | uniq -u
, contains too many entries. After researching I realize that repeated lines need to be adjacent to be detected as repeated, so let's sort then pipe intouniq
.
bandit8@bandit:~$ sort data.txt | uniq -u
4CKMh1JI91bUIZZPXDqGanal4xvAg0JM
bandit8@bandit:~$
- Got it
Level 9
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.
- We can use
strings
to convert the garbage data to text, then grep the file for some "=".
bandit9@bandit:~$ strings data.txt -d | grep ==
[========== the
T%========== passwordG
}========== ist"
========== FGUW5ilLVJrxX9kMYMmlN4MgbpfMiqey
bandit9@bandit:~$
- Password:
FGUW5ilLVJrxX9kMYMmlN4MgbpfMiqey
Level 10
The password for the next level is stored in the file data.txt, which contains base64 encoded data
From wikipedia: >In computer programming, Base64 is a group of binary-to-text encoding schemes that transforms binary data into a sequence of printable characters, limited to a set of 64 unique characters. More specifically, the source binary data is taken 6 bits at a time, then this group of 6 bits is mapped to one of 64 unique characters.
- I can use
base64
to decode the data by piping into it fromcat
.
bandit10@bandit:~$ cat data.txt | base64 -d
The password is dtR173fZKb0RRsDFSGsg2RWnpNVj3qRr
- Success!
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
tr
can be used to effectively rotate every character back.
bandit11@bandit:~$ cat data.txt | tr 'a-z' 'n-za-m' | tr 'A-Z' 'N-ZA-M'
The password is 7x16WNeHIi5YkIhWsfFIqoognUTyj9Q4
I need to learn tr syntax, I just found the implementation of Rot13 in tr
online and added rotation for capitals as well and piped the output a second time. That worked.
Level 12
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. Use mkdir with a hard to guess directory name. Or better, use the command “mktemp -d”. Then copy the datafile using cp, and rename it using mv (read the manpages!)
mkdir /tmp/sm;cp data.txt /tmp/sm/; cd /tmp/sm
- I will probably have to convert from hex to binary or something and uncompress that multiple times
xxd -r data.txt | gzip -d > out
xxd
can convert data from hex to binary and vice-versa.bzip2 out -d -c > out2
gzip out2 -d -c > out3
tar -xvf out3
tar -xvf data5.bin
bzip2 data6.bin -d -c > out7
tar -xvf out7
gzip data8.bin -d -c > out9
bandit12@bandit:/tmp/sm$ cat out9
The password is FO5dwFsc0cbaIiH0h8J2eUks2vdTDwAn
bandit12@bandit:/tmp/sm$
- I gave up on renaming every time so the scheme is inconsistent, but I just checked the output using
file
every time to determine what decompression algorithm or archival tool to use until it was completely unwrapped as a text file. - Password:
FO5dwFsc0cbaIiH0h8J2eUks2vdTDwAn
Level 13
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
bandit13@bandit:~$ cat sshkey.private
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAxkkOE83W2cOT7IWhFc9aPaaQmQDdgzuXCv+ppZHa++buSkN+
gg0tcr7Fw8NLGa5+Uzec2rEg0WmeevB13AIoYp0MZyETq46t+jk9puNwZwIt9XgB
ZufGtZEwWbFWw/vVLNwOXBe4UWStGRWzgPpEeSv5Tb1VjLZIBdGphTIK22Amz6Zb
ThMsiMnyJafEwJ/T8PQO3myS91vUHEuoOMAzoUID4kN0MEZ3+XahyK0HJVq68KsV
ObefXG1vvA3GAJ29kxJaqvRfgYnqZryWN7w3CHjNU4c/2Jkp+n8L0SnxaNA+WYA7
jiPyTF0is8uzMlYQ4l1Lzh/8/MpvhCQF8r22dwIDAQABAoIBAQC6dWBjhyEOzjeA
J3j/RWmap9M5zfJ/wb2bfidNpwbB8rsJ4sZIDZQ7XuIh4LfygoAQSS+bBw3RXvzE
pvJt3SmU8hIDuLsCjL1VnBY5pY7Bju8g8aR/3FyjyNAqx/TLfzlLYfOu7i9Jet67
xAh0tONG/u8FB5I3LAI2Vp6OviwvdWeC4nOxCthldpuPKNLA8rmMMVRTKQ+7T2VS
nXmwYckKUcUgzoVSpiNZaS0zUDypdpy2+tRH3MQa5kqN1YKjvF8RC47woOYCktsD
o3FFpGNFec9Taa3Msy+DfQQhHKZFKIL3bJDONtmrVvtYK40/yeU4aZ/HA2DQzwhe
ol1AfiEhAoGBAOnVjosBkm7sblK+n4IEwPxs8sOmhPnTDUy5WGrpSCrXOmsVIBUf
laL3ZGLx3xCIwtCnEucB9DvN2HZkupc/h6hTKUYLqXuyLD8njTrbRhLgbC9QrKrS
M1F2fSTxVqPtZDlDMwjNR04xHA/fKh8bXXyTMqOHNJTHHNhbh3McdURjAoGBANkU
1hqfnw7+aXncJ9bjysr1ZWbqOE5Nd8AFgfwaKuGTTVX2NsUQnCMWdOp+wFak40JH
PKWkJNdBG+ex0H9JNQsTK3X5PBMAS8AfX0GrKeuwKWA6erytVTqjOfLYcdp5+z9s
8DtVCxDuVsM+i4X8UqIGOlvGbtKEVokHPFXP1q/dAoGAcHg5YX7WEehCgCYTzpO+
xysX8ScM2qS6xuZ3MqUWAxUWkh7NGZvhe0sGy9iOdANzwKw7mUUFViaCMR/t54W1
GC83sOs3D7n5Mj8x3NdO8xFit7dT9a245TvaoYQ7KgmqpSg/ScKCw4c3eiLava+J
3btnJeSIU+8ZXq9XjPRpKwUCgYA7z6LiOQKxNeXH3qHXcnHok855maUj5fJNpPbY
iDkyZ8ySF8GlcFsky8Yw6fWCqfG3zDrohJ5l9JmEsBh7SadkwsZhvecQcS9t4vby
9/8X4jS0P8ibfcKS4nBP+dT81kkkg5Z5MohXBORA7VWx+ACohcDEkprsQ+w32xeD
qT1EvQKBgQDKm8ws2ByvSUVs9GjTilCajFqLJ0eVYzRPaY6f++Gv/UVfAPV4c+S0
kAWpXbv5tbkkzbS0eaLPTKgLzavXtQoTtKwrjpolHKIHUz6Wu+n4abfAIRFubOdN
/+aLoRQ0yBDRbdXMsZN/jvY44eM+xRLdRVyMmdPtP8belRi2E2aEzA==
-----END RSA PRIVATE KEY-----
- I will copy this key to my host's
~/.ssh
directory and login by forcing the use of the key for access:ssh bandit14@bandit.labs.overthewire.org -p 2220 -i .ssh/id_bandit14
- I'm in!
Level 14
The password for the next level can be retrieved by submitting the password of the current level to port 30000 on localhost.
- I can
cat
the password referenced in the last level and pipe it intonetcat
to send it to the port.
bandit14@bandit:~$ cat /etc/bandit_pass/bandit14 | netcat localhost 30000
Correct!
8xCjnmgoKbGLhHFAZlGE5Tmu4M2tKJQo
Level 15
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. Helpful note: Getting “HEARTBEATING” and “Read R BLOCK”? Use -ign_eof and read the “CONNECTED COMMANDS” section in the manpage. Next to ‘R’ and ‘Q’, the ‘B’ command also works in this version of that command…
- I will need to encrypt what I send to the port beforehand. This can be acchomplished with openssl's s_client.
- From the man page: >DESCRIPTION This command implements a generic SSL/TLS client which connects to a remote host using SSL/TLS. It is a very useful diagnostic tool for SSL servers.
openssl s_client -ign_eof -connect localhost:30001
- I then manually enter the password
8xCjnmgoKbGLhHFAZlGE5Tmu4M2tKJQo
Correct!
kSkvUpMQ7lBYyCM4GBPvCvT1BfWRy0Dx
closed
bandit15@bandit:~$
- Mission accomplished!
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. 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.
- I will search for candidate ports
bandit16@bandit:~$ netstat -tulpn
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
netstat: no support for `AF INET (tcp)' on this system.
tcp6 0 0 :::31691 :::* LISTEN -
tcp6 0 0 :::31046 :::* LISTEN -
tcp6 0 0 :::22 :::* LISTEN -
tcp6 0 0 :::2232 :::* LISTEN -
tcp6 0 0 :::2231 :::* LISTEN -
tcp6 0 0 :::2230 :::* LISTEN -
tcp6 0 0 :::2220 :::* LISTEN -
tcp6 0 0 :::31960 :::* LISTEN -
bandit16@bandit:~$
- 31691, 31046, and 31960 are candidates
- However none are over ssl, the port may be open but not listening. I can scan with
nmap
.
nmap -p 31000-32000 localhost
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-07-16 01:36 UTC
Nmap scan report for localhost (127.0.0.1)
Host is up (0.00014s latency).
Not shown: 996 closed tcp ports (conn-refused)
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.11 seconds
- I will not manually check each with
s_client
.
openssl s_client -ign_eof -connect localhost:31790
kSkvUpMQ7lBYyCM4GBPvCvT1BfWRy0Dx
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:~$
- It was port 31790 and a key was returned, I will add it to my host's
~/.ssh
.ssh bandit17@bandit.labs.overthewire.org -p 2220 -i ~/.ssh/id_bandit17
works!
Level 17
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 NOTE: if you have solved this level and see ‘Byebye!’ when trying to log into bandit18, this is related to the next level, bandit19
- We can just
diff
to find the differing line:
bandit17@bandit:~$ diff passwords.new passwords.old
42c42
< x2gLTTjFwMOhQ8oWNbMN362QKxfRqGlO
---
> FtePUTiLiwPzjIFw2T7o57oBS4zUvPpg
So the password is: x2gLTTjFwMOhQ8oWNbMN362QKxfRqGlO
Level 18
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.
- I know that you can pass a command to
ssh
to be ran rather than initializing a shell ssh bandit18@bandit.labs.overthewire.org -p 2220 'cat readme'
- The password was returned:
bandit18@bandit.labs.overthewire.org's password: cGWpMaKXVwDUNgPAVJbWYuGHVn9zl3j8
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.
bandit19@bandit:~$ ./bandit20-do
Run a command as another user.
Example: ./bandit20-do id
- Evidently, we can use this binary to
cat
bandit20's password since it is the owner of the file that contains it.
bandit19@bandit:~$ ./bandit20-do cat /etc/bandit_pass/bandit20
0qXahG8ZjOVMN9Ghs7iOWsCfZyXOUbYO
Level 20
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). NOTE: Try connecting to your own network daemon to see if it works as you think
- I believe I have to connect to a port of my choosing using the
suconnect
binary and then send the password to that port while it is open. I have some options. I can either use a multiplexer or throwsuconnect
's process to the background. - I am mistaken, it it the other way around. I must send the password to the port first, then
suconnect
grabs it.
bandit20@bandit:~$ echo -n "0qXahG8ZjOVMN9Ghs7iOWsCfZyXOUbYO" | netcat -l -p 30003 &
[1] 867141
bandit20@bandit:~$ ./suconnect 30003
Read: 0qXahG8ZjOVMN9Ghs7iOWsCfZyXOUbYO
Password matches, sending next password
EeoULMCra2q0dSkYj561DX7s1CpBuOBt
[1]+ Done echo -n "0qXahG8ZjOVMN9Ghs7iOWsCfZyXOUbYO" | netcat -l -p 30003
- Password:
EeoULMCra2q0dSkYj561DX7s1CpBuOBt
Level 21
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.
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
bandit21@bandit:~$ cat /usr/bin/cronjob_bandit22.sh
#!/bin/bash
chmod 644 /tmp/t7O6lds9S0RqQh9aMcz6ShpAoZKF7fgv
cat /etc/bandit_pass/bandit22 > /tmp/t7O6lds9S0RqQh9aMcz6ShpAoZKF7fgv
bandit21@bandit:~$ cat /tmp/t7O6lds9S0RqQh9aMcz6ShpAoZKF7fgv
tRae0UfB9v0UzbCdn9cY0gQnds9GF58Q
bandit21@bandit:~$
Password: tRae0UfB9v0UzbCdn9cY0gQnds9GF58Q
Level 22
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: Looking at shell scripts written by other people is a very useful skill. The script for this level is intentionally made easy to read. If you are having problems understanding what it does, try executing it to see the debug information it prints.
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
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
bandit22@bandit:~$
- Based on this, the password whose name was hashed by
md5sum
- I will manually run the command using "bandit23" as
myname
in a subshell and cat the appropriate file.
bandit22@bandit:~$ cat /tmp/$(echo I am user bandit23 | md5sum | cut -d ' ' -f 1)
0Zf11ioIjMVN551jX3CmStKLYqjk54Ga
Level 23
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…
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:~$ cat /usr/bin/cronjob_bandit24.sh
#!/bin/bash
myname=$(whoami)
cd /var/spool/$myname/foo
echo "Executing and deleting all scripts in /var/spool/$myname/foo:"
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
- Based on the script that is being run by cron, we just need to write a script that gets the name of bandit24's password for us. This script executes every script in
/var/spool/bandit24/foo/
if it is owned by bandit23 then deletes it. However, the script will be ran as bandit24 since it is that user's cronjob. Therefore, I can get the contents of/etc/bandit_pass
from a script in/var/spool/bandit24/foo/
. - I am having an issue getting output from the script presumably due to permissions. I modified the target directory with
chmod 777
.
#!/bin/bash
cat /etc/bandit_pass/bandit24 >> /tmp/sm2/out.txt
This did the trick:
gb8KRRCsshuZXI0tUuR6ypOFjiZbf3G8
- Success!
Level 24
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
- This is the script I've formulated:
#!/bin/sh
code=0
while [ $code -le 9998 ];
do
code=$((code+1))
pass="gb8KRRCsshuZXI0tUuR6ypOFjiZbf3G8 ${code}"
echo "Trying code $pass"
echo $pass | nc localhost 30002 -w 1 | tee -a out.txt
done
- But it is very slow, there must be a faster way.
- Firstly, it starts at 0 because it just increments it doesn't handle every digit independently.
#!/bin/bash
for i in {0000..9999}
do
pass="gb8KRRCsshuZXI0tUuR6ypOFjiZbf3G8 ${i}"
echo "Trying code $pass"
echo $pass | nc localhost 30002 -w 1 | tee -a out.txt
done
- This is better! Didn't know bash supported iterating over ranges this way. Now looking into improving speed. Could utilize parallelization in some way. I could:
- Throw the jobs into the background with a max number running any time
- Utilize
parallel
#!/bin/bash
export pass_prefix="gb8KRRCsshuZXI0tUuR6ypOFjiZbf3G8 "
generate_and_try() {
i=$1
pass="${pass_prefix}${i}"
echo "Trying code $pass"
echo $pass | nc localhost 30002 -w 1 | tee -a out.txt
}
export -f generate_and_try
export pass_prefix
# Generate the sequence and run in parallel
seq -w 0000 9999 | parallel -j 100 generate_and_try
parallel
handles the parallelization... luckily it is installed...- Instead of a loop this solution utilizes
seq
to generate codes - The code is passed as a cmdline arg
- I will then search the output for the string "Correct". One could also
grep -v
the string "Wrong".
Correct! The password of user bandit25 is iCi86ttT4KSNe1armKiwbQNmB3YJP3q4
- Success!
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.
- I know that default shells are in
/etc/passwd
. cat /etc/passwd | grep -i bandit26
yieldsbandit26:x:11026:11026:bandit level 26:/home/bandit26:/usr/bin/showtext
showtext
is a script:
#!/bin/sh
export TERM=linux
exec more ~/text.txt exit 0
* And there is a key in the home directory
```terminal
ls
bandit26.sshkey
bandit25@bandit:~$ cat bandit26.sshkey
-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEApis2AuoooEqeYWamtwX2k5z9uU1Afl2F8VyXQqbv/LTrIwdW
pTfaeRHXzr0Y0a5Oe3GB/+W2+PReif+bPZlzTY1XFwpk+DiHk1kmL0moEW8HJuT9
/5XbnpjSzn0eEAfFax2OcopjrzVqdBJQerkj0puv3UXY07AskgkyD5XepwGAlJOG
xZsMq1oZqQ0W29aBtfykuGie2bxroRjuAPrYM4o3MMmtlNE5fC4G9Ihq0eq73MDi
1ze6d2jIGce873qxn308BA2qhRPJNEbnPev5gI+5tU+UxebW8KLbk0EhoXB953Ix
3lgOIrT9Y6skRjsMSFmC6WN/O7ovu8QzGqxdywIDAQABAoIBAAaXoETtVT9GtpHW
qLaKHgYtLEO1tOFOhInWyolyZgL4inuRRva3CIvVEWK6TcnDyIlNL4MfcerehwGi
il4fQFvLR7E6UFcopvhJiSJHIcvPQ9FfNFR3dYcNOQ/IFvE73bEqMwSISPwiel6w
e1DjF3C7jHaS1s9PJfWFN982aublL/yLbJP+ou3ifdljS7QzjWZA8NRiMwmBGPIh
Yq8weR3jIVQl3ndEYxO7Cr/wXXebZwlP6CPZb67rBy0jg+366mxQbDZIwZYEaUME
zY5izFclr/kKj4s7NTRkC76Yx+rTNP5+BX+JT+rgz5aoQq8ghMw43NYwxjXym/MX
c8X8g0ECgYEA1crBUAR1gSkM+5mGjjoFLJKrFP+IhUHFh25qGI4Dcxxh1f3M53le
wF1rkp5SJnHRFm9IW3gM1JoF0PQxI5aXHRGHphwPeKnsQ/xQBRWCeYpqTme9amJV
tD3aDHkpIhYxkNxqol5gDCAt6tdFSxqPaNfdfsfaAOXiKGrQESUjIBcCgYEAxvmI
2ROJsBXaiM4Iyg9hUpjZIn8TW2UlH76pojFG6/KBd1NcnW3fu0ZUU790wAu7QbbU
i7pieeqCqSYcZsmkhnOvbdx54A6NNCR2btc+si6pDOe1jdsGdXISDRHFb9QxjZCj
6xzWMNvb5n1yUb9w9nfN1PZzATfUsOV+Fy8CbG0CgYEAifkTLwfhqZyLk2huTSWm
pzB0ltWfDpj22MNqVzR3h3d+sHLeJVjPzIe9396rF8KGdNsWsGlWpnJMZKDjgZsz
JQBmMc6UMYRARVP1dIKANN4eY0FSHfEebHcqXLho0mXOUTXe37DWfZza5V9Oify3
JquBd8uUptW1Ue41H4t/ErsCgYEArc5FYtF1QXIlfcDz3oUGz16itUZpgzlb71nd
1cbTm8EupCwWR5I1j+IEQU+JTUQyI1nwWcnKwZI+5kBbKNJUu/mLsRyY/UXYxEZh
ibrNklm94373kV1US/0DlZUDcQba7jz9Yp/C3dT/RlwoIw5mP3UxQCizFspNKOSe
euPeaxUCgYEAntklXwBbokgdDup/u/3ms5Lb/bm22zDOCg2HrlWQCqKEkWkAO6R5
/Wwyqhp/wTl8VXjxWo+W+DmewGdPHGQQ5fFdqgpuQpGUq24YZS8m66v5ANBwd76t
IZdtF5HXs2S5CADTwniUS5mX1HO9l5gUkk+h0cH5JnPtsMCnAUM+BRY=
-----END RSA PRIVATE KEY-----
bandit25@bandit:~$
- The solution for this was ultimately simple yet very elusive. So the text contained in
~text.txt
was too short to do anything with and would immeditaly exit. I explored for any possible ssh switch or techqiue I could employ. I checked every permission. But the simpliest solution was just... to make the window smaller... That forcesmore
to enter an interactive mode since all the text can't be displayed. From there you cna evert Vi and do whatever you need to. - I first redefined the shell:
:set shell=/bin/bash
- And enter a shell from Vi using
:shell
- Now I am in and technically in:
Level 26
Good job getting a shell! Now hurry and grab the password for bandit27!
- Then catted the password
bandit26@bandit:~$ cat /etc/bandit_pass/bandit26 s0773xxkk0MXfdqOfPRVr9L3jJBUOgCZ
bandit26@bandit:~$ ```
- Password:
s0773xxkk0MXfdqOfPRVr9L3jJBUOgCZ
- Remember this is just bandit 26's password.
bandit26@bandit:~$ ls -l
total 20
-rwsr-x--- 1 bandit27 bandit26 14880 Jul 17 15:57 bandit27-do
-rw-r----- 1 bandit26 bandit26 258 Jul 17 15:57 text.txt
bandit26@bandit:~$ ./bandit27-do cat /etc/bandit_pass/bandit27
upsNCc7vzaRDx6oZC6GiR6ERwe1MowGB
bandit26@bandit:~$
- Looks like there is a binary with the
suid
bit set allowing me to run it as bandit27 since they are the owner and bandit26's group has execute permissions on. The binary evidently takes a command as an argument to be ran. I used this to get the password for bandit27. - Password:
upsNCc7vzaRDx6oZC6GiR6ERwe1MowGB
Level 27
There is a git repository at ssh://bandit27-git@localhost/home/bandit27-git/repo via the port 2220. The password for the user bandit27-git is the same as for the user bandit27.
Clone the repository and find the password for the next level.
- I make a directory in
tmp
and clone the repo
bandit27@bandit:/tmp/gh$ git clone ssh://bandit27-git@localhost:2220/home/bandit27-git/repo
bandit27@bandit:/tmp/gh/repo$ cat README
The password to the next level is: Yz9IpL0sBcCeuG7m9uQFt8ZNpS4HZRcN
- There was simply a
README
containing the password
Level 28
There is a git repository at ssh://bandit28-git@localhost/home/bandit28-git/repo via the port 2220. The password for the user bandit28-git is the same as for the user bandit28. Clone the repository and find the password for the next level.
- It is the same process as before, but the contents are little different.
bandit28@bandit:/tmp/gh28/repo$ ls
README.md
bandit28@bandit:/tmp/gh28/repo$ cat README.md
# Bandit Notes
Some notes for level29 of bandit.
## credentials
- username: bandit29
- password: xxxxxxxxxx
bandit28@bandit:/tmp/gh28/repo$
- Looks like we will have to brute for a password a 10 character password, which would take way too long. As in like millions of years... using a supercomputer... so this can't be the solution.
bandit28@bandit:/tmp/gh28/repo$ git log
WARNING: terminal is not fully functional
Press RETURN to continue
commit 8cbd1e08d1879415541ba19ddee3579e80e3f61a (HEAD -> mast
er, origin/master, origin/HEAD)
Author: Morla Porla <morla@overthewire.org>
Date: Wed Jul 17 15:57:30 2024 +0000
fix info leak
commit 73f5d0435070c8922da12177dc93f40b2285e22a
Author: Morla Porla <morla@overthewire.org>
Date: Wed Jul 17 15:57:30 2024 +0000
add missing data
commit 5f7265568c7b503b276ec20f677b68c92b43b712
Author: Ben Dover <noone@overthewire.org>
Date: Wed Jul 17 15:57:30 2024 +0000
initial commit of README.md
bandit28@bandit:/tmp/gh28/repo$
- The solution looks it is going to be looking at each commit to see when a password added. This can be a accomplished with
checkout
. There seems to be three commits and the password was ultimately in the middle one.
bandit28@bandit:/tmp/gh28/repo$ git checkout 73f5d0435070c8922da12177dc93f40b2285e22a
Previous HEAD position was 5f72655 initial commit of README.md
HEAD is now at 73f5d04 add missing data
bandit28@bandit:/tmp/gh28/repo$ ls
README.md
bandit28@bandit:/tmp/gh28/repo$ cat README.md
# Bandit Notes
Some notes for level29 of bandit.
## credentials
- username: bandit29
- password: 4pT1t5DENaYuqnqvadYs1oE4QLCdjmJ7
bandit28@bandit:/tmp/gh28/repo$
- Password:
4pT1t5DENaYuqnqvadYs1oE4QLCdjmJ7
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.
bandit29@bandit:/tmp/b29/repo$ cat README.md
# Bandit Notes
Some notes for bandit30 of bandit.
## credentials
- username: bandit30
- password: <no passwords in production!>
bandit29@bandit:/tmp/b29/repo$
- Probably going to have to go to a different branch based on this.
bandit29@bandit:/tmp/b29/repo$ git branch -r
WARNING: terminal is not fully functional
Press RETURN to continue
origin/HEAD -> origin/master
origin/dev
origin/master
origin/sploits-dev
bandit29@bandit:/tmp/b29/repo$
- I'll checkout dev
bandit29@bandit:/tmp/b29/repo$ git checkout dev
Previous HEAD position was 5a53eb8 initial commit of README.md
branch 'dev' set up to track 'origin/dev'.
Switched to a new branch 'dev'
bandit29@bandit:/tmp/b29/repo$ ls
code README.md
bandit29@bandit:/tmp/b29/repo$ ls code/
gif2ascii.py
bandit29@bandit:/tmp/b29/repo$ cat README.md
# Bandit Notes
Some notes for bandit30 of bandit.
## credentials
- username: bandit30
- password: qp30ex3VLz5MDG1n91YowTv4Q8l7CDZL
bandit29@bandit:/tmp/b29/repo$
- There it is! Password:
qp30ex3VLz5MDG1n91YowTv4Q8l7CDZL
Level 30
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.
bandit30@bandit:/tmp/b30/repo$ cat README.md
just an epmty file... muahaha
bandit30@bandit:/tmp/b30/repo$ git tag
WARNING: terminal is not fully functional
Press RETURN to continue
secret
bandit30@bandit:/tmp/b30/repo$ git show secret
WARNING: terminal is not fully functional
Press RETURN to continue
fb5S2xb7bRyFmAvQYQGEqsbhVyJqhnDy
bandit30@bandit:/tmp/b30/repo$
- The
README
had nothing, but there was a tag namedsecret
that contained the password. - Password:
fb5S2xb7bRyFmAvQYQGEqsbhVyJqhnDy
Level 31
There is a git repository at ssh://bandit31-git@localhost/home/bandit31-git/repo via the port 2220. The password for the user bandit31-git is the same as for the user bandit31. Clone the repository and find the password for the next level.
bandit31@bandit:/tmp/b31/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/b31/repo$
- Here it seems we must write a file
key.txt
that contains the required string. - We can
touch key.txt; echo "May I come in? > key.txt"
- Then
add key.txt
,commit
, thenpush
. - The
.gitignore
needed to be edited. because every text file was being ignored via:*.txt
- Once pushed we succeeded!
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: 3O9RfhqyAlVBEZpVb6LYStshZoqoSx5K
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'
bandit31@bandit:/tmp/b31/repo$
- Password:
3O9RfhqyAlVBEZpVb6LYStshZoqoSx5K
Level 32
After all this git stuff, it’s time for another escape. Good luck!
WELCOME TO THE UPPERCASE SHELL
>> ls
sh: 1: LS: Permission denied
Where am I?
- We can't use commands because they are all made uppercase. In this peculiar situation we'd have access to environment variables and command line arguments however. Considering that the first arg,
$0
, is the shell itself, i can call a new shell with it?
>> $0
$
- YES!
- I switched to a bash shell and got the next password
bandit33@bandit:~$ cat /etc/bandit_pass/bandit33
tQdtbs5D5i2vJwkO8mEyYEyTL8izoeJ0
bandit33@bandit:~$
Level 33
At this moment, level 34 does not exist yet.
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.
us
If you have an idea for an awesome new level, please let us know!
bandit33@bandit:~$
I WON! 🥳
What I Learned
This game was very fun and forces us to really think about how certain aspects of a Linux system works and how they interact with one another. The topics that are generally touched on are:
- Basic command line utilities
ls
,cd
,mkdir
, etc.
- Text manipulation
cat
,grep
,uniq
,sort
,seq
,strings
,tr
- Redirection
- Redirection Operators, Pipes,
tee
- Redirection Operators, Pipes,
- Permissions
- Remote Access and Remote Command Execution
ssh
- System File Locations and Root Directories
etc/passwd
,/tmp
, `/bin
- Processes
&
,bg
,fg
,tmux
,screen
,ps
- Scheduling
cron
- Shells
bash
,sh
- Environment Variables and Arguments,
$0
,TERM
- Base Conversions, Encoding, and Hashing
base64
,md5sum
- Compression and Archiving
tar
,gzip
,bzip2
- Basic networking Concepts and Utilities
nc
,netstat
- Scripting
- Conditionals, Comparisons, Loops
- Optionally parallelization through
parallel
- Git Concepts and Subcommands
checkout
,branch
,tag
,add
,commit
,push