Over The Wire (Bandit) 🧑‍💻 (2024-07-17)

Link

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 into grep 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 into uniq.
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 from cat.
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 into netcat 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 throw suconnect'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 yields bandit26: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 forces more 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 port 2220. The password for the user bandit30-git is the same as for the user bandit30. 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 named secret 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, then push.
  • 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
  • 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