October 19, 2026
OverTheWire Bandit WalkthroughPart 7: Levels 30โ32
Discover hidden Git tags, push files to a remote repository, and escape the uppercase shell to complete Bandit.
By isheblank
6 min read
Introduction
Throughout this series, I've explored Linux commands, file permissions, networking, shell scripting, and Git. In these last three challenges, we'll look at hidden information in Git tags, submit a file to a remote repository, and escape a shell that transforms commands into uppercase.
Let's finish the challenge.
Level 30 โ Level 31: Finding a Hidden Git Tag
The challenge
The home page of the repository does not provide the password directly. The README file looks like a dead end, so I needed to explore other parts of the Git repository.
Step 1: Clone the repository
From my local machine, I cloned the repository using Git:
git clone ssh://bandit30-git@bandit.labs.overthewire.org:2220/home/bandit30-git/repo repo_30git clone ssh://bandit30-git@bandit.labs.overthewire.org:2220/home/bandit30-git/repo repo_30After entering the password for bandit30-git, the repository was downloaded successfully.
I moved into the directory:
cd repo_30cd repo_30Step 2: Check the README
I listed the available files:
lslsThe repository contained a README.md file. I opened it:
cat README.mdcat README.mdIts contents were:
just an empty file... muahahajust an empty file... muahahaThere was no password here, so I needed to look beyond the regular files.
Step 3: List the Git tags
Git tags can point to specific objects or commits in a repository. They can also be used to mark releases or preserve references to particular points in a project's history.
I checked the tags with:
git taggit tagThe output showed a tag named:
secretsecretThis looked promising.
Step 4: Read the tag
I inspected the tag using:
git show secretgit show secretThe command displayed the password for the next level.
82NkymblpGBYmIXG6ZQ8YldBYstHpUf82NkymblpGBYmIXG6ZQ8YldBYstHpUf
What I learned
Git repositories contain more than just files and commits. Tags can preserve useful references that are not obvious when browsing the working directory.
When a repository's README does not provide an answer, checking its tags with git tag and inspecting them using git show can reveal additional information.
Level 31 โ Level 32: Pushing a File to a Remote Repository
The challenge
This level changes the usual approach. Instead of finding a password in an existing file, I had to create a new file and push it to a remote Git repository.
The repository's README provided the requirements:
- File name:
key.txt - Content:
May I come in? - Branch:
master
The main obstacle was that the repository contained a .gitignore file that excluded .txt files.
Step 1: Clone the repository
I cloned the repository for bandit31-git:
git clone ssh://bandit31-git@bandit.labs.overthewire.org:2220/home/bandit31-git/repo repo_31git clone ssh://bandit31-git@bandit.labs.overthewire.org:2220/home/bandit31-git/repo repo_31Then I entered the directory:
cd repo_31cd repo_31I read the repository instructions:
cat README.mdcat README.mdThe README confirmed that I needed to push key.txt with the exact required content to the master branch.
Step 2: Inspect the .gitignore file
I listed all files, including hidden ones:
ls -lals -laThe output included:
.git
.gitignore
key.txt
README.md.git
.gitignore
key.txt
README.mdI checked the ignore rules:
cat .gitignorecat .gitignoreThe file contained:
*.txt*.txtThe * wildcard matches any filename, while .txt specifies the file extension. Together, this rule tells Git to ignore files ending in .txt.
That explained why simply creating key.txt would not be enough to ensure Git tracked it.
Step 3: Create the required file
I created key.txt and added the exact content specified by the challenge:
touch key.txt
echo 'May I come in?' > key.txttouch key.txt
echo 'May I come in?' > key.txtI then checked the file:
cat key.txtcat key.txtThe output was:
May I come in?May I come in?
Step 4: Remove the ignore rule
For this challenge, I removed the .gitignore file:
rm .gitignorerm .gitignoreThis removed the rule that excluded .txt files from Git tracking.
I checked the directory again:
lslsBoth key.txt and README.md were present.
Step 5: Stage and commit the changes
I staged the files:
git add .git add .Then I created a commit:
git commit -m "new changes"git commit -m "new changes"Git confirmed the new commit and showed that .gitignore was deleted and key.txt was created.
Step 6: Push to the remote repository
Finally, I pushed the changes to the required branch:
git push origin mastergit push origin masterThe remote repository processed the submission. Although the push ended with a rejection from the server's pre-receive hook, the output displayed the password for the next level before that rejection.
pWuJ5jBQ6IGvONXwIH6g1pXRF8S1YvbTpWuJ5jBQ6IGvONXwIH6g1pXRF8S1YvbT
What I learned
This challenge helped me understand how .gitignore affects Git tracking and how files move through the Git workflow:
- Create or modify a file.
- Stage the changes with
git add. - Record the changes with
git commit. - Send the commit to a remote repository with
git push.
I also learned that a remote repository can validate a submission using a server-side hook. In this challenge, the hook returned the next password even though the push itself was rejected.
Level 32 โ Level 33: Escaping the Uppercase Shell
The challenge
The final challenge introduced a special shell called the Uppercase Shell.
When I connected, the terminal displayed:
WELCOME TO THE UPPERCASE SHELL
>>WELCOME TO THE UPPERCASE SHELL
>>Commands such as ls, whoami, and id were transformed into uppercase before execution. Since Linux commands are generally case-sensitive, commands such as LS and WHOAMI failed.
I needed a way to escape the unusual shell and get back to a normal command prompt.
Step 1: Test the shell
I tried a few familiar commands:
>> ls
>> whoami
>> id>> ls
>> whoami
>> idThe shell transformed them into uppercase, so I received errors such as:
sh: 1: LS: Permission deniedsh: 1: LS: Permission deniedThis confirmed that the shell was modifying the commands before they were executed.
Step 2: Use $0 to escape
Instead of trying more uppercase commands, I entered:
$0$0This uses the special shell parameter $0, which expands to the name used to invoke the current shell. In this challenge, entering it provided a way to escape the uppercase command-processing behavior.
I now had a normal shell prompt where lowercase Linux commands worked again.
Step 3: Verify the current user
I ran:
whoamiwhoamiThe output was:
bandit33bandit33This confirmed that I had successfully escaped the uppercase shell and obtained a normal shell as bandit33.
Step 4: Retrieve the final password
I used the password file for the current account:
cat /etc/bandit_pass/bandit33cat /etc/bandit_pass/bandit33The output was:
u4P2CyP0wPGLe94RdD9Uo2FxFwvFnSwMu4P2CyP0wPGLe94RdD9Uo2FxFwvFnSwM
Step 5: Confirm completion
After logging in as bandit33, I listed the home directory:
lslsThe directory contained:
README.txtREADME.txtI opened it:
cat README.txtcat README.txtThe message confirmed that the last level of Bandit had been solved and that there were no more levels currently available in the game.
I had completed the OverTheWire Bandit wargame!
What I learned
This challenge demonstrated that unusual shell behavior does not necessarily mean every escape route is blocked. Understanding shell parameters and how command input is processed can help reveal a way back to a normal command interpreter.
It was a fitting end to the series because solving the level required thinking about how the shell itself worked, rather than simply searching for a file.
Lessons Learned From the Bandit Series
Completing these challenges gave me practical experience with several Linux and cybersecurity concepts:
- Linux fundamentals: Navigating directories, reading files, and understanding permissions.
- Networking: Connecting to services through TCP, Netcat, and SSL/TLS.
- SSH authentication: Using passwords and private keys to access remote accounts.
- Shell scripting: Automating tasks and understanding cron jobs.
- SUID permissions: Learning how programs can run with their owner's privileges.
- Git: Cloning repositories, inspecting tags, exploring branches, checking commit history, and pushing changes.
- Shell behavior: Understanding restricted environments and finding a way to interact with a normal shell.
Final Thoughts
Completing all 33 Bandit levels was a valuable learning experience. The early levels introduced basic Linux commands, while later levels required more investigation, automation, and understanding of how the underlying system behaved.
My biggest takeaway is that solving these challenges is not just about memorizing commands. It is about inspecting what is available, understanding why a command behaves a certain way, and using that information to work toward a solution.
This concludes my seven-part OverTheWire Bandit walkthrough series. If you're starting your Linux or cybersecurity journey, Bandit is a great way to build practical command-line skills through hands-on challenges.
All commands and findings in this walkthrough are based on my hands-on session. Passwords are reproduced from my recorded results, so verify them against your own session if they differ.
My rating: 10/10