Aplicar un hardening completo de seguridad en Moodle desde cero puede llevar entre 40 y 80 horas de trabajo, según la complejidad de la instalación. Lo que de verdad marca la diferencia no es solo hacerlo una vez, sino mantenerlo: el parcheo mensual, la revisión de cabeceras de seguridad, los logs de auditoría y las dependencias del sistema actualizadas son, en la práctica, donde la mayoría de equipos pierden la disciplina con el tiempo.
Esta checklist reúne, en un único lugar, todos los puntos de hardening que deberían revisarse en cualquier instalación de Moodle en producción.
Permisos de archivo
| Punto | Verificado |
|---|---|
Código de la aplicación con propiedad root:root | ☐ |
Directorios del código en 755, archivos en 644 | ☐ |
moodledata con propiedad del usuario del servidor web | ☐ |
moodledata fuera del directorio públicamente accesible por web, si es posible | ☐ |
El objetivo de estos permisos es concreto: que el proceso del servidor web pueda leer el código pero no reescribirlo. Si Apache o PHP-FPM pueden modificar los .php de Moodle, cualquier fallo que permita escribir un archivo se convierte en ejecución de código arbitrario. En la práctica se traduce en tres comandos:
# Código de Moodle: propiedad de root, solo lectura para el servidor web
chown -R root:root /var/www/moodle
find /var/www/moodle -type d -exec chmod 755 {} \;
find /var/www/moodle -type f -exec chmod 644 {} \;
# moodledata: propiedad del usuario del servidor web, y FUERA del webroot
chown -R www-data:www-data /var/moodledata
chmod 700 /var/moodledata
El error clásico que vemos entrar por soporte es moodledata colgando dentro de /var/www/moodle/moodledata, alcanzable por URL. Ahí viven los backups, los archivos de sesión y todo lo que suben los usuarios: si es accesible por web, alguien puede descargar datos de alumnos sin ni siquiera autenticarse. moodledata debe estar en una ruta que el servidor web no sirva jamás, normalmente un nivel por encima del DocumentRoot.
Autenticación y contraseñas
| Punto | Verificado |
|---|---|
| Longitud mínima de contraseña en 12 caracteres o más | ☐ |
| Complejidad exigida: mayúsculas, minúsculas, dígitos, caracteres especiales | ☐ |
| Validación contra bases de datos de credenciales filtradas conocidas | ☐ |
| Autenticación multifactor activada para cuentas administrativas | ☐ |
| Protección contra fuerza bruta a nivel de aplicación | ☐ |
| Protección contra fuerza bruta a nivel de servidor (fail2ban u equivalente) | ☐ |
La política de contraseñas se ajusta en Administración del sitio > Seguridad > Políticas de seguridad del sitio (passwordpolicy). Los parámetros que importan: minpasswordlength (súbelo a 12 como mínimo) y los mínimos de dígitos, mayúsculas, minúsculas y caracteres no alfanuméricos (minpassworddigits, minpasswordupper, minpasswordlower, minpasswordnonalphanum). En esa misma pantalla vive el bloqueo de cuenta, la primera línea contra fuerza bruta: lockoutthreshold (intentos antes de bloquear, p. ej. 5), lockoutwindow y lockoutduration.
Ese bloqueo por usuario no basta por sí solo. Frena a quien machaca una cuenta concreta, pero no a un barrido que prueba una IP distinta en cada intento. La segunda línea es fail2ban a nivel de servidor, leyendo los logs de acceso y cortando la IP antes de que la petición llegue siquiera a PHP. Las dos capas se complementan; ninguna sustituye a la otra.
La MFA merece un punto aparte. En las versiones recientes Moodle trae autenticación multifactor integrada en el núcleo (antes era el plugin tool_mfa). Actívala al menos para todos los roles con capacidades administrativas: la contraseña de un administrador, por muy robusta que sea, sigue siendo una brecha total si se filtra y no hay segundo factor. Y no pierdas de vista $CFG->forcelogin: por defecto Moodle deja la portada y algunos recursos visibles sin sesión iniciada; si tu campus no es un catálogo público, fuérzalo.
Configuración de PHP y servidor
| Punto | Verificado |
|---|---|
zend.exception_ignore_args = 1 configurado, para evitar exposición de datos en trazas de error | ☐ |
| Versión de PHP dentro del rango soportado por tu versión de Moodle | ☐ |
Extensiones necesarias activas (sodium, mbstring, intl, curl) | ☐ |
| Cabeceras de seguridad HTTP revisadas (HSTS, X-Frame-Options, Content-Security-Policy) | ☐ |
| HTTPS forzado en todo el sitio, sin acceso HTTP sin cifrar disponible | ☐ |
Buena parte del hardening de sesión y transporte vive en config.php. Tres flags que no deberían faltar en producción:
// Fuerza que las cookies solo viajen por HTTPS (requiere wwwroot con https://)
$CFG->cookiesecure = true;
// Impide que JavaScript lea la cookie de sesión (mitiga el robo por XSS)
$CFG->cookiehttponly = true;
// Obliga a iniciar sesión para ver cualquier página del sitio
$CFG->forcelogin = true;
El gotcha con cookiesecure: si tu $CFG->wwwroot todavía apunta a http://, activarlo deja a los usuarios sin poder iniciar sesión, porque el navegador nunca devolverá la cookie por un canal sin cifrar. El orden correcto es primero HTTPS de extremo a extremo (redirección 301 de HTTP a HTTPS en el servidor web y wwwroot con https://) y solo entonces marcar cookiesecure. La configuración fina del certificado da para su propio artículo; si vienes de ahí, revisa SSL y HTTPS en Moodle.
Las cabeceras de seguridad (HSTS, X-Frame-Options, Content-Security-Policy) se configuran en el servidor web, no en Moodle, y son fáciles de perder en una migración: al mover el sitio a otro hosting, la configuración del virtual host se rehace y las cabeceras se quedan por el camino. Por eso están en la checklist de revisión periódica, no solo en la de instalación inicial.
Correo y comunicaciones
| Punto | Verificado |
|---|---|
| SPF configurado para el dominio de envío de correo | ☐ |
| DKIM activo en el servidor de correo saliente | ☐ |
| Política DMARC publicada y revisada periódicamente | ☐ |
El correo saliente de Moodle (avisos de foro, restablecimiento de contraseña, notificaciones de tareas) es un objetivo cómodo para la suplantación: si tu dominio no autentica lo que envía, cualquiera puede mandar correos que parezcan venir del campus, y los mensajes legítimos de Moodle acaban en spam. SPF, DKIM y DMARC son tres registros que se configuran en DNS y en el servidor de correo, no dentro de Moodle. El detalle de cada uno lo cubrimos en SPF, DKIM y DMARC para el correo de Moodle; en esta checklist basta con dejar constancia de que los tres estén publicados y de que la política DMARC no se quede en p=none para siempre.
Backups y recuperación
| Punto | Verificado |
|---|---|
| Backups automáticos diarios configurados | ☐ |
| Backups almacenados fuera del servidor de producción | ☐ |
| Restauración de prueba realizada al menos mensualmente | ☐ |
| Origen de cualquier backup verificado antes de restaurar | ☐ |
Monitorización y avisos
| Punto | Verificado |
|---|---|
| Informe de Security Checks de Moodle revisado mensualmente | ☐ |
| Suscripción activa al foro oficial de anuncios de seguridad de Moodle | ☐ |
| Monitorización de uptime activa, con aviso inmediato ante caída | ☐ |
| Revisión periódica de logs en busca de actividad anómala | ☐ |
Roles y accesos
| Punto | Verificado |
|---|---|
| Roles y permisos revisados, sin privilegios excesivos por defecto | ☐ |
| Plugins de terceros auditados antes de instalar, sin vulnerabilidades conocidas activas | ☐ |
| Cuentas de usuarios inactivas o de exalumnos/exempleados desactivadas periódicamente | ☐ |
Por dónde empezar si partes de cero
- Permisos de archivo primero: es la base sobre la que se apoya todo lo demás, y de las medidas más rápidas de aplicar con impacto inmediato.
- Contraseñas y autenticación: segunda prioridad, ya que las credenciales comprometidas son uno de los vectores de acceso más comunes.
- PHP y servidor: revisar configuración de cabeceras y versión antes de que un cambio de versión de Moodle lo fuerce de todos modos.
- Correo, backups y monitorización: capas que no evitan un ataque directamente, pero que determinan cuánto daño causa y cuánto tardas en detectarlo.
- Roles y accesos: revisión continua, no un punto que se resuelve una vez y se olvida.
Si prefieres verlo por riesgo en lugar de por orden, esta tabla resume qué te expones a perder en cada área y dónde se toca cada ajuste:
| Área | Riesgo si no se aplica | Dónde se configura |
|---|---|---|
| Permisos de archivo | Escritura por web → ejecución de código | Sistema de ficheros (chmod/chown) |
| Política de contraseñas | Credenciales débiles y adivinables | Admin > Seguridad > Políticas de seguridad |
| Bloqueo de cuenta + fail2ban | Fuerza bruta sin límite | Admin (lockout) + servidor (fail2ban) |
| MFA | Una contraseña filtrada = brecha total | Núcleo de Moodle (MFA) |
HTTPS + cookiesecure | Robo de sesión en tránsito | Servidor web + config.php |
| PHP y núcleo al día | Explotación de un CVE ya público | Servidor + actualización de Moodle |
| SPF/DKIM/DMARC | Suplantación del correo del campus | DNS + servidor de correo |
| Backups verificados | Sin recuperación tras un incidente | Servidor de backup + prueba de restauración |
Mantenimiento continuo: donde la mayoría falla
Completar esta checklist una vez es relativamente sencillo comparado con mantenerla activa en el tiempo. El parcheo mensual, la revisión de logs, la comprobación de que las cabeceras de seguridad siguen bien configuradas tras un cambio de servidor, y la verificación periódica de backups son tareas recurrentes, no proyectos de una sola vez, y es exactamente ahí donde la mayoría de equipos internos pierden constancia con el tiempo, no en la configuración inicial.
El punto que más se descuida es el parcheo del núcleo. Moodle publica avisos de seguridad de forma regular, y cada aviso describe con detalle una vulnerabilidad que a partir de ese momento es pública y explotable en cualquier instalación sin actualizar. El hardening no cierra esa puerta de una vez: la mantiene cerrada solo si aplicas las actualizaciones en semanas, no en meses. Es el mismo hilo que desarrollamos en cómo proteger Moodle de ataques y vulnerabilidades, donde el foco está en la respuesta a los CVE conocidos más que en la configuración base.
Preguntas frecuentes
¿Cuánto tiempo lleva aplicar todo este hardening desde cero? Entre 40 y 80 horas de trabajo inicial, según la complejidad de la instalación, sin contar el mantenimiento continuo posterior.
¿Puedo aplicar esta checklist de forma parcial y seguir estando protegido? Cada punto reduce un riesgo específico de forma independiente, pero la protección real viene de aplicar el conjunto, no de una única medida aislada.
¿Con qué frecuencia debería repasar esta checklist completa? Al menos una vez al año de forma exhaustiva, y de forma continua en los puntos de monitorización, backups y parcheo, que no admiten revisión anual únicamente.
¿Qué punto de la checklist tiene más impacto con menos esfuerzo? Los permisos de archivo correctos y la política de contraseñas mínima de 12 caracteres son de las medidas más rápidas de aplicar con un impacto de seguridad desproporcionadamente alto.
¿Necesito contratar a alguien externo para aplicar todo esto? No es obligatorio si tienes conocimiento técnico interno y tiempo dedicado, pero dado el volumen de horas y la necesidad de mantenimiento continuo, muchos centros optan por externalizar esta parte.
¿Esta checklist es válida para cualquier versión de Moodle? Los principios generales sí, aunque algunos detalles concretos (extensiones de PHP requeridas, ajustes específicos) varían según la versión exacta que uses.
¿Qué es lo primero que debería tocar en config.php?
$CFG->cookiesecure, $CFG->cookiehttponly y $CFG->forcelogin. Los dos primeros protegen la cookie de sesión y el tercero cierra el acceso anónimo. Pero antes de activar cookiesecure, asegúrate de que todo el sitio ya funciona por HTTPS y de que wwwroot apunta a https://; si no, dejarás a los usuarios sin poder entrar.
¿El bloqueo de cuenta de Moodle es suficiente contra la fuerza bruta?
No por sí solo. lockoutthreshold protege una cuenta concreta, pero no frena un barrido que prueba una IP diferente en cada intento. Combínalo siempre con fail2ban (u otro filtro a nivel de servidor) que corte la IP leyendo los logs de acceso, antes de que la petición llegue a PHP.
¿Cada cuánto hay que actualizar el núcleo de Moodle? En cuanto salga un aviso de seguridad, que Moodle publica con regularidad. Cada aviso convierte una vulnerabilidad en información pública, así que la ventana entre el anuncio y el parcheo es justo cuando eres más vulnerable. La meta es aplicar en semanas, no dejarlo para la siguiente revisión trimestral.
Conclusión
El hardening de Moodle no es un proyecto que se completa y se olvida, es una checklist que hay que mantener viva mes a mes. La configuración inicial es importante, pero el verdadero reto está en sostener la disciplina de parchear, revisar logs y probar backups con la misma constancia en el mes doce que en el mes uno.
Si prefieres no tener que mantener tú mismo esta disciplina, en Avantys aplicamos y sostenemos esta checklist como parte del mantenimiento continuo de cada Moodle que gestionamos. Puedes pedir una auditoría gratuita en Moodle Gestionado.
Artículos relacionados
- Mantenimiento y hosting Moodle: guía completa
- Cómo proteger Moodle de ataques y vulnerabilidades
- SSL y HTTPS en Moodle: configuración correcta
- SPF, DKIM y DMARC para el correo de Moodle
- Backups de Moodle: cómo verificar que restauran de verdad
¿Y si tu Moodle lo lleváramos nosotros?
Actualizaciones, backups verificados, rendimiento y trazabilidad FUNDAE, gestionado de forma continua por una persona que responde. Auditoría gratuita de tu plataforma actual.