Step 101. Bandit 26~30 — Digging Secrets from git History, and the Finish Line

Step 101. Bandit 26~30 — Digging Secrets from git History, and the Finish Line

Level 2 — Introduction to Security and Attack Skill Basics | Difficulty ★★★☆☆ | Estimated time: 3 hours

Prerequisites: you’ll use the Git knowledge from Steps 86~88 (log, show, branch, tag) and your Bandit experience through Step 100.

  • What you need: the password chain through Bandit 25, an SSH connection environment, and git on your own computer (for local experiments).
  • ⚠️ All exercises in this chapter are for your own lab and legal platforms only. Applying them to unauthorized systems is a crime.
  • Note: Bandit is a legal learning platform officially operated by OverTheWire — a practice ground opened on the premise of attacks, so attack it freely, but never use the same techniques on other systems. Digging through someone else’s repository without permission can be the start of an intrusion, even if it’s public.

In Step 87 we learned this — never post secrets to a public repository, because they remain in past commits even after deletion. Back then it was a defensive rule. Today is the other side of the coin: the git log, git show, git branch -a, and git tag you mastered become, as-is, "tools for excavating other people’s mistakes." Finding a secret key a developer accidentally committed in Git history is a staple technique of real bug bounties (vulnerability reward programs), and Bandit’s final stretch (26~30) is exactly that training ground. After finishing, a review awaits: condensing all of 0~30 into a single map.


1. Learning Objectives

By the end of this chapter, you will be able to:

  • Explain the concept of bypassing a restricted shell by reading files via more/vim
  • Clone an entire repository with git clone and find hidden secrets in its history, branches, and tags
  • Prove for yourself with a local git experiment that "a deleted secret doesn’t disappear"
  • Search a repository’s entire history with the git log --all -p | grep combination
  • Turn learning into an asset with a wargame review’s three questions (technique, pattern, connection)

2. Background Knowledge — Today’s Tools and Concepts

Today’s Tools at a Glance

Category Details
Language/environment Bandit server (SSH, Screen example) + git on your own computer (measured experiments)
Today’s commands git clone, git log --oneline --all, git show hash, git branch -a, git show branch:file, git tag, git log --all -p | grep
Concepts needed restricted-shell bypass (more→vim), git objects and history, branches and tags, responding to secret leaks (revoke & reissue)
Today’s artifact treasure-lab — a local practice repository for burying and digging secrets, plus a bandit-wrapup.md review document

2-1. The Restricted Shell — Look at the Door’s Parts, Not the Door

Bandit 26 is an account that bounces you the moment you connect, because its login shell is set not to ordinary bash but to a special program that shows text and exits. We call this kind of environment a restricted shell situation.

The thread of the bypass is this: "even if the shell is locked, the features of the components that shell invokes are still alive." If the output is longer than the terminal window, the text-display program pauses in a more (page-at-a-time) state, and from the more state the v key launches the vim editor. Since vim is a program that opens files, the moment you’re inside vim the restriction is gone. This is the full version of the problem previewed in Step 100.

2-2. git clone — Bringing Not the Current Files but the Entire History

git clone is a command that copies someone’s repository history and all.

git clone ssh://user@address:port/path

An important fact — clone doesn’t bring just "the current files"; it brings the .git folder, meaning the entire history. Every past commit, every branch, every tag is copied onto my computer. This is why excavation is possible. Bandit’s git servers are open per level with separate accounts (bandit27-git, etc.) over SSH port 2220.

2-3. The Three Big Techniques for Digging History

The order in which an attacker searches a cloned repository for secrets is fixed.

  1. Past commits: git log --oneline → open suspicious commits with git show hash
  2. Other branches: git branch -a → the real thing may live on a development (dev) branch
  3. Tags: git tag → a note tucked into a release marker, viewed with git show tagname

All three are commands you learned in Steps 86~88. Only the perspective differs — from "my history-management tool" to "a tool for excavating other people’s mistakes."

2-4. The Craft of Review — Turning a Game into an Asset

The difference between "solving a wargame and forgetting it" and "turning it into an asset" is a single review. A review asks three questions.

  • What did this problem demand? (technique)
  • Why was I stuck, or fast? (my patterns)
  • Where in the real world does this technique apply? (connection)

The third question is the heart of review. Techniques last when they’re connected.


3. Follow Along

3-1. Level 26 → 27: Completing the Restricted-Shell Escape

This is the full version of the problem previewed in Step 100’s 3-6. Connect to the server.

Input — reconnaissance:

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

Screen example: a short text appears immediately on connection, then the connection closes.

Procedure:

  1. Shrink your terminal window’s height to 2~3 lines, drastically.
  2. Connect again — this time the text overflows the window and stops in the more state (a --More-- indicator at the bottom of the screen).
  3. Press v to enter vim.
  4. Inside vim, type :e /etc/bandit_pass/bandit26 → the password opens.

How to read it: even though the shell was locked, we bypassed it through a feature (vim entry) of a component (more) that the shell invoked. The moment Step 100’s lesson — "look at the door’s parts, not the door" — was completed in the field.

If stuck: if vim won’t open, you’re not in the more state — shrink the window further. If trapped in vim: Esc:q! → Enter.

3-2. Level 27 → 28: Your First git Clone

Input (on the server, Screen example):

mkdir /tmp/git27 && cd /tmp/git27
git clone ssh://bandit27-git@localhost:2220/home/bandit27-git/repo
cd repo && ls
cat README

Screen example: the cloned repository’s files — the next password is visible inside the README (this level is a warm-up).

How to read it: localhost:2220 means "connect to the git service through SSH inside this server." When asked for a password, enter the current level’s.

Why: the flow of cloning a remote git repository is itself a real-world skill. In an actual penetration, the discovery that "the dev server’s git is exposed" is a jackpot clue — and the actions are exactly this sequence.

3-3. Level 28 → 29: Digging Up a Past Commit

This repository’s README has the password masked as xxxxxx.

Input (on the server):

git log --oneline
git show oldest-commit-hash

Screen example: the README in a past commit contains the real password from before it was masked.

How to read it: git show hash shows what changed in that commit. The commit right before the "password masking" commit is the treasure chest.

Why: Step 87’s experiment (pulling a deleted key back out with git show) has returned as an attack technique. What’s deleted is not gone — this one sentence has produced countless bug-bounty payouts.

3-4. Level 29 → 30: The Real Thing on Another Branch

Input (on the server):

git branch -a
git show remotes/origin/dev:README.md

Screen example: besides main, branches like dev appear, and that branch’s README holds the real password.

How to read it: git branch -a shows every branch, including remote ones. git show branch:file is a shortcut that views a file inside a branch without checking it out. Development branches often retain things that never made it into main — test passwords, temporary keys.

Why: branches being parallel universes (Step 88) means "secrets from another universe become mine with a single clone."

3-5. Level 30 → 31: A Memo Hidden in a Tag

Input (on the server):

git tag
git show secret

Screen example: the tag list holds a suspicious name (secret, etc.), and showing it reveals the password written inside.

How to read it: a tag is "a label marking a point" (Step 88’s appendix), but you can attach a note to it. Developers really do make the mistake of writing secrets into tags "to look at later."

Why: log → branch → tag — the last cell of the three techniques. Finding hidden secrets in a cloned repository is now a complete procedure.

3-6. Reproduce It in Your Lab — Burying and Digging Secrets (Local Measurement)

An attack technique is complete only after you’ve also experienced it from "the installing side." Let’s measure all three techniques on your own computer, no server needed. Create a working folder and make a mini repository.

Input (Git Bash or a terminal):

mkdir treasure-lab && cd treasure-lab
git init
echo "PASSWORD=real_secret_1234" > config.txt
git add . && git commit -m "add config"
sed -i 's/real_secret_1234/xxxxxx/' config.txt
git add . && git commit -m "mask the password"
git checkout -b dev
echo "API_KEY=dev_only_key_9999" >> config.txt
git add . && git commit -m "add dev key"
git checkout main
git tag -a secret -m "backup: root_pw=tag_hidden_777"

(Windows Git Bash includes sed. If it errors, you can open config.txt yourself and change real_secret_1234 to xxxxxx. Depending on your git version, the default branch may be master — in that case use git checkout master instead of git checkout main.)

Three secrets are now buried. Looking at only the current file, it’s masked like this (measured 2026-09-09):

$ cat config.txt
PASSWORD=xxxxxx

Technique 1 — the past commit. View the history with git log --oneline and open the oldest commit (measured 2026-09-09):

$ git log --oneline
b3c8011 mask the password
756df69 add config

$ git show 756df69
commit 756df696114cf37f86947e145ca039c898d8e26c
Author: Lab <lab@example.com>
Date:   Wed Sep 9 14:26:00 2026 +0900

    add config

diff --git a/config.txt b/config.txt
new file mode 100644
index 0000000..abe05c1
--- /dev/null
+++ b/config.txt
@@ -0,0 +1 @@
+PASSWORD=real_secret_1234

The masked password lives on intact in the first commit. The hashes will come out differently in your environment — that’s normal.

Technique 2 — another branch (measured 2026-09-09):

$ git branch -a
  dev
* main

$ git show dev:config.txt
PASSWORD=xxxxxx
API_KEY=dev_only_key_9999

Technique 3 — tags (measured 2026-09-09):

$ git tag
secret

$ git show secret
tag secret
Tagger: Lab <lab@example.com>

backup: root_pw=tag_hidden_777
...

How to read it: all three techniques pinpointed their respective secrets exactly. Without any server, you’ve reproduced all of Bandit 28~30’s core on your own computer.

Why: if you first do the three techniques from "the burying side," your sense of where to dig on the excavating side becomes precise. An attacker’s search order is reading a developer’s hiding habits backward.

3-7. Searching the Entire History — The Techniques’ Complete Form

There’s a search that bundles the three techniques into one (measured 2026-09-09):

$ git log --oneline --all
8855c3a add dev key
b3c8011 mask the password
756df69 add config

$ git log --all -p | grep -i -E "pass|key|pw"
 PASSWORD=xxxxxx
+API_KEY=dev_only_key_9999
-PASSWORD=real_secret_1234
+PASSWORD=xxxxxx
+PASSWORD=real_secret_1234

How to read it: --all means the history of every branch, and -p means print each commit’s changes (diff) too. Filtering that whole stream with grep brought out all three buried secrets at once. Lines starting with - are "content deleted in that commit" — deleted secrets remain this densely.

This one line is the complete form of manual excavation. Real leak-scanning tools (truffleHog, gitLeaks) work on the same principle — they’re just tools that automate scanning a repository’s entire history for "strings that look like keys."

3-8. The Review — 0~30 as a Single Map

You’ve opened Bandit’s last door (level 31 onward is an advanced stretch beyond this book’s scope — keep challenging yourself if you have the bandwidth). Now for the review. Create bandit-wrapup.md in your wiki.

Writing guide:

Stretch Core techniques Real-world name
0~5 hidden files, file, find basic reconnaissance
6~10 conditional search, grep, base64 file-system searching
11~15 tr, nc, openssl manual service conversation
16~20 nmap, diff, setuid privilege escalation intro
21~25 cron tracing and slipping in automation abuse
26~30 git history excavation secret-exposure detection

Add to each row one line each of "the level I was stuck on longest" and "my biggest realization." Those two lines are the soul of this document.

A Peek at git’s Internals — Why Deleted Things Remain

Inside the .git folder, every commit is stored as an object. Even a commit that deletes a file leaves the previous commit’s objects untouched — because the act of "deleting" is itself just stacking a new commit. Only when an object is pointed to by no branch or tag does it become a cleanup candidate, and even then it remains until a cleaning command like git gc runs. "Git doesn’t forget" — this single structural fact is the root of all of today’s attacks and defenses. That’s why the response to a leak isn’t deletion but revoking and reissuing the key.


4. Missions & Exercises

Mission — The Bandit Graduation Proof Package

  1. Clear bandit26~30 and complete the password chain
  2. Build the treasure-lab from 3-6 yourself, find all three buried secrets with the three techniques (log / branch / tag) plus the complete-form one-liner (git log --all -p | grep), and capture the evidence
  3. Write bandit-wrapup.md — the technique-map table from 3-8 plus one line each of "the level I was stuck on longest" and "my biggest realization" per stretch
  4. Inspect your own real git repositories with an attacker’s eye — check with git log --all -p | grep -i -E "pass|key|token" whether any secret has leaked, and record the results

Exercises

Exercise 1. Explain why the fact that git clone brings "the entire history" rather than "just the current files" works in an attacker’s favor.

Exercise 2. A developer deleted a file containing a password and committed. Explain, from the perspective of git objects, why the secret can still be recovered.

Exercise 3. What does git show dev:config.txt do, and how does it differ from opening the file after git checkout dev?

Exercise 4. You’ve discovered a secret key was committed in your repository. Explain why the claim "deleting that commit solves it" is wrong, and what the correct response is.


5. Model Answers & Completion Criteria

Mission Model Answer

The solving procedure for Bandit 26~30 is exactly the order of 3-1~3-5 — enter vim from the more state (26), check the README (27), open a past commit (28), open the dev branch (29), open the tag (30).

For the treasure-lab’s three-technique verification, matching the shape of the measured output in 3-6 is correct:

Technique 1: git show <first-commit>  → +PASSWORD=real_secret_1234
Technique 2: git show dev:config.txt → API_KEY=dev_only_key_9999
Technique 3: git show secret → backup: root_pw=tag_hidden_777

It’s complete when all three secrets appear mixed together in the complete-form one-liner’s output (see the 3-7 measurement).

How to verify: ① in treasure-lab, is cat config.txt masked while git show first-commit shows the original? ② does the single line git log --all -p | grep -i pass bring out all three secrets? ③ are the inspection results of your real repositories recorded (with a revoke/reissue plan if anything was found)? All three "yes" means complete.

Exercise Answers

Answer 1. Because a single clone copies past commits, every branch, and all tags wholesale onto my computer. Without touching the server again, the attacker can rummage through history offline, as much as they like, inside the copy.

Answer 2. Because a commit that deletes a file merely stacks "a new commit saying it was deleted" — the previous commit’s objects remain intact inside .git. In the 3-6 measurement, the current file was masked as xxxxxx, but the first commit (git show 756df69) still held real_secret_1234 exactly.

Answer 3. It’s a command that prints the contents of config.txt at the commit the dev branch points to, immediately, without changing the working folder (no checkout). checkout is a heavy operation that converts my entire working folder to that branch’s state; the branch:file form is a light shortcut that only views.

Answer 4. Because an already-committed secret remains in history (3-6 measurement), and if it was already pushed, there’s no telling who has cloned it. Even if you delete the commit, it lives on in the cloners’ copies. The correct response: ① revoke that key immediately and issue a new one. ② cleaning the history is hygiene work that comes after. "An exposed secret is finished only when it’s made a dead secret."

Completion Criteria Checklist

  • [ ] I can explain the concept of a more/vim bypass in a restricted-shell environment
  • [ ] I can clone a git repository and find hidden information in its history, branches, and tags
  • [ ] I found all three buried secrets in treasure-lab with the three techniques
  • [ ] I can use the complete-form one-liner git log --all -p | grep
  • [ ] I can prove "deleted things remain" with commands and state the response (revoke & reissue)
  • [ ] I organized 31 levels of techniques into a single map (bandit-wrapup.md)
  • [ ] I inspected my real repositories from an attacker’s perspective

6. Common Pitfalls & Fixes

Wall 1. git clone throws a permission error

Symptom: the clone is rejected or asks for the password endlessly (on the server, Screen example).

Permission denied, please try again.

Cause: a password typo, a missing port (:2220), or you’re cloning in an unwritable folder outside /tmp.
Fix: make a /tmp/work-folder and clone inside it. Check the port notation in the address (ssh://...@localhost:2220/...) character by character.

Wall 2. git log shows only one line

Symptom: past commits aren’t visible.
Cause: plain git log shows only the current branch. Other branches’ history doesn’t appear.
Fix: git log --oneline --all (all branches), or view the list with git branch -a and then git show branch-name:file. In the 3-7 measurement, notice how dev’s commit ("add dev key") appeared once --all was added.

Wall 3. v doesn’t work in more

Symptom: you can’t get into vim at Level 26.
Cause: entering the more state failed — the window is still too big. Without a --More-- indicator, it’s not more yet.
Fix: really shrink the terminal height to 2~3 lines. Drag the window border with the mouse, drastically. If trapped after entering vim, exit with Esc:q! → Enter.

Wall 4. Tags/branches look empty

Symptom: git tag shows nothing.
Cause: you’re not inside the cloned directory (you must type there), or you’re typing somewhere that isn’t a repository.
Fix: confirm cd repo. Type git tag -l and git branch -a again inside the repository. Inside the repository, the secret tag should be visible, as in the 3-6 measurement.

Wall 5. git checkout main errors out

Symptom (in the local experiment):

error: pathspec 'main' did not match any file(s) known to git

Cause: depending on your git version/settings, the default branch was created as master, not main.
Fix: check the current branch name with git branch and use that name. The essence isn’t the branch name — it’s "returning to the original branch."


7. Summary

Today’s Concepts

Concept One-line explanation
Restricted shell an environment whose login shell is fixed to a special program — bypass via components (more→vim)
git clone copies not the current files but the entire history (.git)
git object the storage unit of commits — a delete commit doesn’t erase previous objects
The three history-digging techniques past commits (log→show) / other branches (branch→show branch:file) / tags (tag→show)
Secret-leak response not deletion but revoke & reissue — "make an exposed secret a dead secret"
The review’s three questions technique (what) · pattern (why I was stuck) · connection (where in the field)

Today’s Commands

Command What it does
git clone ssh://account@address:port/path clone a remote repository, history and all
git log --oneline / --all history one line each / including all branches
git show hash view that commit’s changes
git show branch:file view a file inside a branch without checkout
git branch -a / git tag branch list / tag list
git log --all -p | grep -i -E "pass|key|pw" search the entire history for secret patterns (complete form)

An Instinct More Important Than Commands

When you encounter someone’s repository, the search order should live in your body — ① skim the whole history with git log --oneline --all, ② check parallel universes and labels with git branch -a and git tag, ③ open suspicious spots with git show, and ④ finally sweep for leftovers with the complete-form git log --all -p | grep. This order reads a developer’s hiding habits (delete → another branch → tag memo) backward.

And the sense as a defender — you are now both the executor and the defender of this attack. With your own attacker’s eyes today, you confirmed that if a secret entered your repository, "deleting the commit" isn’t enough — key revocation and reissue are required. Having passed through 31 doors, you now hold the full outline of "how to find opportunities on a Linux server." Files → conditions → network → privileges → automation → history. This outline is where the deeper techniques you’ll learn next will plug in. Congratulations on graduating your first wargame.


Once every box is checked, Step 101 is complete. Click the checkbox in the sidebar to save your progress.