a key
photo by Michael Dziedzic via unsplash

Bandit Primer

SSH and RSA

The bandit wargames make frequent usage of ssh (secure shell) to log into the game server. Secure shell is a way of running commands on a remote server. To initiate an ssh connection, a command is typed in the terminal if you’re using macos or linux, or the powershell if you’re using a windows operating system.

ssh [user]@[ip address or hostname]

For example, if I want to connect as user bandit0 to the bandit wargames server, I can execute the following command.

ssh -p 2220 bandit0@bandit.labs.overthewire.org

Additional flags can be used such as the -p flag to specify a port and the -i flag to specify a key file used for passwordless entry.

SSH makes use of asymmetric encryption for purposes of authenticity and confidentiality. What does this mean? Let’s take RSA, an asymmetric encryption algorithm as an example. It is called asymmetric because it uses two keys. One key is used to encrypt the contents and the other is used to decrypt it. This is different than symmetric algorithms which use a single key to encrypt and decrypt contents. One key is known as the private key and the other is known as the public key. Private keys are never shared and are kept secret forever. Public keys on the other hand can be shared.

What is the benefit of two keys? Imagine we have two people: Mac and Charlie. Mac wants to send Charlie encrypted information in which only Charlie can decrypt it, in other words he wants confidentiality. Mac can encrypt a message using Charlie’s PUBLIC key. Then, Charlie can decrypt it using Charile’s PRIVATE key. Other people might know of Charlie’s PUBLIC key, but only Charlie can decrypt the message because no one has Charlie’s PRIVATE key.

Another usage is Authenticity. What if Charlie is sending a reply to Mac and he wants to ensure that Mac knows that the message is definately coming from Charlie (not an imposter). Charlie can encrypt the message using his own (Charlie) PRIVATE key. Then, Mac can try to decrypt the message using Charlie’s PUBLIC key. If it works, he knows that the message came from Charlie. In this situation, other people could theoretically intercept the message and decrypt it with Charlie’s public key, in other words, it doesn’t make the message confidential, it only ensures that Charlie was the one who sent the message.

Now Mac is sending a reply to Charlie and he wants Authenticity and Confidentiality, how can he achieve this? Mac can encrypt his message using his own (Mac) private key. Then, he can encrypt the message again using Charlie’s public key! When Charlie receives the message, he can decrypt it using his own (Charlie) private key and than decrypt it again using Mac’s public key. At his point he knows that the message is an authentic Mac message and that no one intercepting the message could have decrypted it!

SSH makes usage of such asymmetric encryption in order to secure traffic from your computer to the remote server. A good way to practice these concepts is to make a ubuntu VM using something like virtualbox. Here are some research topic to google.

concepts:

the known_hosts file
ssh fingerprint
ssh with an identity (rsa key) file (-i flag)
preventing password authentication through ssh

commands:

man ssh-keygen
man ssh
man scp

files and directories:

.ssh/
known_hosts
/etc/ssh/
/etc/sshd_config
/var/log/auth.log

Level 0

Our first task is to SSH (secure shell) into the game server. This can be done using the ssh command with the port specified. After that, we can use cat to print the contents of the readme to the terminal.

ssh -p 2220 bandit0@bandit.labs.overthewire.org
cat readme

Level 1

For this level we need to view the contents of a file that beings with a dash. We can reference this file by first specifying the current directory using ./. We can then cat the file as normal.

cat ./-

Level 2

This level introduces a file with spaces in the name. We can access this file by escaping the spaces. Keep in mind that pressing tab will autocomplete the name, which is easier than manually typing in the backslashes.

cat spaces\ in\ this\ filename

Level 3

For Level 3, we need to print the contents of a hidden file. Using certain flags, we can modify the ls command to include hidden contents.

cd inhere
ls -a
cat .hidden

Level 4

Level 4 asks us to find and print the ASCII file in the directory. We can use the file command to determine the file types of the files. The * wildcard character can be used to reference all of the files in the directory.

cd inhere
ls
file ./*
cat ./-file07

Level 5

To clear this level, we have to find a file with certain parameters. Luckily, the find command is awesome.

find . -type f -size 1033c

Level 5 Alt

Here is the solution I used before I learned about the file attribute flags demonstrated above. I used two python modules for this one, Subprocess and RE. Subprocess allows us to run bash commands and regular expressions will help us filter our results. First, we’ll run find to list the entire contents of the inhere directory. Then, we’ll use split() to create a list of files. After that, we’ll build our lambda function which will run the stat command on a particular file. The stat command will list attributes regarding the file in question, including the size of the file. Now, we can construct our re string which we’ll use to filter the results. The file we are looking for has a size of 1033 bytes. Finally, we can use a list comprehension to filter our results, exit the interpreter using exit(), and cat the appropriate file.

python3
import re
import subprocess
l0 = subprocess.run(["find", "."], capture_output=True).stdout.decode("ascii")
l0 = l0.split()
f0 = lambda x: subprocess.run(["stat", x], capture_output=True).stdout.decode("ascii")
res = "Size: 1033"
[x for x in l0 if re.findall(res, f0(x))]

Level 6

For this level we can utilize useful flags from the find command. Searching in root is going to give us a lot of permission errors so we can send them to the oblivion of /dev/null.

find / -type f -size 33c -user bandit7 -group bandit6 2>/dev/null

Level 7

Level 7 tells us that the password is next to a certain word in a text file. We can use grep to search within the text file for that word.

grep "millionth" data.txt

Level 8

We can use the power of the uniq command to solve this level. The -c flag will count the number of occurences of each line and insert it into the printed result. We can then pipe this into grep to find results that appeared only once.

cat data.txt | sort | uniq -c | grep "1 "

Level 9

For level 9, we can pipe strings into a grep.

strings data.txt | grep "== "

Level 10

The base64 command finishes this level.

base64 -d data.txt

Level 11

For this one, we can use the tr command to translate the characters by the desired amount. Moving the character a 13 places results in a n. Moving the character m, result in a z, meaning that m is the last character we can rotate before we have to circle back to a. Moving n 13 places results in an a as expected. With this knowledge, we can repeat the same thought process for uppercase letters.

echo [string] | tr [a-mn-zA-MN-Z] [n-za-mN-ZA-M]

Level 11 Alt

Once again, I’ll show the method I used before learning about the tr command. We can start the python interpreter by entering python3 into the terminal. Then, we can create a variable that stores the string we want to decode. Now, let’s convert the string into a list of numbers using a list comprehension, the ord function will transpose the characters into their numerical representation. Now, let’s do some digging to find out what the numerical representations are for the lower and upper ranges of characters we could potentially come across. For example A is 65 whereas Z is 90. Let us now make a function that adds two numbers and circles back to the lower range if the result exceeds the upper range. One way to think about this is adding 1 to the character Z. If we add 1 to Z, we want to get A back, in other words, 90 + 1 should equal 65. After crafting our function, we need to make another function to ensure that special characters and numbers are ignored. After that, let’s make a function that utilized both of the previous functions to correctly rotate the numbers. Finally, we can use the join function on a list comprehension to get our result.

python3
s1 = "[string contents]"
l1 = [ord(s1[x]) for x in range(len(s1))]
ord('a') #97
ord('z') #122
ord('A') #65
ord('Z') #90
ord(' ') #32
addwithrange = lambda num,by,lower,upper: num+by if num+by < upper+1 else numb+by-upper+lower-1
isspecial = lambda x: True if x < 65 or x > 122 or (x > 90 and x < 97) else False
getnewnum = lambda num,by: num if isspecial(num) else addwithrange(num,by,65,90) if num<91 else addwithrange(num,by,97,122)
"".join([chr(getnewnum(x, 13)) for x in l1])

Level 12

For this level we need to un-hexdump a file and then decompress it a bunch of times. Let’s start by making a temp folder to perform our commands.

cd $(mktemp -d)
mv ~/data.txt data

We can use xxd to reverse the hexdump.

xxd -r data datar

Let’s use file to determine the type of file. The shell tells us that it gzip compressed. So, let’s rename it to use the gz file extension and then decompress it.

file datar
mv datar data.gz
gunzip data.gz

Using file again, we can see that it is bzip2 compressed.

file data
bzcat data > data2

We will have to decompress the file a couple more times after this. Make sure to use file to see what type of decompression you should perform after each decompression. At certain points, in addition to gunzip and bzcat, you will have to use tar -xf as well.

Level 13

Upon logging into bandit13 and using ls, we are greeted with a single file. The file is a private key for ssh purposes. Let’s copy it back to our personal machine and use it to ssh into level 14. Once we attempt to use the key, we will get an error stating that the key’s permissions are too permisive, we can remedy that with chmod.

exit
scp -P 2220 bandit13@bandit.labs.overthewire.org:sshkey.private .
chmod 400 sshkey.private
ssh -p 2220 -i sshkey.private bandit14@bandit.labs.overthewire.org

Level 14

For this level we need to submit the current password to a certain port. We can use netcat for this.

cat /etc/bandit_pass/bandit14 | nc localhost 30000

Level 15

For this level we need to submit the current password to a specific port using SSL. We can use openssl for this.

cat /etc/bandit_pass/bandit15 | openssl s_client -connect localhost:30001 -ign_eof 

Level 16

First, lets find which ports are open. We can use the nc command with the -zv flags to scan a range of ports. 2>&1 is used to send errors into the standard output and grep is used to filter out connections that were refused. Finally, we can use awk to print the specific column of information we want: the port number. Now that we have the port number saved to a variable, we can view the results and then one by one, test them using the openssl command. The correct port will give us a private key which we can use as an identity file (ssh -i) when we connect to the next level. After creating the file and copying the key into it, we need to alter the permissions using chmod.

ports=$(nc -zv localhost 31000-32000 2>&1 | grep -v "refused" | awk '{print $5}')
echo $ports
cat /etc/bandit_pass/bandit16 | openssl s_client -connect localhost:31790 -ign_eof
touch [keyfile]
#paste key into keyfile
chmod 400 [keyfile]

Level 17

For this level, we can the diff command to see what lines are different among the two files. We could also use vim with the -d flag to see a larger representation.

diff passwords.new passwords.old

Level 18

Level 18 kicks us out as soon as we ssh, but that’s okay, we can run commands using ssh.

ssh -p 2220 bandit18@bandit.labs.overthewire.org "cat readme"

Level 19

This level introduces special permissions. If we take a look at the executable file, we can see that the file’s group is bandit19 (us) and the user is bandit20. However, the special user bit (SUID) is set for this file because the ls -l result is depicting an s where an x would normally be. This means that when we execute the file, we will be treated as bandit20, not bandit19. We can show this by executing the whoami command. With this information, we can print the next password.

ls -l
./bandit20-do
./bandit20-do whoami
./bandit20-do cat /etc/bandit_pass/bandit20

Level 20

nc -lp [port] < /etc/bandit_pass/bandit20
./suconnect [port]

Level 21

For level 21, we need to dig into some cron jobs. Once we cd to the /etc/cron.d directory, we can cat the contents of the files. With this information, we can cd to the directory of the shell scripts in question: /usr/bin. A ls -l cron* command will list the right files along with permissions. Perusing the permissions will tell us that we have group read access to a particular script which we can analyze with vim. Analyzing the file will tell us that the script is putting information into a specific file, we can cat that file to get the information we need.

cd /etc/cron.d
cat cron*
cd /usr/bin
ls -l cron*
vi [file]
cat [path]

Level 22

Based on our experience playing these bandit games, we can assume that the next password is related to bandit23. Using similar detective skills from the previous level, we can analyze the relevant files and end up back in /usr/bin to analyze the bandit23 shell script being run. Looking at the script we can see that its using the result of the whoami command in several places. Running the whoami command in the terminal will return bandit22. In other words, if we run the script as bandit22, it will pull the bandit22 password and input it into a file. However, we want the bandit23 password, not the 22. Looking back at the relevant file in /etc/cron.d, we can see that the cron job is being run every minute and that it will run as user bandit23! Let’s swing back to the script and see where it’s putting the file. Once again, it’s using the result of the whoami command and the md5sum command to create the directory name. So, we can find the directory by running the commands as if we were bandit23!

echo "I am user bandit23" | md5sum
cat /tmp/[path]

Level 23

This level follows a similar pattern to the previous cron oriented challenges. We should check out the bandit24 cron job in /etc/cron.d to discover the location of the script being run (/usr/bin), and then analyze that script. The script is running and then deleting scripts placed in /etc/spool/bandit24/foo. So theoretically, all we have to do is make a script that will cat the contents of the bandit24 password file and then save it to a file. After we make our script, we should use chmod to make it executable and then cp the script into the foo directory.

#!/bin/bash
cat /etc/bandit_pass/bandit24 >> /tmp/blarg.txt

Level 24

For this level we need to brute force a 4-digit pin and send it along with a password to a specific port.

echo "$(cat /etc/bandit_pass/bandit24) 1234" | nc localhost 30002

Let’s make a script to automate the brute force aspect of it.

#!/bin/bash
pass=$(cat /etc/bandit_pass/bandit24)
for i in {0000..9999} ; do
echo "$pass $i" >> [textfile]
done

Then, you can make it executable and execute it.

chmod 700 [script]
./[script]

Now that we have our large text file, we can pipe it into netcat.

cat [textfile] | nc localhost 30002 > [textfile2]

After running this command, I waited for some time. The command appeared to hang so I used control-c to stop it. I then examined the file using word count with the line flag set.

wc -l [textfile2]
tail [textfile2]

The command had created roughly 6200 lines before hanging. After some thinking, I decided to just delete the first 6000 lines of the large text file, thinking that perhaps there was some kind of limit. I did this with vim.

vi [testfile]

Once in vim, I typed dd to delete the first line. Then, I typed 6000 and . to repeate the dd command 6000 more times. I then saved and exited and retried catting the test file into nc and this time it worked. I opened the result in vim, hit G to go to the bottom of the file, and got the answer.

Level 25 and 26

There’s always something to learn in Linux! Using ls in the home directory shows us a single file, it’s an identify file for use with ssh. However, let’s do some digging first. According to the instructions, there’s something odd about the given shell for bandit26. We can see everyone’s shell by catting the passwd file, let’s do that.

cat /etc/passwd | grep "bandit26"

Upon doing this, we can see that instead of the usual /bin/bash, a different shell is being referenced. Let’s navigate to that directory and cat the contents of that file.

cat /usr/bin/showtext

The script in question is using the more command. The more command is similar to the cat command but is used for longer files. Something I didn’t know is that if the amount of text is small enough, the more command will behave similarly to cat while if the text is quite long, it will enter the interactive mode similar to less. Neverless, let’s forget about that for a second and try simply using that identify file. We can exit and then use scp to copy the identify file to our machine.

exit
scp -P 2220 bandit25@bandit.labs.overthewire.org:[identifyfile] .

Now let’s try to log into bandit26.

ssh -p 2220 -i [identifyfile] bandit26@bandit.labs.overthewire.org

Similar to a previous level, we immediately get kicked out. Let’s use that more knowledge now. Modify your terminal window so that’s it’s very small and repeat the command, this time it should enter the interactive mode. At this point we can type v to enter vim. Another thing I didn’t know is that you can modify your shell from vim and even create a shell.

v #should be in vim now
:set shell=/bin/bash
:shell #should have a shell after this command
ls
./bandit27-do cat /etc/bandit_pass/bandit27

Level 27

For this level we need to clone a git repo. Let’s make temporary place to put our stuff first.

mktemp -d
cd [whatever path it made]

Now let’s run a git command to clone the repo. Don’t forget to specify the port as typed below!

git clone ssh://bandit27-git@localhost:2220/home/bandit27-git/repo

After typing in the current level’s password when prompted, we can investigate the repo and easily find the next password!

Level 28

This one looks similar to the last one! Let’s start by making our temp directory.

cd $(mktemp -d)

Now let’s clone the bandit28 repo (using port 2220).

git clone [bandit28repo] 

Upon investigating the repo, we can see that the readme does not provide the password. Let’s look at the log.

git log

The log mentions something about fixing a leak. Let’s look at the commit before the leak was fixed.

git checkout [previous commit id]

Now, when we look at the readme, the password is exposed!

Level 29

More git stuff! Follow the previous instruction and get your git repo then start investigating. This repo has multiple branches. We can look at different branches by using git commands.

git branch -a #list branches
git switch [branch]

If you switch to the dev branch and take a look at the readme, you can find the password!

Level 30

As usual, let’s clone the git repo and start investigating. This time the repo is quite barebones. It seems like git logs and branches won’t help us here. Git has many ways of storing and organizing data. One of these methods is using tags. Tags are used to mark important moments in the repo’s history; like a new version. Let’s see if there are any tags, then we can use git show command to see information about the tag.

git tag
git show [tagname]

Level 31

Clone the repo and look at the readme. This time we get to push stuff! First, let’s see what our current brach is.

git branch

We’re on the right branch so now, let’s make the file.

touch key.txt
echo May I come in? >> key.txt

Before we go further, let’s make sure our gitignore file is in order. The gitignore file is used to filter some files from getting into the online repo. The gitignore file should be in the root git directory.

ls -lah
vi .gitignore

The gitignore is filtering out txt files! In vim, we can hit dd to delete that line, then wq to write and quit. Now let’s add and commit the file to the local repo. After commiting, we will be asked to create a commit message.

git add key.txt
git commit key.txt

Now, the file is in our local repo but we have to push it to the remote one. We can do this using the git push command. After doing this, we will get our next password!

git push origin master

Level 32

This level puts us into a strange shell in which we must escape. Everything we type becomes uppercase. In Linux, commands are case sensitive so LS for example will not work. This puts us in a pickle. How are we supposed to execute commands like this? The trick to this level is environmental variables. Open a terminal on your personal machine.

printevn

These variables are already uppercase! We can try various variables.

$path
$shell

The variable we want is $0, it stores the name of the shell.

$0

Now we should be free to type commands as we wish, let’s try catting the contents of the password file.

cat /etc/bandit_pass/bandit33