Challenge Information

Platform: OverTheWire
WarGame: Bandit
Levels: 25-33

Level 25

Objective: 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.

Solution: As always, we begin with reconnaissance – checking the current directory and user context. This reveals that we have access to bandit26’s private SSH key, located in the home directory.

Following the task description, we check which shell bandit26 is using:

cat /etc/passwd | grep "bandit26"
Listing 1 - Checking bandit26's shell configuration

Examining the file reveals the following:

# file /usr/bin/showtext

#!/bin/sh

export TERM=linux

exec more ~/text.txt
exit 0
Listing 2 - The showtext binary

In essence, upon login, the system runs the more command on text.txt in the home directory rather than spawning a bash shell. Once the file is fully read, the session exits.

If we attempt a standard SSH login using bandit26’s private key, we are automatically logged out. To prevent this, we must ensure that more cannot display the entire file at once. We accomplish this by resizing the terminal window to a smaller dimension before connecting via SSH.

Once trapped in more, we press v to invoke the vi editor, which opens text.txt. Good news: we can resize the window to restore visibility. Bad news: we must also escape vi.

Normally, we could execute shell commands from vi using :!{command}, but since the shell is still configured to /usr/bin/showtext, we would return to the starting point. To circumvent this, we use the set shell command within vi to specify a different shell:

# inside the vi editor
:set shell=/bin/bash
Listing 3 - Configuring the shell inside vi

With the shell properly configured, we retrieve the flag:

# inside the vi editor
:!cat /etc/bandit_pass/bandit26
Listing 4 - Running commands inside vi

To exit vi and obtain a standard bash shell, we enter :shell.

Level 26

Objective: Good job getting a shell! Now hurry and grab the password for bandit27!

Solution: With a standard shell connection established, reconnaissance reveals an executable named bandit27-do in the home directory. Running it without arguments displays usage information:

# running the executable
./bandit27-do 
Run a command as another user.
  Example: ./bandit27-do id
Listing 5 - Contents of the bandit27-do executable

Since the SUID bit is set on this binary, we can leverage its elevated privileges to retrieve the next flag:

./bandit27-do cat /etc/bandit_pass/bandit27
Listing 6 - Using the SUID binary to run elevated commands

Level 27

Objective: 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.

Solution: One solution is to clone the repository to our local machine:

# on your local machine—clone the repository
git clone ssh://[email protected]:2220/home/bandit27-git/repo
Listing 7 - Cloning a Git repository

Examining the cloned files reveals the next flag inside README.md.

Level 28

Objective: 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.

Solution: We repeat the cloning process from the previous level. Upon examination, README.md contains the following:

# Bandit Notes
Some notes for level29 of bandit.

## credentials

- username: bandit29
- password: xxxxxxxxxx
Listing 8 - Notes left behind in the README file

No flag is present here. However, the Git logs reveal something interesting:

# get the git logs
git log
commit 899ba88df296331cc01f30d022c006775d467f28 (HEAD -> master, origin/master, origin/HEAD)
Author: Morla Porla <[email protected]>
Date:   ...

    fix info leak

commit abcff758fa6343a0d002a1c0add1ad8c71b88534
Author: Morla Porla <[email protected]>
Date:   ...

    add missing data

commit c0a8c3cf093fba65f4ee0e1fe2a530b799508c78
Author: Ben Dover <[email protected]>
Date:   ...

    initial commit of README.md
Listing 9 - Potential lead within Git logs

The commit message “fix info leak” suggests that sensitive data was previously exposed. To examine the changes introduced by that commit, we use git show with the appropriate hash:

# show the commit message and textual diff
git show 899ba88df296331cc01f30d022c006775d467f28
commit 899ba88df296331cc01f30d022c006775d467f28 (HEAD -> master, origin/master, origin/HEAD)
Author: Morla Porla <[email protected]>
Date:   ...

    fix info leak

diff --git a/README.md b/README.md
index b302105..5c6457b 100644
--- a/README.md
+++ b/README.md
@@ -4,5 +4,5 @@ Some notes for level29 of bandit.
 ## credentials
 
 - username: bandit29
-- password: <redacted-flag>
+- password: xxxxxxxxxx
Listing 10 - Checking applied changes

The password is easily recovered by examining the differences between commits. Alternatively, we could have used git diff:

git diff 899ba88df296331cc01f30d022c006775d467f28 abcff758fa6343a0d002a1c0add1ad8c71b88534
Listing 11 - Checking differences between commits

Level 29

Objective: 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.

Solution: We clone the repository as in the previous levels. Examining README.md yields:

# Bandit Notes
Some notes for bandit30 of bandit.

## credentials

- username: bandit30
- password: <no passwords in production!>
Listing 12 - Cloning the repo and checking the README file

No flag is present here. However, the message hints that additional branches may exist. To list all branches, both local and remote, we use the -a flag:

git branch -a
  dev
* master
  remotes/origin/HEAD -> origin/master
  remotes/origin/dev
  remotes/origin/master
  remotes/origin/sploits-dev
Listing 13 - Checking Git branches

Switching to the dev branch reveals the flag in README.md:

# change to the dev branch
git checkout dev
# retrieve the flag
cat README.md
Listing 14 - Changing branches and reading the flag

Level 30

Objective: 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.

Solution: After cloning the repository, we find no flag in README.md. Examining multiple branches also yields nothing. However, checking the Git tags provides a lead:

# list the git tags
git tag -l
secret
Listing 15 - Checking Git tags

We examine the tag using git show to view the tag message:

git show secret
<redacted-flag>
Listing 16 - Checking the secret tag

The tag message contains the password for the next level.

Level 31

Objective: 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.

Solution: As before, we clone the repository and perform reconnaissance. The README.md file describes the task:

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

Listing 17 - Instructions within the README file

We create the required file and examine .gitignore:

# create and modify the key.txt file as required
echo 'May I come in?' > key.txt
# check the .gitignore file
cat .gitignore 
*.txt

# blocks all txt files
Listing 18 - Preparing key.txt and checking .gitignore

The .gitignore file blocks all .txt files. We modify it to allow key.txt:

# allow our key.txt file
echo '!key.txt' >> .gitignore
Listing 19 - Modifying .gitignore to include key.txt

Git requires a username and email for commits. We configure these:

# configure local git username and email
git config user.name "bandit31-git"
git config user.email [email protected]
Listing 20 - Git configuration

Finally, we stage, commit, and push the changes:

# stage all changed files
git add .
...
# commit the changes
git commit -m "modified .gitignore to allow .txt files; added key.txt as required"
...
# push the changes
git push
...
[email protected]'s password: 
...
remote: Well done! Here is the password for the next level:
remote: <redacted-flag> 
...
Listing 21 - Uploading local Git changes

If performed correctly, the remote server returns the next flag upon completion of the push.

Level 32

Objective: After all this git stuff its time for another escape. Good luck!

Solution: We were initially stuck at this level. After some research, we found a useful walkthrough. Using the same technique:

# upon login, we are greeted with a welcome message
WELCOME TO THE UPPERCASE SHELL
# break the uppercase shell with $0
>> $0
...
# retrieve the flag
$ cat /etc/bandit_pass/bandit33
<redacted-flag>
$
Listing 22 - Breaking the uppercase shell and reading the flag

Level 33

Objective: At this moment, level 34 does not exist yet.

Solution: It is still worth logging in. A README.txt file in the home directory contains the following message:

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!

Listing 23 - Goodbye message

With this, we successfully complete the Bandit wargame. Kudos to the creators.