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
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
2.Open a connection on an unused port and send current password
echo password | nc -l -p 60000 &
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
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
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
-
#!/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 frombandit22
and redirects stdout to/tmp/t7O6lds9S0RqQh9aMcz6ShpAoZKF7fgv
To view the password for next level:
cat /tmp/t7O6lds9S0RqQh9aMcz6ShpAoZKF7fgv
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
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 -
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
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
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.
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 directlycat /etc/bandit_pass/bandit24
.-
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. -
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
Make the bash script executable by user:
chmod 700 bruteforce.sh
Now run the script to create pins.txt, and give the output to port 30002:
nc localhost 30002 < pins.txt
or
cat pins.txt | nc localhost 30002
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
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
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
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
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
cd into the directory, then
git clone ssh://bandit27-git@localhost/home/bandit27-git/repo
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
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
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
switch to the dev branch:
git checkout dev
see the README.md file on this branch:
cat README.md
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
Double check the tag reference:
git show-ref --tags
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
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 .
Double check the file has been added:
git status
and it hasn't! Let's see everything inside the repository:
ls -al
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"
and push the changes:
git push
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
display password as usual:
cat /etc/bandit_pass/bandit33
$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
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!
Top comments (0)