Git Repository Exploitation
An exposed .git directory confirmed in vulnerability discovery allows reconstructing the full repository from the web server. This recovers complete application source code, all historical commits including deleted files, hardcoded credentials, and API keys that may no longer appear in the current codebase. The most valuable finds are often not in the current checkout. Developers rotate credentials after a breach but rarely rewrite git history. Old commits frequently contain database passwords, cloud provider keys, and internal service tokens that still work. Config management transitions leave traces. An application that moved from hardcoded values to environment variables will have a commit marking the change. The old values sit in the diff directly above it.
After dumping a git repository, focus on these high-value targets:
.envfiles with database passwords, API keys, and app secrets- Configuration files (
config.php,settings.py, YAML configs) with hardcoded credentials - Deleted commits containing rotated secrets that may still be valid
- SSH private keys and cloud provider tokens in the commit history
- Remote URLs in
.git/configpointing to other private repositories
Once you have the source code, apply source code review methodology to find vulnerabilities through sink-to-source tracing.
Dump the Repository with git-dumper
git-dumper reconstructs the full git repository from an exposed .git directory. It handles missing directory listings by inferring object hashes from the git pack index. The tool works even when web server directory listing is disabled. A successful dump ends with git checkout . restoring the working tree from the object store. If the dump fails partway through, re-run the same command. git-dumper resumes from what it already fetched. If object requests return 403 after the initial HEAD check passes, a WAF is blocking selective path requests. Lower concurrency with --threads 1 to reduce the request rate:
[+] Testing http://10.10.10.50/.git/HEAD [200] [+] Fetching .git/ [+] Running git checkout .
Explain command
| http://$TARGET_IP:$PORT/.git | Target URL pointing to the exposed .git directory on the remote host. |
| /tmp/git_dump | Local destination directory where the dumped git repo will be saved. |
total 28 drwxr-xr-x 3 www-data www-data 4096 Mar 15 14:22 . drwxr-xr-x 12 user user 4096 Mar 15 14:22 .. drwxr-xr-x 8 www-data www-data 4096 Mar 15 14:22 .git -rw-r--r-- 1 www-data www-data 342 Mar 15 14:22 .env -rw-r--r-- 1 www-data www-data 2847 Mar 15 14:22 config.php -rw-r--r-- 1 www-data www-data 1204 Mar 15 14:22 index.php
Extract Credentials from Source
Search the dumped source for credentials, API keys, and connection strings. The .env file is the highest-priority target. Laravel, Django, Rails, and most modern frameworks store all sensitive configuration there. config.php, settings.py, and YAML configuration files are common secondary locations. When you find a database password, test it against any exposed database port on the target. When you find an API key, identify the service from context and test access. Cloud provider keys often carry broad permissions because developers give themselves admin access during development and rarely rotate before shipping. Check package.json or requirements.txt to identify what third-party services the app integrates with. That tells you which keys matter most to pursue.
/tmp/git_dump/.env:DB_PASSWORD=SuperSecret123! /tmp/git_dump/config.php:$db_pass = 'admin123';
Explain command
| -r | Recursively search all files under each directory. |
| -n | Prefix each output line with the file line number. |
| --include='*.php' | Limit search to files matching the *.php glob pattern. |
| --include='*.env' | Limit search to files matching the *.env glob pattern. |
| --include='*.py' | Limit search to files matching the *.py glob pattern. |
| --include='*.js' | Limit search to files matching the *.js glob pattern. |
| --include='*.yml' | Limit search to files matching the *.yml glob pattern. |
| -i | Perform case-insensitive pattern matching. |
| -E | Interpret the pattern as an extended regular expression (ERE). |
| 'password|passwd|secret|api_key|apikey|token|db_pass|database_password' | ERE pattern matching common credential and secret key identifiers. |
| /tmp/git_dump/ | Target directory to recursively search, typically a dumped git repo. |
Mine Commit History for Deleted Secrets
Credentials removed from the current codebase often remain in commit history. Search all commits for sensitive patterns. Commit messages are a useful signal before diving into diffs. A message like "Fix security issue - removed hardcoded credentials" points at the exact commit you want. Check the commit immediately before it. The removed credential appears as an added line in that earlier commit. git show on the target commit reveals the full file at that point in time. Pay attention to branch names from git log --all. Development and staging branches often diverge from main with less scrutiny. A dev or feature/ branch may contain credentials that were never merged to main.
a1b2c3d Fix security issue - removed hardcoded credentials b4c5d6e Initial commit with working config
Explain command
| /tmp/git_dump | Target directory to change into before running git commands. |
| --all | Show commits from all branches, tags, and refs. |
| --oneline | Condense each commit to a single line with short hash and message. |
$db_password = 'OldPassword!2023';
Explain command
| b4c5d6e:config.php | Show contents of config.php at commit b4c5d6e. |
| -iE | Case-insensitive search with extended regex pattern matching. |
| 'password|secret|key' | Regex pattern matching sensitive credential-related strings. |
Explain command
| /tmp/git_dump | Target directory containing the cloned/dumped git repository. |
| -p | Show patch diffs (changes) for each commit in the log. |
| --all | Include all refs (branches, tags, remotes) in the log output. |
| -iE | Case-insensitive search with extended regex pattern matching. |
| '\+.*password|\+.*secret|\+.*api_key' | Regex matching added lines containing password, secret, or api_key. |
| head -30 | Limit output to the first 30 matching lines. |
trufflehog for Automated Secret Mining
trufflehog scans all commits for high-entropy strings and known secret patterns automatically. It uses regex detectors for over 700 secret types including AWS keys, GitHub tokens, and Stripe keys. High-entropy detection catches generic secrets that do not match a known pattern. Use filesystem mode on the dumped repo to scan both the working tree and full git history. trufflehog validates many secret types against their respective APIs to confirm active credentials. An unverified result still warrants investigation. Parse the JSON output and look for SourceMetadata to find the exact file and commit where each secret appeared. If output volume is high, filter for "Verified": true first to prioritize confirmed active credentials before reviewing unverified hits.
Explain command
| filesystem | Scan a local filesystem path for secrets. |
| /tmp/git_dump/ | Target directory path to scan for exposed secrets. |
| --json | Output results in JSON format for machine parsing. |
| 2>/dev/null | Redirect stderr to null, suppressing error messages. |
| -m json.tool | Python module to pretty-print JSON input. |
| -A5 | Print 5 lines of trailing context after each match. |
| 'reason\|stringsFound' | Grep pattern matching reason or stringsFound fields in output. |
Take found credentials to the relevant service page for the next step. A database password goes to MySQL, PostgreSQL, or MSSQL exploitation depending on what .env reveals. Cloud keys go directly to the provider CLI. SSH private keys found in the repository allow direct access to any host they were provisioned for. Check .git/config for the remote URL. GitHub, GitLab, or Bitbucket tokens may grant access to other private repositories in the same organization. If credentials from history no longer work, try them on other services on the target. Password reuse between database credentials and system user accounts is common.
References
-
Repository reconstruction from exposed .git directories
-
Secret scanning across git history and filesystem