← Back to list

OverTheWire Bandit Walkthrough — Level 27 → 28 | 30-Day Cybersecurity Learning Journey (Day 27)

Cloning a private repository over SSH and pulling the next credential straight out of a git README.

William | Cybersecurity & SOC Analyst in System Weakness · 2026-07-01 14:39 · 0 claps · 7.0 min read
#cybersecurity #linux #security #information-technology #ctf
Open on Medium ↗
Wiki topics: EDU · Education & Learning 🔒 · Cybersecurity 🔓 · Open Source

OverTheWire Bandit Walkthrough — Level 27 → 28 | 30-Day Cybersecurity Learning Journey (Day 27)

Cloning a private repository over SSH and pulling the next credential straight out of a git README.

Introduction

Day 27. Bandit Level 27 to Level 28. This is the level where Bandit stops being purely about Linux fundamentals and starts teaching version control. The challenge here is short to read and quick to solve, but the skill behind it is one of the most important in all of cybersecurity. Git.

The core task is to clone a git repository that lives behind a restricted SSH account and read the file it contains. There is no shell escape this time and no SUID trickery. The whole exercise is about knowing how git talks to a remote server over SSH and where a repository hides its files.

By the end of this article you will understand how to clone a repository over SSH, why it must be done from a writable directory and how a single README file can leak a secret. You will also see why this exact pattern, secrets committed into git, is something defenders chase constantly in real security work.

Level Objective

The official OverTheWire page points to a git repository at ssh://bandit27-git@localhost/home/bandit27-git/repo on port 2220. The password for the bandit27-git account is the same as the bandit27 password. The objective is to clone that repository and find the password for the next level inside it.

Approach

I connected from my local Kali machine using the password retrieved from the previous level:

ssh bandit27@bandit.labs.overthewire.org -p 2220

The banner loaded and the prompt changed to bandit27@bandit:~$. I had a working shell to plan from.

Logged into bandit27 via SSH on port 2220.

Logged into bandit27 via SSH on port 2220.

The home directory is not writable for a clone operation so I moved to /tmp, created a dedicated working directory and cloned the repository using the SSH git URL. Git prompted for the bandit27-git password, which is identical to the bandit27 password, and then pulled down the objects:

cd /tmp
mkdir james27git
cd james27git
git clone ssh://bandit27-git@bandit.labs.overthewire.org:2220/home/bandit27-git/repo

With the clone complete I changed into the repo directory and listed it in long form. Two things were present: the hidden .git folder and a plain README file. I read the README and the password for Level 28 was sitting right there in plain text:

cd repo
ls -la
cat README

The cloned README reveals the next level password in plain text.

The cloned README reveals the next level password in plain text.

Commands Used

# Connect to the Bandit server as bandit27 using the Level 27 password
ssh bandit27@bandit.labs.overthewire.org -p 2220
# Move to a writable directory for the clone operation
cd /tmp
# Create a dedicated working directory
mkdir james27git
cd james27git
# Clone the repository over SSH using the git URL on port 2220
git clone ssh://bandit27-git@bandit.labs.overthewire.org:2220/home/bandit27-git/repo
# Enter the cloned repository
cd repo
# List all files including the hidden .git directory
ls -la
# Read the README to retrieve the password
cat README

Command Breakdown

**ssh bandit27@bandit.labs.overthewire.org -p 2220** Opens an SSH session to the Bandit server on port 2220 as bandit27. This confirms access and provides the base shell from which the clone is launched.

**cd /tmp** The home directory for bandit27 is not writable for this operation. Moving to /tmp provides a world-writable scratch space that git can use to build the working tree without permission errors.

**mkdir james27git** Creates a clean named directory so the clone does not collide with anything else in /tmp. A small habit that keeps lab work organised and outputs predictable.

**git clone ssh://bandit27-git@bandit.labs.overthewire.org:2220/home/bandit27-git/repo** The core command of this level. The ssh:// URL tells git to connect over SSH to the bandit27-git account on port 2220 and copy down the repository at the specified path. Git prompts for the password then transfers all objects.

**ls -la** A long listing with hidden files. This exposes the .git directory alongside the README, confirming the clone succeeded and showing exactly what content is available to read.

**cat README** Reads and prints the README file. In this repository that single file contains the plaintext password for the next level.

Lesson Learned

The main technical takeaway is that cloning a repository copies far more than the files visible in the working directory. The .git folder comes with it, carrying the full commit history. In this level the README alone gives up the answer, but the presence of .git is a quiet reminder that git remembers everything including content that has since been deleted from the latest commit.

What clicked during this level was how naturally git rides on top of SSH. The same protocol used to log into every Bandit level is also the transport git uses to clone. Seeing the ssh:// scheme in the URL and then receiving a familiar password prompt made the whole mechanism immediately clear. It was SSH authentication wearing a git coat.

Going forward the pattern is straightforward: see an ssh:// git URL, clone into a writable directory, supply the matching password and read the contents. That sequence repeats across every git level that follows.

  • git clone — copy a repository and its full history to a local directory
  • git log — inspect the complete commit history of a cloned repository
  • git show — view the contents and metadata of a specific commit
  • git diff — compare two versions of a file or two commits
  • git branch — list all branches in a repository
  • ls -la — always run this after cloning to see both visible files and the hidden .git directory

🔴 SOC Analyst Insight

Secrets committed into git repositories are one of the most common and damaging exposures in modern security. A developer pastes a password into a configuration file, commits it, removes it in a later commit and assumes it is gone. It is not. The credential lives in the commit history and anyone who can clone the repository can recover it regardless of how many subsequent commits have passed.

During a repository assessment or a suspected credential leak investigation, scanning the current files is not enough. The entire history needs to be checked because a removed secret can still be retrieved from older commits without any special tools.

# Scan the full commit history across all branches for common secret patterns
git log -p --all | grep -iE "password|api[_-]?key|secret|token"

The command above walks every commit across every branch, prints the full diffs and filters for the language that secrets typically hide behind. It surfaces credentials that were committed and later removed, which is exactly the failure pattern this level models in miniature. Tools like trufflehog and gitleaks automate this at scale across entire organisations but understanding the underlying git log approach is what makes those tools interpretable when they surface findings.

The connection back to this level is direct. The README here holds the password in plain text, the cleanest possible version of a secret in a repository. In production environments the secret is rarely that obvious but the underlying mistake is identical: sensitive data placed somewhere that version control will preserve indefinitely.

Key Takeaway

Cloning a git repository pulls down its entire history, not just the files currently visible in the working directory, and that history is unforgiving. A secret committed once is recoverable forever unless the history is actively rewritten and all copies are replaced. This level shows the simplest case, a password sitting in a README, but the lesson scales to every codebase in existence. Treat repositories as places where secrets go to live permanently and scan the full history accordingly.

30-Day Cybersecurity Learning Journey — Progress

🟢 Open Day — Setup & Series Introduction  | OverTheWire Bandit
✅ Day 0.   — Bandit Level 0               | First Login
✅ Day 1.   — Bandit Level 1 → 2           | Special Characters
✅ Day 2.   — Bandit Level 2 → 3           | Spaces in Filenames
✅ Day 3.   — Bandit Level 3 → 4           | Hidden Files
✅ Day 4.   — Bandit Level 4 → 5           | File Types
✅ Day 5.   — Bandit Level 5 → 6           | find with Properties
✅ Day 6.   — Bandit Level 6 → 7           | find across Filesystem
✅ Day 7.   — Bandit Level 7 → 8           | grep
✅ Day 8.   — Bandit Level 8 → 9           | sort and uniq
✅ Day 9.   — Bandit Level 9 → 10          | strings and grep
✅ Day 10.  — Bandit Level 10 → 11         | base64
✅ Day 11.  — Bandit Level 11 → 12         | ROT13 and tr
✅ Day 12.  — Bandit Level 12 → 13         | hexdump and compression
✅ Day 13.  — Bandit Level 13 → 14         | SSH keys
✅ Day 14.  — Bandit Level 14 → 15         | Netcat
✅ Day 15.  — Bandit Level 15 → 16         | SSL and OpenSSL
✅ Day 16.  — Bandit Level 16 → 17         | Port Scanning
✅ Day 17.  — Bandit Level 17 → 18         | diff
✅ Day 18.  — Bandit Level 18 → 19         | SSH command execution
✅ Day 19.  — Bandit Level 19 → 20         | Setuid binaries
✅ Day 20.  — Bandit Level 20 → 21         | Network services
✅ Day 21.  — Bandit Level 21 → 22         | Cron jobs
✅ Day 22.  — Bandit Level 22 → 23         | Cron and bash scripting
✅ Day 23.  — Bandit Level 23 → 24         | Writing cron scripts
✅ Day 24.  — Bandit Level 24 → 25         | Brute forcing and loops
✅ Day 25.  — Bandit Level 25 → 26         | Restricted shells
✅ Day 26.  — Bandit Level 26 → 27         | SUID privilege escalation
✅ Day 27.  — Bandit Level 27 → 28         | git clone over SSH  ← today
⬜ Day 28.  — Bandit Level 28 → 29         | coming next

Follow along with the series as I document each level, command and lesson learned.

A deleted password is not a gone password. Git keeps the receipts long after the developer forgets.


메타데이터
post_id
eba531291bc0
slug
overthewire-bandit-walkthrough-level-27-28-30-day-cybersecurity-learning-journey-day-27-eba531291bc0
url
https://systemweakness.com/overthewire-bandit-walkthrough-level-27-28-30-day-cybersecurity-learning-journey-day-27-eba531291bc0
canonical_url
https://systemweakness.com/overthewire-bandit-walkthrough-level-27-28-30-day-cybersecurity-learning-journey-day-27-eba531291bc0
author_url
https://medium.com/@wgokahp
status
ok
fetched_at
2026-07-11 16:48:19