ISO/IEC 27001:2022 define en su Anexo A 93 controles agrupados en cuatro temas: organizativos, de personas, físicos y tecnológicos. En un servidor Linux, los que se implementan con configuración son sobre todo los tecnológicos (sección A.8). En este tutorial aplicarás en Ubuntu 24.04 un conjunto de controles concretos, cada uno asociado a su número del Anexo A, y reunirás las evidencias que un auditor te pedirá para demostrar que funcionan.

La norma no exige comandos concretos: exige que tus controles cumplan tu política y que puedas demostrarlo. Adapta los valores de esta guía (longitud de contraseña, retención de logs, puertos abiertos) a lo que diga la política de tu SGSI.

Requisitos previos

  • Un servidor con Ubuntu 24.04 LTS, por ejemplo un VPS de CubePath.
  • Un usuario no root con privilegios sudo y acceso por clave SSH ya configurado.
  • Acceso a la consola del proveedor (VNC/KVM) por si un cambio de SSH o firewall te deja fuera.
  • La política de seguridad y el alcance del SGSI, para saber qué valores aplicar.

Estos son los controles que cubre la guía:

Control del Anexo AQué aplicas en el servidor
A.8.2 Derechos de acceso privilegiadoRegistro de sudo en un log propio
A.8.5 Autenticación seguraPolítica de contraseñas con pwquality y SSH solo con claves
A.8.20 Seguridad de redesUFW con denegación por defecto y parámetros de red en sysctl
A.8.15 Registro de eventosReglas de auditd sobre identidades, sudo y SSH
A.8.8 Gestión de vulnerabilidades técnicasActualizaciones automáticas de seguridad
A.8.9 Gestión de la configuraciónDetección de cambios en ficheros con AIDE
A.8.16 Actividades de seguimientoEvidencias periódicas para la auditoría

Paso 1: Registrar el uso de sudo (A.8.2)

El control A.8.2 pide restringir y gestionar los accesos privilegiados. Empieza revisando quién puede usar sudo:

getent group sudo
sudo ls -l /etc/sudoers.d/
sudo:x:27:your_user

Cada miembro de ese grupo debe tener una justificación documentada. Después, envía la actividad de sudo a un fichero propio con fecha completa y host, y reduce a 5 minutos el tiempo que sudo recuerda la contraseña. Crea el fichero siempre con visudo, que valida la sintaxis antes de guardar:

sudo visudo -f /etc/sudoers.d/iso27001
Defaults logfile="/var/log/sudo.log"
Defaults log_year, log_host
Defaults timestamp_timeout=5

Comprueba que la sintaxis es correcta y lanza un comando para generar una entrada:

sudo visudo -c
sudo -k; sudo true
sudo tail -n 2 /var/log/sudo.log
Sep 25 10:14:02 2026 : your_user : HOST=srv01 : TTY=pts/0 ; PWD=/home/your_user ; USER=root ; COMMAND=/usr/bin/true

Configura la rotación de este log para conservarlo el tiempo que marque tu política (aquí, un año):

sudo nano /etc/logrotate.d/sudo-iso27001
/var/log/sudo.log {
    weekly
    rotate 52
    compress
    missingok
    notifempty
    create 0600 root root
}

Valida la configuración con una ejecución en seco:

sudo logrotate -d /etc/logrotate.d/sudo-iso27001

Paso 2: Aplicar una política de contraseñas (A.8.5)

Aunque el acceso por SSH sea solo con claves, las contraseñas locales siguen usándose para sudo y la consola. Instala el módulo PAM pwquality y la herramienta pwscore para probarlo:

sudo apt update
sudo apt install libpam-pwquality libpwquality-tools

Al instalarse, el paquete añade pam_pwquality a /etc/pam.d/common-password automáticamente. Define la política en un fichero propio dentro de pwquality.conf.d, así no se pisa con futuras actualizaciones:

sudo nano /etc/security/pwquality.conf.d/iso27001.conf
minlen = 14
minclass = 3
maxrepeat = 3
maxsequence = 3
usercheck = 1
dictcheck = 1
enforce_for_root

Comprueba que la política rechaza contraseñas débiles. pwscore lee la contraseña de la entrada estándar:

echo 'Verano2026' | pwscore
Password quality check failed:
 The password is shorter than 14 characters

Si tu política exige caducidad de contraseñas, ajusta PASS_MAX_DAYS en /etc/login.defs para los usuarios nuevos y aplícala a los existentes con chage. Ten en cuenta que la guía actual de NIST desaconseja la caducidad periódica si no hay indicios de compromiso, así que documenta la decisión en tu SGSI:

sudo chage -M 365 -W 14 your_user
sudo chage -l your_user

Paso 3: Permitir SSH solo con claves (A.8.5)

La autenticación con clave pública elimina los ataques de fuerza bruta contra contraseñas por SSH. Antes de continuar, confirma que puedes entrar con tu clave desde otra terminal. Después crea un fichero de configuración adicional; Ubuntu 24.04 carga todo lo que haya en /etc/ssh/sshd_config.d/:

sudo nano /etc/ssh/sshd_config.d/10-iso27001.conf
PermitRootLogin no
PasswordAuthentication no
KbdInteractiveAuthentication no
MaxAuthTries 3
LoginGraceTime 30

Valida la configuración y recarga el servicio:

sudo sshd -t
sudo systemctl reload ssh

sshd -t no muestra nada si todo es correcto. Confirma los valores efectivos:

sudo sshd -T | grep -E 'permitrootlogin|passwordauthentication|maxauthtries'
permitrootlogin no
passwordauthentication no
maxauthtries 3

Paso 4: Filtrar el tráfico de red (A.8.20)

El control A.8.20 pide proteger las redes y los servicios que las usan. Configura UFW para denegar todo el tráfico entrante salvo lo que el servidor necesita. Permite SSH antes de activarlo:

sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw limit OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable

ufw limit bloquea temporalmente una IP que abre 6 o más conexiones en 30 segundos. Abre 80 y 443 solo si el servidor publica un servicio web. Comprueba el resultado:

sudo ufw status verbose
Status: active
Default: deny (incoming), allow (outgoing), deny (routed)
To                         Action      From
--                         ------      ----
22/tcp (OpenSSH)           LIMIT IN    Anywhere
80/tcp                     ALLOW IN    Anywhere
443/tcp                    ALLOW IN    Anywhere

Añade además unos parámetros de red del kernel que rechazan redirecciones ICMP y paquetes con origen falsificado. Si el servidor hace de router, VPN o host de contenedores, no desactives el reenvío:

sudo nano /etc/sysctl.d/99-iso27001.conf
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1
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.send_redirects = 0
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.tcp_syncookies = 1

Carga todos los ficheros de sysctl.d y verifica un valor:

sudo sysctl --system
sysctl net.ipv4.conf.all.accept_redirects
net.ipv4.conf.all.accept_redirects = 0

Paso 5: Auditar eventos con auditd (A.8.15)

El control A.8.15 exige producir, guardar y proteger registros de actividad. auditd registra en el kernel los cambios en ficheros sensibles y la ejecución de comandos con privilegios. Instálalo:

sudo apt install auditd

Crea un fichero de reglas. Cada regla lleva una clave (-k) para poder buscar sus eventos después:

sudo nano /etc/audit/rules.d/50-iso27001.rules
## Identidades y privilegios
-w /etc/passwd -p wa -k identidad
-w /etc/shadow -p wa -k identidad
-w /etc/group -p wa -k identidad
-w /etc/gshadow -p wa -k identidad
-w /etc/sudoers -p wa -k privilegios
-w /etc/sudoers.d/ -p wa -k privilegios

## Configuración de acceso
-w /etc/ssh/sshd_config -p wa -k ssh
-w /etc/ssh/sshd_config.d/ -p wa -k ssh
-w /etc/pam.d/ -p wa -k pam

## Tareas programadas
-w /etc/cron.d/ -p wa -k cron
-w /etc/crontab -p wa -k cron
-w /var/spool/cron/ -p wa -k cron

## Comandos ejecutados como root por un usuario real
-a always,exit -F arch=b64 -S execve -F euid=0 -F auid>=1000 -F auid!=unset -k comandos_root

Carga las reglas y comprueba que el kernel las tiene activas:

sudo augenrules --load
sudo auditctl -l | head -n 5
-w /etc/passwd -p wa -k identidad
-w /etc/shadow -p wa -k identidad
-w /etc/group -p wa -k identidad
-w /etc/gshadow -p wa -k identidad
-w /etc/sudoers -p wa -k privilegios

Provoca un evento y búscalo por su clave:

sudo touch /etc/sudoers.d/iso27001
sudo ausearch -k privilegios -ts recent -i | tail -n 3

La salida muestra el usuario original (auid), el comando y el fichero modificado. Por defecto auditd guarda los registros en /var/log/audit/audit.log y rota con los parámetros max_log_file y num_logs de /etc/audit/auditd.conf. Si tu política exige conservar los logs fuera del servidor, envíalos a un sistema centralizado con rsyslog o tu agente de SIEM.

Paso 6: Aplicar parches de seguridad automáticamente (A.8.8)

El control A.8.8 pide identificar y corregir vulnerabilidades técnicas a tiempo. Ubuntu 24.04 trae unattended-upgrades, que por defecto instala solo las actualizaciones del origen -security. Asegúrate de que está instalado y activado:

sudo apt install unattended-upgrades
sudo dpkg-reconfigure -plow unattended-upgrades

Responde Yes a la pregunta. Esto escribe /etc/apt/apt.conf.d/20auto-upgrades. Comprueba su contenido:

cat /etc/apt/apt.conf.d/20auto-upgrades
APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";

Para cambiar opciones sin tocar el fichero principal del paquete, crea uno propio que se lea después:

sudo nano /etc/apt/apt.conf.d/52iso27001
Unattended-Upgrade::Remove-Unused-Kernel-Packages "true";
Unattended-Upgrade::Automatic-Reboot "false";

Deja el reinicio automático desactivado si tus reinicios deben pasar por gestión de cambios, y revisa el fichero /var/run/reboot-required, que aparece cuando un parche del kernel lo necesita. Haz una prueba en seco:

sudo unattended-upgrade --dry-run --debug 2>&1 | grep -i 'allowed origins'
Allowed origins are: o=Ubuntu,a=noble, o=Ubuntu,a=noble-security, o=UbuntuESMApps,a=noble-apps-security, o=UbuntuESM,a=noble-infra-security

El historial de lo instalado queda en /var/log/unattended-upgrades/unattended-upgrades.log, una evidencia directa para este control.

Paso 7: Detectar cambios no autorizados con AIDE (A.8.9)

El control A.8.9 pide establecer, documentar y supervisar las configuraciones. AIDE guarda una base de datos con los hashes y atributos de los ficheros del sistema y avisa de cualquier diferencia posterior. Instálalo:

sudo apt install aide

Genera la base de datos inicial. Tarda unos minutos, porque recorre todo el sistema:

sudo aideinit

El comando crea la base de referencia en /var/lib/aide/aide.db. Comprueba que existe y lanza una verificación manual:

sudo ls -lh /var/lib/aide/aide.db
sudo aide --config /etc/aide/aide.conf --check

Si no ha cambiado nada, la salida termina con un resumen sin diferencias. Tras modificar ficheros (por ejemplo, las reglas de los pasos anteriores), AIDE los listará como changed. El paquete instala además una comprobación diaria que envía su informe al usuario root por correo, así que configura un agente de correo o la redirección de root si quieres recibirlo.

Cada vez que hagas un cambio aprobado, actualiza la referencia para que el siguiente informe solo muestre cambios nuevos:

sudo aide --config /etc/aide/aide.conf --update
sudo cp /var/lib/aide/aide.db.new /var/lib/aide/aide.db

Paso 8: Reunir evidencias para la auditoría (A.8.16)

Un auditor no se conforma con que digas que el control existe: pide pruebas fechadas. Este script guarda en un directorio con la fecha del día el estado de los controles anteriores. Créalo:

sudo nano /usr/local/sbin/iso27001-evidencias
#!/usr/bin/env bash
set -euo pipefail

destino="/var/lib/iso27001/$(date +%F)"
install -d -m 0700 "$destino"

getent group sudo > "$destino/grupo-sudo.txt"
sshd -T > "$destino/sshd-efectivo.txt"
ufw status verbose > "$destino/ufw.txt"
auditctl -l > "$destino/auditd-reglas.txt"
aureport --summary --start today > "$destino/auditd-resumen.txt" || true
apt list --upgradable 2>/dev/null > "$destino/pendientes.txt"
systemctl list-units --state=failed --no-legend > "$destino/servicios-fallidos.txt"

sha256sum "$destino"/*.txt > "$destino/SHA256SUMS"

Hazlo ejecutable y pruébalo:

sudo chmod 0750 /usr/local/sbin/iso27001-evidencias
sudo /usr/local/sbin/iso27001-evidencias
sudo ls /var/lib/iso27001/$(date +%F)
SHA256SUMS  auditd-reglas.txt  auditd-resumen.txt  grupo-sudo.txt  pendientes.txt  servicios-fallidos.txt  sshd-efectivo.txt  ufw.txt

Prográmalo cada semana con un temporizador de systemd. Primero el servicio:

sudo nano /etc/systemd/system/iso27001-evidencias.service
[Unit]
Description=Recogida de evidencias ISO 27001

[Service]
Type=oneshot
ExecStart=/usr/local/sbin/iso27001-evidencias

Después el temporizador:

sudo nano /etc/systemd/system/iso27001-evidencias.timer
[Unit]
Description=Recogida semanal de evidencias ISO 27001

[Timer]
OnCalendar=Mon *-*-* 06:00:00
Persistent=true

[Install]
WantedBy=timers.target

Actívalo y comprueba la próxima ejecución:

sudo systemctl daemon-reload
sudo systemctl enable --now iso27001-evidencias.timer
systemctl list-timers iso27001-evidencias.timer

Copia periódicamente /var/lib/iso27001/ fuera del servidor para que las evidencias sobrevivan a un incidente.

Solución de problemas

Te has quedado sin acceso SSH. Entra por la consola VNC del proveedor, revisa /etc/ssh/sshd_config.d/10-iso27001.conf y ejecuta sudo sshd -t. Si el bloqueo viene de UFW, comprueba que existe la regla con sudo ufw status y añádela con sudo ufw limit OpenSSH.

augenrules --load no aplica las reglas. Si la configuración contiene -e 2, las reglas son inmutables hasta el siguiente reinicio. Comprueba el estado con sudo auditctl -s (campo enabled 2) y reinicia el servidor para cargar las nuevas.

AIDE informa de cientos de cambios tras una actualización. Es normal cuando unattended-upgrades actualiza paquetes. Revisa que los ficheros cambiados corresponden a paquetes del log de actualizaciones y regenera la referencia con aide --update.

pwscore acepta contraseñas que deberían fallar. Comprueba que el fichero está en /etc/security/pwquality.conf.d/ con extensión .conf y que /etc/pam.d/common-password contiene una línea con pam_pwquality.so.

Conclusión

Has aplicado en Ubuntu 24.04 siete controles tecnológicos del Anexo A de ISO 27001 y tienes una recogida automática de evidencias fechadas para demostrar que siguen activos. Como siguientes pasos, documenta cada control en tu Declaración de Aplicabilidad con su responsable y su evidencia, centraliza los logs de auditd y sudo en un SIEM, y automatiza esta configuración con Ansible para aplicarla igual en todos los servidores del alcance.