--- title: "Checklist de auditoría de seguridad en Linux con comandos" description: "Audita un servidor Ubuntu 24.04 paso a paso: actualizaciones, usuarios, sudo, SSH, puertos, firewall, kernel, permisos y registros, con su comando." category: "Seguridad del Servidor" language: es source: https://cubepath.com/es/docs/seguridad-del-servidor/lista-de-verificacion-de-auditoria-de-seguridad-con-comandos updated: 2026-09-25 --- # Checklist de auditoría de seguridad en Linux con comandos Una auditoría de seguridad manual consiste en recorrer, de forma ordenada, los puntos por los que un servidor suele quedar expuesto: paquetes sin actualizar, cuentas sobrantes, SSH permisivo, puertos abiertos sin motivo, permisos incorrectos o registros que nadie revisa. En esta guía tienes una lista de verificación para Ubuntu 24.04 en la que cada punto va acompañado del comando que lo comprueba, del resultado esperado y de cómo corregirlo. Al final guardarás las evidencias en un directorio fechado para poder comparar auditorías futuras. Todos los comandos son de solo lectura salvo los que aparecen explícitamente como corrección. ## Requisitos previos - Un servidor con Ubuntu 24.04 LTS, por ejemplo un VPS de CubePath. Casi todo sirve en Debian 12; las diferencias para Rocky Linux 9 se indican donde importan. - Un usuario no root con privilegios `sudo`. - Una segunda sesión SSH abierta antes de modificar SSH o el firewall, para no quedarte fuera. ## Paso 1: Preparar el directorio de evidencias Guardar la salida de cada comprobación te permite demostrar qué revisaste y comparar con la siguiente auditoría. Crea un directorio protegido con la fecha del día: ```bash AUDIT_DIR="$HOME/auditoria-$(date +%F)" mkdir -p "$AUDIT_DIR" chmod 700 "$AUDIT_DIR" ``` A lo largo de la guía puedes añadir `| tee "$AUDIT_DIR/nombre.txt"` a cualquier comando para guardar su salida. Empieza por la información básica del sistema: ```bash hostnamectl | tee "$AUDIT_DIR/sistema.txt" uname -r | tee -a "$AUDIT_DIR/sistema.txt" ``` ```output Static hostname: web01 Operating System: Ubuntu 24.04.3 LTS Kernel: Linux 6.8.0-84-generic Architecture: x86-64 ``` ## Paso 2: Actualizaciones y parches Los paquetes con vulnerabilidades conocidas son la vía de entrada más común. Comprueba qué hay pendiente: ```bash sudo apt update apt list --upgradable ``` **Esperado:** lista vacía o solo paquetes publicados en los últimos días. Comprueba si hay un reinicio pendiente (por ejemplo, tras actualizar el kernel): ```bash cat /var/run/reboot-required 2>/dev/null || echo "No hace falta reiniciar" ``` Verifica que las actualizaciones de seguridad automáticas están activas: ```bash cat /etc/apt/apt.conf.d/20auto-upgrades systemctl is-enabled unattended-upgrades ``` ```output APT::Periodic::Update-Package-Lists "1"; APT::Periodic::Unattended-Upgrade "1"; enabled ``` **Corrección:** si falta el archivo o los valores son `0`, instala y activa el paquete: ```bash sudo apt install unattended-upgrades sudo dpkg-reconfigure -plow unattended-upgrades ``` En Rocky Linux 9 el equivalente es `sudo dnf check-update` y el paquete `dnf-automatic`. ## Paso 3: Cuentas de usuario Solo `root` debe tener UID 0. Cualquier otra cuenta con UID 0 tiene privilegios completos: ```bash awk -F: '$3 == 0 {print $1}' /etc/passwd ``` ```output root ``` Ninguna cuenta debe tener la contraseña vacía: ```bash sudo awk -F: '$2 == "" {print $1}' /etc/shadow ``` **Esperado:** ninguna salida. **Corrección:** bloquea la cuenta con `sudo passwd -l nombre_usuario`. Lista las cuentas que pueden iniciar sesión con una shell interactiva y confirma que conoces a todas: ```bash grep -Ev '(/nologin|/false)$' /etc/passwd | cut -d: -f1,3,7 ``` Revisa los inicios de sesión recientes y los intentos fallidos: ```bash last -n 20 sudo lastb -n 20 ``` **Corrección:** elimina las cuentas que ya no se usan con `sudo deluser --remove-home nombre_usuario`, o bloquéalas con `sudo usermod -L -e 1 nombre_usuario` si necesitas conservar sus archivos. ## Paso 4: Privilegios de sudo Comprueba quién pertenece a los grupos con acceso de administración (`sudo` en Ubuntu y Debian, `wheel` en Rocky): ```bash getent group sudo ``` ```output sudo:x:27:your_user ``` Busca reglas que permitan `sudo` sin contraseña, que convierten cualquier sesión robada en root inmediato: ```bash sudo grep -rn 'NOPASSWD' /etc/sudoers /etc/sudoers.d/ ``` **Esperado:** ninguna regla o solo reglas justificadas para comandos concretos (no `ALL`). Edita siempre con `sudo visudo` o `sudo visudo -f /etc/sudoers.d/archivo` para que se valide la sintaxis. ## Paso 5: Configuración de SSH No revises solo `/etc/ssh/sshd_config`: en Ubuntu 24.04 los archivos de `/etc/ssh/sshd_config.d/` (por ejemplo `50-cloud-init.conf`) pueden cambiar los valores. `sshd -T` muestra la configuración efectiva: ```bash sudo sshd -T | grep -Ei '^(permitrootlogin|passwordauthentication|kbdinteractiveauthentication|pubkeyauthentication|maxauthtries|x11forwarding|permitemptypasswords) ' ``` Valores recomendados: | Parámetro | Valor recomendado | |---|---| | `permitrootlogin` | `no` (o `prohibit-password` si necesitas root con clave) | | `passwordauthentication` | `no` | | `kbdinteractiveauthentication` | `no` (salvo que uses 2FA) | | `pubkeyauthentication` | `yes` | | `maxauthtries` | `3` o `4` | | `x11forwarding` | `no` | | `permitemptypasswords` | `no` | Revisa también qué claves públicas pueden entrar en cada cuenta, incluida root: ```bash sudo ssh-keygen -lf /root/.ssh/authorized_keys ssh-keygen -lf ~/.ssh/authorized_keys ``` Cada línea muestra la huella y el comentario de una clave. Elimina las que no reconozcas. **Corrección:** pon los valores en `/etc/ssh/sshd_config.d/10-hardening.conf` (el primer valor leído es el que se aplica, y `10-` se lee antes que `50-cloud-init.conf`), valida con `sudo sshd -t` y aplica con `sudo systemctl reload ssh`. La guía de gestión de claves SSH de esta sección lo explica en detalle. ## Paso 6: Puertos abiertos y servicios Lista los puertos en escucha y el proceso que los abre: ```bash sudo ss -tulpn ``` ```output Netid State Local Address:Port Peer Address:Port Process tcp LISTEN 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=812,fd=3)) tcp LISTEN 127.0.0.1:3306 0.0.0.0:* users:(("mysqld",pid=945,fd=21)) tcp LISTEN 0.0.0.0:443 0.0.0.0:* users:(("nginx",pid=1020,fd=6)) ``` **Esperado:** los servicios internos (bases de datos, Redis, paneles de administración) escuchan en `127.0.0.1` o en una IP privada, nunca en `0.0.0.0` sin firewall. Revisa los servicios en ejecución y deshabilita los que no uses: ```bash systemctl list-units --type=service --state=running --no-pager ``` **Corrección:** `sudo systemctl disable --now nombre_servicio`. ## Paso 7: Firewall Confirma que el firewall está activo, que la política por defecto de entrada es denegar y que solo están abiertos los puertos que viste en el paso anterior: ```bash sudo ufw status verbose ``` ```output Status: active Default: deny (incoming), allow (outgoing), disabled (routed) To Action From -- ------ ---- 22/tcp ALLOW IN Anywhere 443/tcp ALLOW IN Anywhere ``` **Corrección:** si UFW está inactivo, permite SSH antes de activarlo: ```bash sudo ufw allow OpenSSH sudo ufw enable ``` En Rocky Linux 9 usa `sudo firewall-cmd --list-all`. > Nota: los puertos publicados por Docker con `-p` se saltan las reglas de UFW. Si usas Docker, revisa también `sudo docker ps --format '{{.Names}} {{.Ports}}'`. ## Paso 8: Parámetros del kernel Algunos parámetros de red y de memoria reducen la superficie de ataque. Consulta sus valores actuales: ```bash sysctl net.ipv4.ip_forward net.ipv4.tcp_syncookies net.ipv4.conf.all.accept_redirects net.ipv4.conf.all.send_redirects net.ipv4.conf.all.accept_source_route net.ipv4.conf.all.log_martians kernel.randomize_va_space kernel.kptr_restrict kernel.dmesg_restrict fs.suid_dumpable ``` | Parámetro | Valor recomendado | Motivo | |---|---|---| | `net.ipv4.ip_forward` | `0` | El servidor no enruta tráfico (`1` si usas Docker, Kubernetes o VPN). | | `net.ipv4.tcp_syncookies` | `1` | Mitiga inundaciones SYN. | | `net.ipv4.conf.all.accept_redirects` | `0` | Ignora redirecciones ICMP. | | `net.ipv4.conf.all.send_redirects` | `0` | No envía redirecciones. | | `net.ipv4.conf.all.accept_source_route` | `0` | Rechaza paquetes con ruta de origen. | | `net.ipv4.conf.all.log_martians` | `1` | Registra paquetes con direcciones imposibles. | | `kernel.randomize_va_space` | `2` | ASLR completo. | | `kernel.kptr_restrict` | `1` o `2` | Oculta direcciones del kernel. | | `kernel.dmesg_restrict` | `1` | Solo root lee `dmesg`. | | `fs.suid_dumpable` | `0` | Sin volcados de memoria de binarios SUID. | **Corrección:** crea un archivo con los valores que no coincidan: ```bash sudo nano /etc/sysctl.d/99-hardening.conf ``` ```ini net.ipv4.conf.all.accept_redirects = 0 net.ipv4.conf.default.accept_redirects = 0 net.ipv6.conf.all.accept_redirects = 0 net.ipv4.conf.all.send_redirects = 0 net.ipv4.conf.all.accept_source_route = 0 net.ipv4.conf.all.log_martians = 1 fs.suid_dumpable = 0 ``` Aplícalo y vuelve a consultar los valores: ```bash sudo sysctl --system ``` ## Paso 9: Permisos de archivos Los archivos de credenciales deben tener permisos estrictos: ```bash stat -c '%a %U:%G %n' /etc/passwd /etc/shadow /etc/group /etc/gshadow /etc/ssh/sshd_config ``` ```output 644 root:root /etc/passwd 640 root:shadow /etc/shadow 644 root:root /etc/group 640 root:shadow /etc/gshadow 644 root:root /etc/ssh/sshd_config ``` Busca archivos que cualquier usuario puede modificar fuera de los directorios temporales: ```bash sudo find / -xdev -type f -perm -0002 -not -path '/proc/*' 2>/dev/null ``` **Esperado:** ninguna salida. **Corrección:** `sudo chmod o-w ruta/al/archivo`. Lista los binarios SUID y SGID. Guarda la lista para comparar en la siguiente auditoría: un binario SUID nuevo que no viene de un paquete es una señal de alarma. ```bash sudo find / -xdev -type f \( -perm -4000 -o -perm -2000 \) 2>/dev/null | sort | tee "$AUDIT_DIR/suid.txt" ``` Comprueba además que ningún archivo instalado por paquetes ha sido modificado. `debsums -s` solo muestra los archivos cuya suma no coincide: ```bash sudo apt install debsums sudo debsums -s ``` **Esperado:** ninguna salida. Un binario de `/usr/bin` modificado requiere investigación inmediata. ## Paso 10: Tareas programadas Los atacantes suelen dejar persistencia en cron o en temporizadores de systemd. Revisa ambos: ```bash ls -la /etc/cron.d /etc/cron.daily /etc/cron.hourly /etc/cron.weekly sudo ls -la /var/spool/cron/crontabs/ systemctl list-timers --all --no-pager ``` Revisa el contenido de cualquier crontab de usuario que no esperes con `sudo crontab -l -u nombre_usuario`. ## Paso 11: Registros de autenticación Cuenta los intentos fallidos de SSH de las últimas 24 horas y las IP que más lo intentan: ```bash sudo journalctl -u ssh --since "24 hours ago" --no-pager | grep -c 'Failed password' sudo journalctl -u ssh --since "24 hours ago" --no-pager | grep -oP 'Failed password .* from \K[0-9.]+' | sort | uniq -c | sort -rn | head ``` Revisa los inicios de sesión aceptados y el método usado: ```bash sudo journalctl -u ssh --since "7 days ago" --no-pager | grep 'Accepted' ``` **Esperado:** solo `Accepted publickey` desde IP que reconozcas. Un `Accepted password` cuando la autenticación por contraseña debería estar desactivada indica un problema de configuración. Comprueba que los registros se conservan tras reiniciar: ```bash journalctl --list-boots --no-pager | tail -n 3 ``` Si solo aparece el arranque actual, el diario no es persistente. En Ubuntu 24.04 basta con crear el directorio y reiniciar el servicio: ```bash sudo mkdir -p /var/log/journal sudo systemctl restart systemd-journald ``` ## Paso 12: Cerrar la auditoría Comprime las evidencias para archivarlas fuera del servidor: ```bash tar -czf "$AUDIT_DIR.tar.gz" -C "$HOME" "$(basename "$AUDIT_DIR")" ls -lh "$AUDIT_DIR.tar.gz" ``` Anota para cada punto si pasa, falla o se acepta el riesgo, y quién es responsable de corregirlo. En la siguiente auditoría, compara por ejemplo la lista SUID con `diff`. ## Conclusión Has revisado actualizaciones, cuentas, sudo, SSH, puertos, firewall, parámetros del kernel, permisos, tareas programadas y registros de autenticación, y has guardado las evidencias en un archivo fechado. Repite esta lista al menos cada trimestre y siempre después de un cambio importante en el servidor. Como siguientes pasos puedes: - Automatizar gran parte de estas comprobaciones con Lynis y comparar su índice de endurecimiento en el tiempo. - Desactivar por completo el acceso por contraseña con claves SSH y añadir autenticación de dos factores. - Instalar Fail2ban para bloquear automáticamente las IP con muchos intentos fallidos.