Los CIS Benchmarks del Center for Internet Security son guías de configuración segura, con cientos de controles numerados, que auditores y equipos de seguridad usan como referencia de "servidor bastionado". Aplicarlos a mano uno por uno es lento y arriesgado, así que en este tutorial medirás el punto de partida con Lynis, auditarás el sistema contra el perfil CIS Level 1 Server con Ubuntu Security Guide (USG), aplicarás los controles de forma controlada y comprobarás el resultado. Todo sobre Ubuntu 24.04 LTS.
Requisitos previos
- Un servidor con Ubuntu 24.04 LTS, por ejemplo un VPS de CubePath recién instalado. No empieces por un servidor de producción con servicios críticos.
- Un usuario no root con privilegios
sudoy acceso SSH mediante clave pública ya funcionando. - Acceso a una consola alternativa (la consola web o VNC del servidor) por si un cambio de SSH te deja fuera.
- Una copia de seguridad o snapshot reciente del servidor.
- Para el paso 3: una cuenta de Ubuntu Pro. Es gratuita para uso personal en hasta 5 máquinas; en otro caso necesitas una suscripción. Si no la tienes, el paso 4 aplica los controles más importantes a mano.
Paso 1: Entender los niveles de perfil
Cada benchmark define perfiles. En un servidor te interesan dos:
| Perfil | Qué persigue | Impacto |
|---|---|---|
| Level 1 Server | Controles básicos que casi cualquier servidor debería cumplir | Bajo, rara vez rompe servicios |
| Level 2 Server | Defensa en profundidad para entornos de alta seguridad (particiones separadas, auditoría exhaustiva, AppArmor en modo enforce para todo) | Alto, requiere planificación |
Empieza siempre por Level 1. Los PDF oficiales se descargan gratis, con registro, desde cisecurity.org; tenlos a mano para consultar la justificación de cada control, porque la auditoría te dará identificadores de regla y no explicaciones.
Paso 2: Medir el punto de partida con Lynis
Lynis es un auditor de seguridad de código abierto. No evalúa el CIS Benchmark exacto, pero su índice de hardening es una buena referencia rápida del antes y el después.
sudo apt update
sudo apt install lynis
Lanza la auditoría completa:
sudo lynis audit system
Al final del informe verás el índice y la ruta de los resultados:
Lynis security scan details:
Hardening index : 61 [############ ]
Tests performed : 262
Plugins enabled : 0
- Test and debug information : /var/log/lynis.log
- Report data : /var/log/lynis-report.dat
Anota el valor de Hardening index. Para ver solo las advertencias y sugerencias:
sudo grep -E '^(warning|suggestion)\[\]' /var/log/lynis-report.dat
Guarda una copia del informe inicial para compararlo al terminar:
sudo cp /var/log/lynis-report.dat /root/lynis-antes.dat
Paso 3: Auditar y aplicar el perfil CIS con Ubuntu Security Guide
Ubuntu Security Guide (USG) es la herramienta de Canonical para auditar y remediar Ubuntu contra el CIS Benchmark y el DISA-STIG. Por debajo usa OpenSCAP con contenido mantenido por Canonical para cada versión de Ubuntu.
Vincula la máquina a Ubuntu Pro con el token de tu cuenta (lo encuentras en ubuntu.com/pro/dashboard) y activa USG:
sudo pro attach your_pro_token
sudo pro enable usg
sudo apt install usg
Comprueba que el servicio aparece como habilitado:
pro status
SERVICE ENTITLED STATUS DESCRIPTION
...
usg yes enabled Security compliance and audit tools
Auditar
Ejecuta la auditoría contra el perfil de nivel 1 para servidores:
sudo usg audit cis_level1_server
La auditoría tarda unos minutos y deja en /var/lib/usg/ un fichero de resultados XML y un informe HTML con cada regla marcada como pass o fail:
ls -l /var/lib/usg/
Copia el informe HTML a tu equipo para leerlo en el navegador:
scp your_user@your_server_ip:/var/lib/usg/usg-report-*.html .
Notasi
scpfalla por permisos, copia antes el informe a tu directorio personal consudo cpy cambia su propietario consudo chown.
Excluir las reglas que no encajan
Algunas reglas no tienen sentido en tu servidor: por ejemplo, las que exigen particiones separadas para /var/log o /home en un VPS con un único disco, o desactivar el reenvío IP en un host de Docker. Genera un fichero de tailoring, que es la forma soportada de adaptar el perfil:
sudo usg generate-tailoring cis_level1_server /root/tailor.xml
Abre el fichero y cambia selected="true" por selected="false" en las reglas que quieras excluir. Documenta el motivo de cada exclusión: un auditor te lo pedirá.
sudo nano /root/tailor.xml
Remediar
usg fix aplica automáticamente los cambios de las reglas seleccionadas. Afecta a SSH, PAM, módulos del kernel, sysctl y auditd, así que hazlo con una sesión SSH abierta de reserva y la consola a mano:
sudo usg fix --tailoring-file /root/tailor.xml
Reinicia para que los cambios de kernel, montaje y auditoría surtan efecto:
sudo reboot
Tras el reinicio, abre una sesión SSH nueva (sin cerrar la antigua si aún la tienes) y vuelve a auditar con el mismo tailoring:
sudo usg audit --tailoring-file /root/tailor.xml
El porcentaje de reglas en pass debería haber subido de forma notable. Las que sigan en fail suelen requerir una decisión manual (particiones, políticas de contraseñas de usuarios existentes, etc.).
Paso 4: Aplicar a mano los controles clave
Si no usas Ubuntu Pro, o quieres entender qué cambia USG, estos son los controles de nivel 1 con más impacto. Cada bloque indica la sección aproximada del benchmark.
Módulos de sistemas de archivos que no se usan (1.1.1)
Impide que el kernel cargue sistemas de archivos poco comunes, que amplían la superficie de ataque:
sudo nano /etc/modprobe.d/cis-filesystems.conf
install cramfs /bin/false
blacklist cramfs
install freevxfs /bin/false
blacklist freevxfs
install hfs /bin/false
blacklist hfs
install hfsplus /bin/false
blacklist hfsplus
install jffs2 /bin/false
blacklist jffs2
install udf /bin/false
blacklist udf
Advertenciano añadas
squashfsa esta lista en Ubuntu. Los paquetes snap se montan como squashfs y dejarían de funcionar.
Verifica que el módulo ya no se cargaría:
modprobe -n -v cramfs
install /bin/false
Parámetros de red del kernel (3.3)
Crea un fichero de sysctl con los valores del benchmark:
sudo nano /etc/sysctl.d/60-cis-network.conf
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv6.conf.all.accept_redirects = 0
net.ipv6.conf.default.accept_redirects = 0
net.ipv4.conf.all.secure_redirects = 0
net.ipv4.conf.default.secure_redirects = 0
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.default.accept_source_route = 0
net.ipv6.conf.all.accept_source_route = 0
net.ipv6.conf.default.accept_source_route = 0
net.ipv4.conf.all.log_martians = 1
net.ipv4.conf.default.log_martians = 1
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1
net.ipv4.icmp_echo_ignore_broadcasts = 1
net.ipv4.icmp_ignore_bogus_error_responses = 1
net.ipv4.tcp_syncookies = 1
El benchmark también pide net.ipv4.ip_forward = 0. No lo añadas si el servidor ejecuta Docker, Kubernetes, una VPN o hace de router, porque esos servicios necesitan el reenvío activo.
Aplica y comprueba:
sudo sysctl --system
sysctl net.ipv4.conf.all.accept_redirects net.ipv4.tcp_syncookies
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.tcp_syncookies = 1
SSH (5.1)
En Ubuntu 24.04, /etc/ssh/sshd_config incluye los ficheros de /etc/ssh/sshd_config.d/ al principio, y en OpenSSH gana el primer valor que se lee. Como cloud-init suele crear 50-cloud-init.conf, pon tu fichero con un número menor para que prevalezca:
sudo nano /etc/ssh/sshd_config.d/10-cis.conf
PermitRootLogin no
PasswordAuthentication no
PermitEmptyPasswords no
KbdInteractiveAuthentication no
HostbasedAuthentication no
IgnoreRhosts yes
PermitUserEnvironment no
X11Forwarding no
AllowTcpForwarding no
MaxAuthTries 4
MaxSessions 10
MaxStartups 10:30:60
LoginGraceTime 60
ClientAliveInterval 15
ClientAliveCountMax 3
LogLevel VERBOSE
Si usas túneles SSH (por ejemplo, para acceder a una base de datos), deja AllowTcpForwarding sin tocar y documenta la excepción.
Valida la sintaxis antes de reiniciar el servicio. Si sshd -t no devuelve nada, la configuración es correcta:
sudo sshd -t
sudo systemctl restart ssh
Comprueba los valores efectivos:
sudo sshd -T | grep -E 'permitrootlogin|passwordauthentication|maxauthtries|x11forwarding'
permitrootlogin no
passwordauthentication no
maxauthtries 4
x11forwarding no
Sin cerrar tu sesión actual, abre otra terminal y confirma que sigues pudiendo entrar con ssh your_user@your_server_ip.
Calidad y caducidad de contraseñas (5.3 y 5.4)
Aunque entres por clave, las contraseñas locales se siguen usando con sudo. Instala el módulo de calidad de contraseñas; el paquete lo añade a PAM automáticamente:
sudo apt install libpam-pwquality
sudo nano /etc/security/pwquality.conf.d/50-cis.conf
minlen = 14
minclass = 4
maxrepeat = 3
dictcheck = 1
enforce_for_root
Ajusta la caducidad para los usuarios nuevos en /etc/login.defs:
sudo sed -i 's/^PASS_MAX_DAYS.*/PASS_MAX_DAYS\t365/; s/^PASS_MIN_DAYS.*/PASS_MIN_DAYS\t1/; s/^PASS_WARN_AGE.*/PASS_WARN_AGE\t7/' /etc/login.defs
grep -E '^PASS_(MAX|MIN)_DAYS|^PASS_WARN_AGE' /etc/login.defs
Esos valores solo afectan a cuentas que crees a partir de ahora. Aplícalos también a tu usuario actual:
sudo chage --maxdays 365 --mindays 1 --warndays 7 your_user
sudo chage -l your_user
Auditoría con auditd (6.2)
El benchmark exige registrar cambios de identidad, de sudoers, de hora del sistema y de configuración de red. Instala auditd:
sudo apt install auditd audispd-plugins
Crea un fichero de reglas:
sudo nano /etc/audit/rules.d/50-cis.rules
## Cambios en usuarios y grupos
-w /etc/group -p wa -k identity
-w /etc/passwd -p wa -k identity
-w /etc/gshadow -p wa -k identity
-w /etc/shadow -p wa -k identity
## Cambios en sudo
-w /etc/sudoers -p wa -k scope
-w /etc/sudoers.d -p wa -k scope
## Comandos ejecutados como otro usuario (sudo, su)
-a always,exit -F arch=b64 -C euid!=uid -F auid!=unset -S execve -k user_emulation
## Cambios de fecha y hora
-a always,exit -F arch=b64 -S adjtimex,settimeofday,clock_settime -k time-change
-w /etc/localtime -p wa -k time-change
## Cambios en red y nombre del host
-a always,exit -F arch=b64 -S sethostname,setdomainname -k system-locale
-w /etc/hosts -p wa -k system-locale
-w /etc/netplan -p wa -k system-locale
## Inicios de sesión
-w /var/log/wtmp -p wa -k session
-w /var/log/btmp -p wa -k session
## Configuración de SSH
-w /etc/ssh/sshd_config -p wa -k sshd
-w /etc/ssh/sshd_config.d -p wa -k sshd
Carga las reglas y comprueba que están activas:
sudo augenrules --load
sudo auditctl -l | head
-w /etc/group -p wa -k identity
-w /etc/passwd -p wa -k identity
-w /etc/gshadow -p wa -k identity
-w /etc/shadow -p wa -k identity
-w /etc/sudoers -p wa -k scope
...
Prueba una regla: añade un usuario de prueba y busca el evento.
sudo useradd cis-test && sudo userdel cis-test
sudo ausearch -k identity -ts recent -i | tail -n 5
El benchmark pide además hacer las reglas inmutables con -e 2, de forma que nadie pueda cambiarlas sin reiniciar. Añádelo solo cuando la lista de reglas sea definitiva, como última línea de un fichero 99-finalize.rules, porque después cualquier ajuste requerirá un reinicio.
Paso 5: Volver a medir
Repite la auditoría de Lynis y compara:
sudo lynis audit system --quiet
sudo grep hardening_index /root/lynis-antes.dat /var/log/lynis-report.dat
/root/lynis-antes.dat:hardening_index=61
/var/log/lynis-report.dat:hardening_index=74
Si usas USG, la segunda ejecución de usg audit es la evidencia formal de cumplimiento. Guarda los informes HTML con fecha fuera del servidor.
Solución de problemas
No puedes entrar por SSH después del hardening. Entra por la consola del servidor y revisa los valores efectivos con sudo sshd -T. Lo más habitual es que tu usuario no tenga clave pública en ~/.ssh/authorized_keys y se haya desactivado PasswordAuthentication, o que un fichero con número menor en /etc/ssh/sshd_config.d/ contradiga al tuyo.
Un servicio deja de arrancar. Consulta su registro con journalctl -u nombre_servicio -n 50. Si depende del reenvío IP (Docker, WireGuard), comprueba sysctl net.ipv4.ip_forward y excluye esa regla en el tailoring.
sudo rechaza una contraseña nueva. pwquality exige ahora 14 caracteres y 4 clases (mayúsculas, minúsculas, dígitos y símbolos). El mensaje de passwd indica qué requisito no se cumple.
augenrules --load avisa de que las reglas no se pueden cambiar. Ya cargaste -e 2. Edita los ficheros de /etc/audit/rules.d/ y reinicia el servidor para que se apliquen.
Conclusión
Has medido el estado inicial de Ubuntu 24.04 con Lynis, auditado y remediado el perfil CIS Level 1 Server con USG, y aplicado a mano los controles de SSH, kernel, contraseñas y auditoría que más pesan en el benchmark. Como siguientes pasos, programa una auditoría periódica para detectar desviaciones, envía los registros de auditd a un servidor central y valora qué controles del nivel 2 encajan en tus servidores más sensibles.
