Phabricator is a widely deployed open-source software development platform (used by Facebook, Wikimedia, and many organizations) covering code review (Differential), task tracking (Maniphest), repository hosting (Diffusion), and project management, making it a high-value target as it centralizes source code and development workflows. Key assessment areas: Phabricator's Conduit API provides programmatic access to all tasks, code reviews, repositories, users, and project data; conf/local/local.json stores the MySQL database credentials; the conduit_token database table stores all API tokens; Diffusion (repository hosting) may allow cloning repositories without authentication on misconfigured instances; and Phabricator's file storage may expose uploaded files and code attachments. This guide covers systematic Phabricator security assessment.
# Phabricator — authentication and Conduit API token testing
PHAB_URL="https://phabricator.example.com"
# Phabricator Conduit API authentication — token-based
# Generate a Conduit token: Settings > Conduit API Tokens
CONDUIT_TOKEN="cli-abc123yourtokenhere"
# Verify token and get current user identity
curl -s -X POST "${PHAB_URL}/api/user.whoami" \
-d "api.token=${CONDUIT_TOKEN}" 2>/dev/null | python3 -c "
import json,sys
d=json.load(sys.stdin)
r=d.get('result',{})
if r:
print(f'Authenticated as: {r.get(\"userName\")} ({r.get(\"primaryEmail\")})')
print(f'PHID: {r.get(\"phid\")}')
print(f'Is admin: {r.get(\"isAdmin\")}')
else:
print(f'Error: {d.get(\"error_info\")}')
" 2>/dev/null
# Enumerate all Conduit API tokens in the database (with DB access)
# conduit_token table — lists all active API tokens
mysql -u phabricator -p"DB_PASSWORD" phabricator_conduit 2>/dev/null << 'EOF'
SELECT ct.tokenType, ct.token, ct.userPHID,
u.userName, u.userEmail
FROM conduit_token ct
JOIN phabricator_user.user u ON ct.userPHID = u.phid
WHERE ct.expired IS NULL OR ct.expired = 0
ORDER BY u.userName;
EOF
# Phabricator Conduit API — task, repository, and user enumeration
PHAB_URL="https://phabricator.example.com"
CONDUIT_TOKEN="cli-your-token-here"
# Maniphest — enumerate all tasks including private ones (if admin)
curl -s -X POST "${PHAB_URL}/api/maniphest.search" \
-d "api.token=${CONDUIT_TOKEN}" \
-d "queryKey=all" \
-d "limit=100" 2>/dev/null | python3 -c "
import json,sys
d=json.load(sys.stdin)
tasks = d.get('result',{}).get('data',[])
print(f'Tasks: {len(tasks)}')
for t in tasks[:10]:
fields = t.get('fields',{})
print(f' T{t.get(\"id\")}: {fields.get(\"name\")} status={fields.get(\"status\",{}).get(\"value\")} priority={fields.get(\"priority\",{}).get(\"value\")}')
" 2>/dev/null
# Differential — all code reviews (diffs contain source code)
curl -s -X POST "${PHAB_URL}/api/differential.revision.search" \
-d "api.token=${CONDUIT_TOKEN}" \
-d "queryKey=all" \
-d "limit=50" 2>/dev/null | python3 -c "
import json,sys
d=json.load(sys.stdin)
revs = d.get('result',{}).get('data',[])
print(f'Code reviews: {len(revs)}')
for r in revs[:5]:
fields = r.get('fields',{})
print(f' D{r.get(\"id\")}: {fields.get(\"title\")} status={fields.get(\"status\",{}).get(\"value\")}')
" 2>/dev/null
# Diffusion — list all repositories (source code access)
curl -s -X POST "${PHAB_URL}/api/diffusion.repository.search" \
-d "api.token=${CONDUIT_TOKEN}" \
-d "limit=50" 2>/dev/null | python3 -c "
import json,sys
d=json.load(sys.stdin)
repos = d.get('result',{}).get('data',[])
print(f'Repositories: {len(repos)}')
for r in repos[:10]:
fields = r.get('fields',{})
uris = fields.get('uri',{})
print(f' [{r.get(\"id\")}] {fields.get(\"name\")} vcs={fields.get(\"vcs\")} uri={uris.get(\"effective\")}')
" 2>/dev/null
# User enumeration — all accounts with emails
curl -s -X POST "${PHAB_URL}/api/user.search" \
-d "api.token=${CONDUIT_TOKEN}" \
-d "limit=100" 2>/dev/null | python3 -c "
import json,sys
d=json.load(sys.stdin)
users = d.get('result',{}).get('data',[])
print(f'Users: {len(users)}')
for u in users[:10]:
fields = u.get('fields',{})
print(f' {fields.get(\"username\")} email={fields.get(\"primaryEmail\")} roles={fields.get(\"roles\")}')
" 2>/dev/null
# Phabricator local.json and database credential extraction
# conf/local/local.json — MySQL credentials and configuration
cat /var/www/phabricator/conf/local/local.json 2>/dev/null | python3 -c "
import json,sys
d=json.load(sys.stdin)
for k,v in d.items():
if any(s in k.lower() for s in ['pass','secret','key','mysql','storage']):
print(f'{k}: {v}')
" 2>/dev/null
# mysql.pass — database password
# storage.local-disk.path — file storage path
# phabricator.base-uri — deployment URL
# MySQL direct access — all Phabricator databases
# Phabricator uses a separate database per application
mysql -u phabricator -p"DB_PASSWORD" 2>/dev/null << 'EOF'
SHOW DATABASES LIKE 'phabricator_%';
EOF
# Returns: phabricator_user, phabricator_maniphest, phabricator_differential,
# phabricator_repository, phabricator_conduit, etc.
# phabricator_user — all user accounts and bcrypt password hashes
mysql -u phabricator -p"DB_PASSWORD" phabricator_user 2>/dev/null << 'EOF'
SELECT u.userName, u.userEmail, u.isAdmin, u.isDisabled,
p.passwordHash
FROM user u
LEFT JOIN user_password p ON u.phid = p.userPHID
LIMIT 20;
EOF
# phabricator_repository — all repos including private
mysql -u phabricator -p"DB_PASSWORD" phabricator_repository 2>/dev/null << 'EOF'
SELECT name, callsign, versionControlSystem, localPath, isImporting
FROM repository
WHERE isImporting = 0
LIMIT 20;
EOF
| Security Test | Method | Risk |
|---|---|---|
| Conduit API task and code review enumeration | POST /api/maniphest.search queryKey:all — all tasks; POST /api/differential.revision.search — all code reviews with diff content; high-value data on development priorities and source code changes | Critical |
| Repository enumeration and clone access | POST /api/diffusion.repository.search — all repos with URIs; git clone via SSH using user's key or unauthenticated if misconfigured; full source code access for all hosted repositories | Critical |
| local.json MySQL credential extraction | Read conf/local/local.json — mysql.pass database password; direct MySQL access to all Phabricator databases including users (bcrypt hashes), conduit tokens, and all development data | Critical |
| conduit_token table API key enumeration | MySQL SELECT from phabricator_conduit.conduit_token — all active API tokens with user PHID; enables API access as any user by reusing their token | Critical |
| User email harvesting | POST /api/user.search — all users with primary emails and admin status; enables targeted phishing and credential attacks against developers and admins | High |
Ironimo tests Phabricator deployments for Conduit API authentication, task and code review enumeration via Maniphest and Differential, repository access testing via Diffusion, local.json MySQL credential extraction, conduit_token table active key enumeration, user email harvesting, file storage path exposure testing, repository policy misconfiguration detection, and SSH key audit for deactivated users.
Start free scan