DEV Community

Yulin Chen
Yulin Chen

Posted on • Updated on

OverTheWire Bandit Levels 19-34 Hints and Notes

Table of Contents

Level 19 - setuid
Level 20 - nc
Level 21 - cron
Level 22 - Script
Level 23 - Script
Level 24 - for loop
Level 25 - more
Level 26 - shell
Level 27 - git clone
Level 28 - git log
Level 29 - git branch
Level 30 - git tag
Level 31 - gitignore
Level 32 - bash
Level 33


Level 19

Use the setuid binary in the homedirectory to access /etc/bandit_pass/bandit20

ls -l on the homedirectory file you will see letter s in the permissions in place of the user execution.

Setuid, which stands for set user ID on execution, is a special type of file permission in Unix and Unix-like operating systems such as Linux and BSD. It is a security tool that permits users to run certain programs with escalated privileges.

When an executable file's setuid permission is set, users may execute that program with a level of access that matches the user who owns the file. For instance, when a user wants to change their password, they run the passwd command. The passwd program is owned by the root account and marked as setuid, so the user is temporarily granted root access for that limited purpose.

Here, the homedirectory bandit20-do has the setuid permission set, and /etc/bandit_pass/bandit20 can only be read by the owner bandit20. We can open /etc/bandit_pass/bandit20 at the runtime of bandit20-do binary:

./bandit20-do cat /etc/bandit_pass/bandit20
Enter fullscreen mode Exit fullscreen mode

Level 20

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)

1.Check which ports are in use

nmap localhost
Enter fullscreen mode Exit fullscreen mode

2.Open a connection on an unused port and send current password

echo password | nc -l -p 60000 &
Enter fullscreen mode Exit fullscreen mode

The & at the end allows you to listen to port in the background, so you can run the next command in the same terminal.
3.Run the setuid binary on the port

./suconnect 600000
Enter fullscreen mode Exit fullscreen mode

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

Let's look at what is inside the crontab file for bandit22. A crontab file is a simple text file containing a list of commands meant to be run at specified times.

cat cronjob_bandit22
Enter fullscreen mode Exit fullscreen mode

Typical format for a cron job is:
Minute(0-59) Hour(0-24) Day_of_month(1-31) Month(1-12) Day_of_week(0-6) Command_to_execute

Cron offers some special strings, which can be used in place of the five time-and-date fields:

  • @reboot, run once at startup
  • @yearly, run once a year, "0 0 1 1 *"
  • @annually, same as @yearly
  • @monthly, run once a month, "0 0 1 * *"
  • @weekly, run once a week, "0 0 * * 0"
  • @daily, run once a day, "0 0 * * *"
  • @midnight, same as @daily
  • @hourly, run once an hour, "0 * * * *"

program &> /dev/null, which will redirect both stderr and stdout to /dev/null, so nothing will be printed on screen. /dev/null is a special file (i.e. a virtual device, known as the null device) that’s present in every single Linux system and purely used to write. Everything you write to /dev/null will be discarded.

Now let's see the bash script that is been executed

cat /usr/bin/cronjob_bandit22.sh
Enter fullscreen mode Exit fullscreen mode
  • #!/bin/bash is called a shebang line, this script runs in the bash environment
  • chmod 644 /tmp/t7O6lds9S0RqQh9aMcz6ShpAoZKF7fgv chmod 644 means only the owner are allowed to write/modify, read-only for others (group) included
  • cat /etc/bandit_pass/bandit22 > /tmp/t7O6lds9S0RqQh9aMcz6ShpAoZKF7fgv gets password from bandit22 and redirects stdout to /tmp/t7O6lds9S0RqQh9aMcz6ShpAoZKF7fgv

To view the password for next level:

cat /tmp/t7O6lds9S0RqQh9aMcz6ShpAoZKF7fgv
Enter fullscreen mode Exit fullscreen mode

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

Output from 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
Enter fullscreen mode Exit fullscreen mode

The first line is shebang as usual, defining the bash environment in which the script is run.

The second line assigns output from command whoami to variable myname.

The next line uses a new command md5sum.

When downloading files, particularly installing files from websites, it is good to verify that the download is valid. A website will often display a hash value for each file to make sure the download is completed correctly. md5sum is one of the tools you can use to validate file transfer.

If a file has changed, the checksum will throw a warning. Here we're simply displaying the hash for text I am user $(whoami), clean the output with cut and assign the hash to variable mytarget.

Output from echo I am user $myname | md5sum:

8169b67bd894ddbb4412f91573b38db3  -
Enter fullscreen mode Exit fullscreen mode

There's an extra dash after the hash. cut -d cut -d ' ' -f 1 specifies the delimiter (-d) as space (' '), and select the first field with -f. -d ' ' separates the hash and dash since there's a space between them, returns the hash only.

When this script is being run, it will write the currently logged-on user’s password into a file.

We can see the password is redirected to /tmp/hash. There is a caveat here, the currently logged-on user is bandit22, but we want the password for bandit23:

echo I am user bandit23 | md5sum | cut -d ' ' -f 1
Enter fullscreen mode Exit fullscreen mode

This gives us the file name in tmp directory that stores bandit23 password. Now we just need to view it using cat /tmp/hash.


Level 23

Follow the same procedure as the previous level, the shell script running in /usr/bin/cronjob_bandit24.sh:

#!/bin/bash

myname=$(whoami)

cd /var/spool/$myname
echo "Executing and deleting all scripts in /var/spool/$myname:"
for i in * .*;
do
    if [ "$i" != "." -a "$i" != ".." ];
    then
        echo "Handling $i"
        owner="$(stat --format "%U" ./$i)"
        if [ "${owner}" = "bandit23" ]; then
            timeout -s 9 60 ./$i
        fi
        rm -f ./$i
    fi
done
Enter fullscreen mode Exit fullscreen mode

First the shebang is declared, then myname saves user who is currently logged on the system. Goes inside the directory /var/spool/$myname, prints the task it is about to carry out on screen with echo.

The for loop for i in * .* matches all files in the currently directory, including hidden files starting with a dot. for i in * returns all regular files in the working directory, for i in .* returns all hidden files (starting with a dot).

if [ "$i" != "." -a "$i" != ".." ] skips the special files . and .. in the for loop.

The stat command displays file status. Try stat -x file to see the output from stat. --format option allows you to design the desired output from stat. %U format specifier returns the owner of the file/file system. There are many versions of stat, on Mac, the equivalent command is stat -f %Su file.

The timeout allows the user to execute a command and then terminate it after a set time has passed. The timeout command uses the “SIGTERM” to stop a process, but many processes ignore the “SIGTERM” signal. To forcefully terminate a process using the “SIGKILL” signal -s 9, cannot be ignored by any process.

Here, it checks if the owner of file is bandit23. If so, execute the file, and terminate after 60 seconds.

At the end of the for loop, it removes each file/folder.

  1. Find where the password is stored
    From previous levels, we know that all passwords are in /etc/bandit_pass. Password for bandit24 will be in /etc/bandit_pass/bandit24. However, we get a permission denied when we directly cat /etc/bandit_pass/bandit24.

  2. Make the bash script
    We do have permissions to create, read and write files in /tmp, make a new folder in tmp with mybandit23.sh that contains the following bash script (/tmp/dir23/mybandit23.sh):

    #!/bin/bash                                             
    cat /etc/bandit_pass/bandit24 > /tmp/dir23/bandit24pass       
    

    Make the file executable by changing the mode to have all permissions:

    chmod 777 mybandit23.sh
    

    You might want to change the permissions of the entire dir23 folder to make it writable by others.

  3. Copy the bash script to be run by bandit24

    We know that if we make an executable script in /var/spool/bandit24, it will be run with a timeout of 60 seconds.

    cp mybandit23.sh /var/spool/bandit24/mybandit23.sh
    

    Check our bash script is there:

    cat /var/spool/bandit24/mybandit23.sh
    

Wait until the shell script file in the folder is deleted, and check the /tmp/dir23 directory, a bandit24pass file should appear. cat bandit24pass to get the password.


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.

nc localhost 30002 asks for the password and a 4 digit pin code on a single line. The steps we need to take are get all combinations of the password and pins, pass each one to port 30002.

Navigate to /tmp where we are granted write permissions, and make a new folder called mydir24. Inside /tmp/mydir24, create a shell script bruteforce.sh that would loop through 4 digit numbers and append each one to pins.txt

#!/bin/bash
for i in {0000..9999}
do 
    echo "password $i" >> pins.txt
done
Enter fullscreen mode Exit fullscreen mode

Make the bash script executable by user:

chmod 700 bruteforce.sh
Enter fullscreen mode Exit fullscreen mode

Now run the script to create pins.txt, and give the output to port 30002:

nc localhost 30002 < pins.txt
Enter fullscreen mode Exit fullscreen mode

or

cat pins.txt | nc localhost 30002
Enter fullscreen mode Exit fullscreen mode

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.

In the home directory of bandit25, there is a bandit26.sshkey private key file,

ssh -i bandit26.sshkey bandit26@localhost
Enter fullscreen mode Exit fullscreen mode

the connection closes immediately. Let's take the hint from the task and checkout what shell bandit26 is using.

The /etc/passwd file is a text file with one record per line, each describing a user account. It consists of 7 fields, the last field is the program that is started every time the user logs into the system, i.e. the shell for an interactive user.

cat /pwd/passwd | grep bandit26
Enter fullscreen mode Exit fullscreen mode

Instead of /bin/bash, bandit26 uses /usr/bin/showtext. A quick cat /usr/bin.showtext gives

#!/bin/sh

export TERM=linux

more ß/text.txt
exit 0
Enter fullscreen mode Exit fullscreen mode

The code that terminates the shell is exit 0, and the only command that runs before is more ~/text.txt.

more command is used to view the text files in the command prompt, displaying one screen at a time in case the file is large.

Minimise your terminal before ssh into bandit26 to trigger more. The large “bandit26” ASCII art banner will force a “more” message to prompt you to continue. Press v to enter the default vim text editor, and type ":e /etc/bandit_pass/bandit26" to open bandit26 password file within vim.


Level 26

The shell still immediately terminates after ssh login. Do the same trick again, minimise the terminal window and then ssh login. Press "v" to enter vim and change shell type ":set shell=/bin/bash". Now type ":shell" should take you back to the bash shell. Do "ls -l" to see all files in the home directory.

The file "bandit27-do" has the special permission for the user access level, which means we can directly "cat" the password in /etc/bandit_pass/bandit27 (only bandit27 has the read permission) while we execute bandit27-do. A file with SUID always executes as the user who owns the file, regardless of the user passing the command.

./bandit27-do cat /etc/bandit_pass/bandit27
Enter fullscreen mode Exit fullscreen mode

Level 27

There is a git repository at ssh://bandit27-git@localhost/home/bandit27-git/repo. 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.

ssh login to bandit27 as usual, make a new directory within /tmp/ where we have the write permission.

mkdir -p /tmp/dir27
Enter fullscreen mode Exit fullscreen mode

cd into the directory, then

git clone ssh://bandit27-git@localhost/home/bandit27-git/repo
Enter fullscreen mode Exit fullscreen mode

Enter the password when you're prompted on the command line. There is only one file contained in the repository, cat the file to see bandit28 password.


Level 28

There is a git repository at ssh://bandit28-git@localhost/home/bandit28-git/repo. 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.

Same procedure as the previous level, mkdir -p /tmp/dir28, then git clone ssh://bandit28-git@localhost/home/bandit28-git/repo. This time when you cat the README.md, it doesn't show the password. Let's have look at the commit history to see if there's any clue. Type following command within the repository:

git log
Enter fullscreen mode Exit fullscreen mode

commit edd935d60906b33f0619605abd1689808ccdd5ee
Author: Morla Porla morla@overthewire.org
Date: Thu May 7 20:14:49 2020 +0200
fix info leak
commit c086d11a00c0648d095d04c089786efef5e01264
Author: Morla Porla morla@overthewire.org
Date: Thu May 7 20:14:49 2020 +0200
add missing data
commit de2ebe2d5fd1598cd547f4d56247e053be3fdc38
Author: Ben Dover noone@overthewire.org
Date: Thu May 7 20:14:49 2020 +0200
initial commit of README.md

There are actually 3 commit pushes for the repository. From the commit messages, it looks like the second commit probably contains the password. To see the actual changes made in each commit, do git log -p; Alternatively, to display changes in the second commit only, do git show followed by the commit hash:

git show c086d11a00c0648d095d04c089786efef5e01264
Enter fullscreen mode Exit fullscreen mode

Level 29

There is a git repository at ssh://bandit29-git@localhost/home/bandit29-git/repo. 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.

Same procedure as the previous level, mkdir -p /tmp/dir28, then git clone ssh://bandit28-git@localhost/home/bandit28-git/repo. This time when you cat the README.md, in place of password it shows no passwords in production!. It implies this is the production branch, there is probably a development branch. To see all existing branches:

git branch -a
Enter fullscreen mode Exit fullscreen mode

switch to the dev branch:

git checkout dev
Enter fullscreen mode Exit fullscreen mode

see the README.md file on this branch:

cat README.md
Enter fullscreen mode Exit fullscreen mode

Level 30

There is a git repository at ssh://bandit30-git@localhost/home/bandit30-git/repo. 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.

Same procedure as previous levels, but this time there is nothing useful contained in README.md...neither git branch or git log has anything interesting. Do ls -al to see the hidden files, cd .git and search for anything that looks like a clue. The packed-refs file contains reference to the master branch, as well as a tag called secret. Let's check existing tags:

git tag
Enter fullscreen mode Exit fullscreen mode

Double check the tag reference:

git show-ref --tags
Enter fullscreen mode Exit fullscreen mode

Tags are ref's that point to specific points in Git history. Tagging is generally used to capture a point in history that is used for a marked version release (i.e. v1. 0.1). A tag is like a branch that doesn't change. Unlike branches, tags, after being created, have no further history of commits.

Reveal the content of the tag using git show:

git show secret
Enter fullscreen mode Exit fullscreen mode

Level 31

There is a git repository at ssh://bandit31-git@localhost/home/bandit31-git/repo. 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.

Same procedure as previous levels, the actual instructions are in README.md of the repository. The task for this level is to push a text file to the remote repository. Inside of the repository, make the key.txt file with the required text.

Now the file exists locally, to push to remote, first step is to add the file to stage:

git add .
Enter fullscreen mode Exit fullscreen mode

Double check the file has been added:

git status
Enter fullscreen mode Exit fullscreen mode

and it hasn't! Let's see everything inside the repository:

ls -al
Enter fullscreen mode Exit fullscreen mode

There is a .gitignore file which tells git not to track the changes in certain types of files. Remove the line from .gitignore, now try add to stage again, then git commit:

git commit -m "adding my key file"
Enter fullscreen mode Exit fullscreen mode

and push the changes:

git push
Enter fullscreen mode Exit fullscreen mode

Level 32

After you ssh login, you will enter UPPERCASE SHELL where non of the terminal commands work anymore. To escape out of the shell and spawn a new shell, use the special parameter:

$0
Enter fullscreen mode Exit fullscreen mode

display password as usual:

cat /etc/bandit_pass/bandit33
Enter fullscreen mode Exit fullscreen mode

$0 Expands to the name of the shell or shell script. This is set at shell initialization.

If Bash is invoked with a file of commands, $0 is set to the name of that file.

If Bash is started with the -c option, then $0 is set to the first argument after the string to be executed, if one is present. Otherwise, it is set to the filename used to invoke Bash, as given by argument zero.

What is the meaning of $0 in the Bash shell


Level 33

ssh bandit33@bandit.labs.overthewire.org -p 2220
Enter fullscreen mode Exit fullscreen mode

password: c9c3199ddf4121b10cf581a98d51caee

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.

If you have an idea for an awesome new level, please let us know!

Discussion (0)