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 sudo y 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:

PerfilQué persigueImpacto
Level 1 ServerControles básicos que casi cualquier servidor debería cumplirBajo, rara vez rompe servicios
Level 2 ServerDefensa 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 .

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

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.