October 19, 2026
OverTheWire Bandit Walkthrough Part 6: Levels 25โ29
Escape a restricted shell, use SUID binaries, and uncover passwords hidden in Git history and branches.
By isheblank
7 min read
Introduction
In this part, we'll explore restricted login shells, SSH private keys, SUID executables, and Git repositories. The challenges gradually shift from working with Linux commands to understanding how shells behave and how sensitive information can remain in version history.
Let's get started.
Level 25 โ Level 26: Escaping a Restricted Shell
The challenge
The home directory of bandit25 contains a private SSH key for bandit26.
Logging in as bandit26 is not the difficult part. The challenge is that its login shell is different from the usual Bash shell. We need to understand how it works and find a way to escape it.
Step 1: Retrieve the SSH private key
From my local machine, I copied the key from the Bandit server:
scp -P 2220 bandit25@bandit.labs.overthewire.org:/home/bandit25/bandit26.sshkey .scp -P 2220 bandit25@bandit.labs.overthewire.org:/home/bandit25/bandit26.sshkey .This downloads bandit26.sshkey into my current local directory.
Next, I restricted access to the private key:
chmod 600 bandit26.sshkeychmod 600 bandit26.sshkeyStep 2: Connect as bandit26
I used the private key to authenticate:
ssh -p 2220 -i bandit26.sshkey bandit26@bandit.labs.overthewire.orgssh -p 2220 -i bandit26.sshkey bandit26@bandit.labs.overthewire.org
The connection was established, but the session closed almost immediately.
To understand why, I checked the account's shell information from the previous level:
cat /etc/passwd | grep bandit26cat /etc/passwd | grep bandit26The output showed that the account uses:
/usr/bin/showtext/usr/bin/showtextThis explains why I did not get a normal interactive Bash shell.
Step 3: Understand the login program
I inspected the program:
cat /usr/bin/showtextcat /usr/bin/showtextThe important part was:
#!/bin/sh
export TERM=linux
exec more ~/text.txt
exit 0#!/bin/sh
export TERM=linux
exec more ~/text.txt
exit 0The program launches more to display text.txt. Because the file is short, the content normally fits on the screen, so more finishes immediately and the SSH session closes.
The key is to make the terminal small enough that more enters its interactive viewing mode instead.
Step 4: Enter the interactive viewer
I reconnected as bandit26 and reduced the terminal window's height.
This time, more stayed open rather than exiting immediately.
While inside more, I pressed:
vvThis opened the text in Vim.
Step 5: Escape into Bash
Inside Vim, I entered the following command:
:set shell=/bin/bash:set shell=/bin/bashThis changes the shell Vim uses when starting a shell.
Then I entered:
:shell:shellThis opened a Bash shell. I now had an interactive command prompt as bandit26.
Step 6: Read the password
With the shell available, I ran:
cat /etc/bandit_pass/bandit26cat /etc/bandit_pass/bandit26The command displayed the password for the next level.
jHdv2ELQhT22BkprMNDjybZDAkw1zeBJjHdv2ELQhT22BkprMNDjybZDAkw1zeBJ
What I learned
This challenge showed me that a login shell does not always need to be Bash. A program that opens a pager or editor can create unexpected ways to interact with a system, depending on how it is configured.
I also learned how to use Vim's shell setting and :shell command to launch an interactive shell from within the editor.
Level 26 โ Level 27: Using a SUID Binary
The challenge
Now that I had obtained a shell as bandit26, I found an executable named bandit27-do in the home directory.
The objective was to understand what the program does and use it to retrieve the password for the next level.
Step 1: Inspect the available files
I listed the directory:
lslsThe output included:
bandit27-do
text.txtbandit27-do
text.txtStep 2: Check how the program works
I ran the executable without arguments:
./bandit27-do./bandit27-doIt displayed instructions similar to:
Run a command as another user.
Example: ./bandit27-do idRun a command as another user.
Example: ./bandit27-do idI tested the example:
./bandit27-do id./bandit27-do idThe output showed that the command was executed with the identity of bandit27, confirming that the binary could run commands with that user's permissions.
Step 3: Retrieve the next password
Since the binary could run commands as bandit27, I used it to read the corresponding password file:
./bandit27-do cat /etc/bandit_pass/bandit27./bandit27-do cat /etc/bandit_pass/bandit27The command returned the password.
STJLBPRbpMxKB392CT4i0r5cbzPU9ERSTJLBPRbpMxKB392CT4i0r5cbzPU9ER
What I learned
This challenge reinforced the importance of Linux SUID permissions. An executable configured to run with its owner's privileges may be able to access files that the user who launches it cannot read directly.
Level 27 โ Level 28: Cloning a Git Repository
The challenge
The next password was stored in a Git repository hosted on the OverTheWire server.
The repository needed to be cloned from my local machine, using Git and the credentials for bandit27-git.
Step 1: Clone the repository
On my local machine, I ran:
git clone ssh://bandit27-git@bandit.labs.overthewire.org:2220/home/bandit27-git/repogit clone ssh://bandit27-git@bandit.labs.overthewire.org:2220/home/bandit27-git/repoGit prompted me for the password associated with bandit27-git. I entered the current Level 27 password.
The repository was downloaded successfully.
Step 2: Explore the repository
I entered the repository directory:
cd repocd repoThen I listed its contents:
lslsThe repository contained a file named README.
Step 3: Read the README
I opened the file:
cat READMEcat READMEThe README contained the credentials for the next level.
y8Yd2ssKcpHpud7UvOSOxwamRMzIGIeQy8Yd2ssKcpHpud7UvOSOxwamRMzIGIeQ
What I learned
Git repositories can contain useful information in ordinary project files such as README documents. The git clone command creates a local copy of a remote repository, allowing its files to be inspected on your own machine.
Level 28 โ Level 29: Recovering Information from Git History
The challenge
The next repository contained a README with the username for the next level, but the password field had been replaced with a placeholder.
Instead of searching through the files, I needed to investigate the Git history to find the earlier version of the README.
Step 1: Clone the repository
I cloned the Level 28 Git repository:
git clone ssh://bandit28-git@bandit.labs.overthewire.org:2220/home/bandit28-git/repogit clone ssh://bandit28-git@bandit.labs.overthewire.org:2220/home/bandit28-git/repoAfter entering the repository:
cd repocd repoI checked the README:
cat README.mdcat README.mdThe password field was redacted, so the current version did not provide the answer.
Step 2: Inspect the commit history
I used:
git loggit logThe output showed several commits, including messages such as:
fix info leak
add missing data
initial commit of README.mdfix info leak
add missing data
initial commit of README.mdThe commit message fix info leak looked particularly relevant. It suggested that information had been removed or corrected in a later commit.
Step 3: Inspect the relevant commit
I examined the latest commit and its changes:
git show de09b8205d8d115e2749670df21bf1882bc98e34git show de09b8205d8d115e2749670df21bf1882bc98e34The output showed a diff of the README. The older version included a password, while the newer version replaced it with a placeholder.
The removed password was visible in the diff.
Em7eGtqaMySwNFjCpwzzHhlhosp0cdt0Em7eGtqaMySwNFjCpwzzHhlhosp0cdt0
What I learned
Git records changes over time. Removing a password from the latest version of a file does not automatically erase it from the repository's earlier commits.
The git log and git show commands help examine that history and reveal what changed between versions.
Level 29 โ Level 30: Finding the Password in Another Branch
The challenge
The next repository contained a README with the username for Level 30, but its password field said there were no passwords in production.
This suggested that the password might exist in another Git branch rather than the default master branch.
Step 1: Clone the repository
I cloned the repository for bandit29-git from my local machine:
git clone ssh://bandit29-git@bandit.labs.overthewire.org:2220/home/bandit29-git/repo repo_29git clone ssh://bandit29-git@bandit.labs.overthewire.org:2220/home/bandit29-git/repo repo_29I then entered the cloned directory and read the README.md file
cd repo_29
cat README.mdcd repo_29
cat README.md
Step 2: List all branches
I ran:
git branch -agit branch -aThe output showed the local branch and several remote branches:
* master
remotes/origin/HEAD -> origin/master
remotes/origin/dev
remotes/origin/master
remotes/origin/sploits-dev* master
remotes/origin/HEAD -> origin/master
remotes/origin/dev
remotes/origin/master
remotes/origin/sploits-devThe dev branch looked promising because development branches may contain work that has not been included in the production branch.
Step 3: Switch to the development branch
I checked it out:
git checkout devgit checkout devGit switched me to the dev branch and configured it to track origin/dev.
Step 4: Read the README again
I inspected the file:
cat README.mdcat README.mdUnlike the production branch, the development branch contained the password for the next level.
jq9Dfg2rXsfYswMgFuKlXhphjdH7USgXjq9Dfg2rXsfYswMgFuKlXhphjdH7USgX
What I learned
Git branches allow developers to maintain different versions of a project. A file that contains no useful information in one branch may contain it in another.
The git branch -a command lists local and remote-tracking branches, while git checkout lets you switch to a branch and inspect its contents.
Key Takeaways From Part 5
Across Levels 25โ29, I practiced several important concepts:
- SSH private keys: Authenticating to another account using a key file.
- Restricted shells: Understanding how a login program behaves and how to reach an interactive shell.
- SUID binaries: Executing commands with another user's permissions.
- Git cloning: Downloading remote repositories for local inspection.
- Git history: Recovering information that was removed from a later commit.
- Git branches: Looking beyond the default branch to find information in development work.
Conclusion
That completes Part 6 of the OverTheWire Bandit walkthrough, covering Levels 25 through 29.
These challenges helped me understand how restricted shells work, how SUID executables affect permissions, and how Git history and branches can preserve information that is no longer visible in the current version of a file.
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.