Las tres lecciones anteriores han levantado un perímetro: red controlada, SSH con claves y sin root, cortafuegos con política de lista blanca y fail2ban bloqueando a quien insiste. Todo eso es prevención, y la prevención tiene una propiedad incómoda: cuando falla, no avisa. Un atacante que entra con una credencial legítima no dispara ninguna regla; su conexión aparece como established, igual que la tuya. Esta lección cambia la pregunta de «¿cómo impido que entren?» a «¿cómo me entero de que ya han entrado?», y responde con herramientas concretas: integridad de ficheros con AIDE, auditoría del kernel con auditd, lectura sistemática de los registros, auditoría de configuración con Lynis y un procedimiento de respuesta a incidentes que puedas seguir a las tres de la madrugada sin improvisar.
Advertencia legal previa. Todo lo que hay aquí es defensivo y se aplica sobre srv-tramontana, que es tu propia máquina de laboratorio. Escanear, sondear o intentar acceder a sistemas ajenos sin autorización escrita es un delito, con independencia de la intención. Y en el terreno del cumplimiento: detectar intrusiones en un sistema que trata datos personales de huéspedes activa obligaciones legales concretas —notificación de brechas en 72 horas bajo el RGPD— y monitorizar la actividad de personas trabajadoras tiene límites que no decide el administrador. Ambas cosas se tratan al final de la lección.
Contenido
- Por qué la detección es un control distinto de la prevención
- Taxonomía: NIDS, HIDS, firmas, anomalías, IDS e IPS
- Integridad de ficheros con AIDE
- Automatizar AIDE con un timer de systemd
- Detección de rootkits: rkhunter y chkrootkit
- auditd: la auditoría del kernel
- Análisis de registros para detección
- NIDS: panorámica honesta de Suricata
- Auditoría de configuración con Lynis
- Respuesta a incidentes y obligaciones legales
Por qué la detección es un control distinto de la prevención
Un control preventivo intenta que algo no ocurra. Un control detectivo asume que puede ocurrir y se ocupa de que no pase desapercibido. No son alternativas: son capas distintas, y una organización que solo tiene la primera se enteraría de un compromiso por una llamada de un tercero, semanas después.
Los cuatro caminos por los que la prevención de srv-tramontana puede fallar, hoy mismo:
| Vía de fallo | Por qué el firewall no ayuda |
|---|---|
| Vulnerabilidad sin parche (0-day o ventana de exposición) | El tráfico llega por un puerto legítimamente abierto |
| Credencial filtrada | La autenticación es correcta desde el punto de vista del sistema |
| Error de configuración propio | La regla que abriste «solo un momento» sigue abierta |
| Abuso de acceso legítimo | Quien actúa ya está dentro y tiene permiso para estar |
La mentalidad que hay que adoptar se llama presunción de compromiso: no «¿estoy seguro?», sino «si estuviera comprometido, ¿cómo lo sabría?». Y esa pregunta se descompone en tres, que son las que estructuran toda la lección:
- ¿Qué ha cambiado? Un atacante que quiere persistir tiene que modificar algo: un binario, un fichero de configuración, una clave autorizada, una unidad de systemd. → integridad de ficheros.
- ¿Quién ha entrado? Toda sesión deja rastro en los registros de autenticación. → análisis de registros.
- ¿Qué ha hecho? Qué ficheros se han leído o escrito, qué procesos se han lanzado. → auditoría del kernel.
Taxonomía: NIDS, HIDS, firmas, anomalías, IDS e IPS
El vocabulario del área es confuso porque mezcla tres ejes independientes. Conviene separarlos:
| Eje | Opciones | Qué distingue |
|---|---|---|
| Dónde observa | NIDS (red) / HIDS (host) | El NIDS mira paquetes en tránsito; el HIDS mira el estado y la actividad de una máquina |
| Cómo decide | Firmas / Anomalías | Las firmas reconocen lo malo conocido; las anomalías detectan desviaciones de lo normal |
| Qué hace al detectar | IDS (avisa) / IPS (bloquea) | El IPS actúa, con el riesgo de bloquear tráfico legítimo |
Las consecuencias prácticas de cada elección:
- Firmas: precisión alta, pocos falsos positivos, y ceguera total ante lo que no está en el catálogo. Necesitan actualización constante.
- Anomalías: pueden detectar lo desconocido, a cambio de falsos positivos y de necesitar un periodo de aprendizaje de lo que es «normal». Y «normal» cambia: la línea base que estableciste en 05-07 caduca.
- IPS: cuando se equivoca, provoca una interrupción del servicio.
fail2ban, que ya tienes funcionando, es exactamente un IPS de propósito estrecho — y ya viste en 06-03 el riesgo de que te bloquee a ti.
Para un servidor único como srv-tramontana, la inversión que más rinde es un HIDS de integridad más auditoría del kernel. El NIDS gana valor cuando hay una red con varios equipos y un punto por el que pasa todo el tráfico; volveremos sobre ello.
Integridad de ficheros con AIDE
La integridad de ficheros es la señal más fiable que tiene un servidor, por una razón estructural: un atacante que quiere persistir tiene que escribir en el disco. Puede borrar entradas de registro, puede falsear la salida de ps con un rootkit, pero el binario modificado o la clave añadida siguen ahí, y su huella criptográfica no coincide con la que tenías.
AIDE (Advanced Intrusion Detection Environment) construye una base de datos con los atributos y las sumas de comprobación de los ficheros que le indiques, y después compara el estado actual contra ella.
Las reglas de selección
La configuración vive en /etc/aide/aide.conf y en los fragmentos de /etc/aide/aide.conf.d/. Lo esencial son los grupos de atributos, que definen qué se comprueba de cada fichero:
| Atributo | Comprueba |
|---|---|
p |
Permisos |
i |
Número de inodo |
n |
Número de enlaces |
u / g |
Propietario / grupo |
s |
Tamaño |
m |
Tiempo de modificación (mtime) |
c |
Tiempo de cambio de inodo (ctime) |
md5 / sha256 |
Suma de comprobación del contenido |
Se combinan con + en definiciones reutilizables, y luego se aplican a rutas con ruta grupo para vigilar y !ruta para excluir:
# /etc/aide/aide.conf.d/99_tramontana
# Grupo completo: todo lo que se puede comprobar de un fichero
TramoTodo = p+i+n+u+g+s+m+c+md5+sha256
# Grupo laxo: para ficheros que cambian de contenido legítimamente
# pero cuyos permisos y propiedad NO deben cambiar nunca
TramoPermisos = p+u+g
# Configuracion y binarios: cualquier cambio es sospechoso
/etc/tramontana$ TramoTodo
/opt/tramontana/releases$ TramoTodo
/home/operador/scripts$ TramoTodo
/home/operador/bin$ TramoTodo
# Los logs crecen constantemente: vigila el continente, no el contenido
/var/log/tramontana$ TramoPermisos
!/var/log/tramontana/.*\.log$
!/var/log/tramontana/.*\.gz$
# Las copias cambian cada noche; solo interesan permisos y propiedad
/srv/tramontana/backups$ TramoPermisos
!/srv/tramontana/backups/.*Fíjate en el criterio: el nivel de vigilancia se ajusta a lo que se espera que cambie. Vigilar el contenido de acceso.log con sha256 produciría una alerta cada minuto y en dos días habrías dejado de leer los informes — que es la forma más común de que un sistema de detección deje de servir para nada.
Inicializar la base de datos, y dónde guardarla
$ sudo aideinit
Running aide --init...
Start timestamp: 2026-08-18 11:04:22 +0200 (AIDE 0.18.6)
AIDE initialized database at /var/lib/aide/aide.db.new
Number of entries: 231847
$ sudo mv /var/lib/aide/aide.db.new /var/lib/aide/aide.db
$ sudo chmod 600 /var/lib/aide/aide.dbY ahora el punto que decide si todo esto sirve de algo o es teatro:
Una base de datos de integridad que vive en el servidor vigilado no vale nada. Un atacante con privilegios de root modifica el binario, regenera la base de datos, y
aide --checkte dirá que todo está en orden. La base de datos —y, si te lo puedes permitir, el propio binario deaide— tiene que estar fuera de alcance: en un medio de solo lectura, o en otra máquina.
Como el runbook de recuperación que ya guardas fuera del servidor (05-08), la copia de referencia sale de la máquina:
$ sudo sha256sum /var/lib/aide/aide.db | sudo tee /var/lib/aide/aide.db.sha256
c4f1...e88a /var/lib/aide/aide.db
$ scp -3 operador@srv-tramontana:/var/lib/aide/aide.db.sha256 \
alumno@portatil-alumno:~/tramontana-referencia/Guardando al menos la suma de la base de datos fuera del servidor puedes detectar que la propia base de datos ha sido manipulada, que es el ataque contra el que hay que protegerse.
Interpretar un informe de cambios
$ sudo aide --check
Start timestamp: 2026-08-18 11:31:07 +0200 (AIDE 0.18.6)
AIDE found differences between database and filesystem!!
Summary:
Total number of entries: 231847
Added entries: 1
Removed entries: 0
Changed entries: 2
---------------------------------------------------
Added entries:
---------------------------------------------------
f++++++++++++++++: /home/operador/.ssh/authorized_keys2
---------------------------------------------------
Changed entries:
---------------------------------------------------
f ... . C... : /usr/bin/openssl
f ... . C... : /usr/lib/x86_64-linux-gnu/libssl.so.3La notación es densa pero mecánica: la primera letra es el tipo (f fichero, d directorio, l enlace), y las posiciones siguientes indican qué atributo cambió (C contenido, p permisos, u propietario, s tamaño, m mtime). Un + en la columna significa que se añadió.
Y aquí está la habilidad de verdad, que no es leer el informe sino clasificarlo:
-
Los dos ficheros cambiados son
opensslylibssl. Tienes una explicación documentada: el 18/08 a las 06:12unattended-upgradesaplicó la corrección de un CVE de TLS. Es un cambio legítimo, y se comprueba de forma independiente:$ grep -E 'openssl|libssl' /var/log/apt/history.log | tail -2 Upgrade: libssl3t64:amd64 (3.0.13-0ubuntu3.4, 3.0.13-0ubuntu3.5), openssl:amd64 (3.0.13-0ubuntu3.4, 3.0.13-0ubuntu3.5) $ sudo debsums -c openssl # sin salida: todos los ficheros del paquete coinciden con el manifiesto de Debiandebsumses la segunda opinión: verifica los ficheros instalados contra las sumas del propio paquete. Coinciden, así que el binario es el que Ubuntu publicó. -
El fichero añadido es otra cosa.
authorized_keys2es un nombre obsoleto que OpenSSH ya no lee por defecto, pero que en configuraciones antiguas sí, y nadie tenía motivo para crearlo. Esto no tiene explicación documentada, y es exactamente la forma de un mecanismo de persistencia. Aquí no se borra el fichero: se activa el procedimiento de respuesta a incidentes del final de la lección.
Tras validar los cambios legítimos, la base de datos se actualiza para que el próximo informe vuelva a estar limpio:
Existen alternativas: Tripwire es el ancestro de AIDE y tiene un modelo de firma criptográfica de su propia base de datos algo más robusto, a cambio de bastante más complejidad. debsums ya lo has visto y cubre solo ficheros de paquetes. Para un servidor único, AIDE es el equilibrio correcto.
Automatizar AIDE con un timer de systemd
Una comprobación que hay que recordar hacer no se hace. Con lo aprendido en 05-05, el patrón es directo, y respeta el principio de silencio si todo va bien:
$ sudo tee /usr/local/sbin/aide-comprobar >/dev/null <<'EOF'
#!/usr/bin/env bash
set -euo pipefail
readonly ETIQUETA_LOG="aide-tramontana"
salida="$(mktemp)"; trap 'rm -f "$salida"' EXIT
if aide --check >"$salida" 2>&1; then
logger -t "$ETIQUETA_LOG" -p local0.info "integridad correcta, sin cambios"
exit 0
fi
# aide devuelve un codigo distinto de 0 cuando hay diferencias
logger -t "$ETIQUETA_LOG" -p local0.warning "AIDE detecto cambios: revisar informe"
mail -s "[srv-tramontana] AIDE detecto cambios" [email protected] <"$salida" \
|| logger -t "$ETIQUETA_LOG" -p local0.err "no se pudo enviar el aviso"
exit 1
EOF
$ sudo chmod 700 /usr/local/sbin/aide-comprobar# /etc/systemd/system/tramontana-integridad.service
[Unit]
Description=Comprobacion de integridad de ficheros con AIDE
Documentation=man:aide(1)
[Service]
Type=oneshot
ExecStart=/usr/local/sbin/aide-comprobar
Nice=19
IOSchedulingClass=idle# /etc/systemd/system/tramontana-integridad.timer
[Unit]
Description=Comprobacion diaria de integridad
[Timer]
OnCalendar=*-*-* 05:40:00
Persistent=true
RandomizedDelaySec=600
[Install]
WantedBy=timers.target$ sudo systemctl daemon-reload
$ sudo systemctl enable --now tramontana-integridad.timer
$ systemctl list-timers tramontana-integridad.timer --no-pager
NEXT LEFT LAST PASSED UNIT ACTIVATES
Tue 2026-08-19 05:44:12 CEST 18h left - - tramontana-integridad.timer tramontana-integridad.serviceLas 05:40 no son arbitrarias: la copia de seguridad termina antes de esa hora y la purga se ejecuta los lunes a las 05:10, así que la comprobación de integridad ve un sistema en reposo y no compite por la E/S — el mismo razonamiento que aplicaste en 05-07 cuando moviste la copia a las 02:30. Nice=19 e IOSchedulingClass=idle son la garantía adicional.
Detección de rootkits: rkhunter y chkrootkit
Un rootkit es software que se instala tras el compromiso para mantener el acceso y ocultar su presencia, típicamente sustituyendo binarios del sistema (ps, ls, netstat) o cargando un módulo del kernel que miente al espacio de usuario. Es la razón por la que la regla de oro del final de esta lección existe: si el sistema miente sobre su propio estado, ninguna herramienta que corra dentro de él es de fiar.
$ sudo apt install rkhunter chkrootkit
$ sudo rkhunter --propupd # linea base de propiedades de los binarios
$ sudo rkhunter --check --skip-keypress
[ Rootkit checks ]
Rootkits checked : 479
Possible rootkits: 0
[ Applications checks ]
Warning: The SSH configuration option 'PermitRootLogin' has not been set
to 'no'.
Warning: Package manager verification has failedY aquí llega el aprendizaje real de estas herramientas: los dos avisos son falsos positivos, y saber por qué lo son es el trabajo.
-
El primero es una limitación del parseo de
rkhunter: tú sí configurastePermitRootLogin noen 06-02, pero lo hiciste en un fichero de/etc/ssh/sshd_config.d/, que la herramienta no lee. Se verifica con la fuente autorizada,sshd -T, que muestra la configuración efectiva:$ sudo sshd -T | grep -i permitrootlogin permitrootlogin no -
El segundo se explica por la actualización de openssl: los binarios cambiaron después de que ejecutaras
--propupd. Tras validarlo condebsums, se regenera la base de propiedades.
chkrootkit cubre un terreno parecido con otras heurísticas y es habitual que marque interfaces en modo promiscuo o procesos ocultos que en realidad son artefactos de la virtualización. La conclusión operativa es que estas herramientas son complemento, no núcleo: se ejecutan periódicamente, sus avisos se investigan uno a uno, y jamás se automatiza una acción a partir de ellos.
auditd: la auditoría del kernel
AIDE responde a «¿qué ha cambiado?», pero no a «¿quién lo cambió, cuándo y con qué proceso?». Eso es auditd, el subsistema de auditoría del kernel de Linux: registra llamadas al sistema y accesos a ficheros en el momento en que ocurren, con el usuario real, el usuario efectivo, el PID y el comando.
Las reglas persistentes van en /etc/audit/rules.d/, y augenrules las compila al arrancar:
# /etc/audit/rules.d/50-tramontana.rules
# -w ruta -p permisos -k clave
# p: r lectura, w escritura, x ejecucion, a cambio de atributos
# k: etiqueta para buscar despues con ausearch -k
# Configuracion de la aplicacion: contiene credenciales
-w /etc/tramontana/app.conf -p wa -k tramontana_conf
-w /etc/tramontana/ -p wa -k tramontana_conf
# Identidades y privilegios
-w /etc/passwd -p wa -k identidades
-w /etc/shadow -p wa -k identidades
-w /etc/group -p wa -k identidades
-w /etc/sudoers -p wa -k privilegios
-w /etc/sudoers.d/ -p wa -k privilegios
# Claves SSH autorizadas: el mecanismo de persistencia mas comun
-w /home/operador/.ssh/ -p wa -k claves_ssh
-w /root/.ssh/ -p wa -k claves_ssh
# Scripts que se ejecutan con privilegios
-w /home/operador/scripts/ -p wa -k scripts_operador
-w /usr/local/sbin/ -p wa -k binarios_locales
# Llamadas al sistema: carga de modulos del kernel (senal clasica de rootkit)
-a always,exit -F arch=b64 -S init_module,finit_module,delete_module -k modulos_kernel
# Cambios de propiedad y permisos hechos por usuarios normales
-a always,exit -F arch=b64 -S chmod,fchmod,fchmodat -F auid>=1000 -F auid!=unset -k cambios_permisos$ sudo augenrules --load
$ sudo auditctl -l | head -4
-w /etc/tramontana/app.conf -p wa -k tramontana_conf
-w /etc/tramontana -p wa -k tramontana_conf
-w /etc/passwd -p wa -k identidades
-w /etc/shadow -p wa -k identidadesConsultar lo que auditd ha registrado
Recuerda que en 05-02 pusiste chattr +i en app.conf. Mira lo que apareció:
$ sudo ausearch -k tramontana_conf -ts today -i | tail -12
type=PROCTITLE msg=audit(18/08/26 09:47:31.882:1043) : proctitle=vim /etc/tramontana/app.conf
type=PATH msg=audit(18/08/26 09:47:31.882:1043) : item=0 name=/etc/tramontana/app.conf
inode=262149 dev=fd:00 mode=file,640 ouid=root ogid=tramontana
type=SYSCALL msg=audit(18/08/26 09:47:31.882:1043) : arch=x86_64 syscall=openat
success=no exit=EPERM(Operation not permitted) auid=luis uid=luis gid=luis
euid=luis comm=vim exe=/usr/bin/vim key=tramontana_confLéelo despacio, porque contiene un incidente completo: el usuario luis intentó abrir app.conf en escritura con vim, y la llamada openat falló con EPERM. El atributo inmutable hizo su trabajo. Y —esto es lo que aporta auditd sobre cualquier otro control— el intento quedó registrado con nombre, hora, PID y comando, aunque no llegara a producir ningún cambio que AIDE pudiera ver.
No es necesariamente malicioso: lo más probable es que Luis quisiera subir max_conexiones para resolver los db_timeout y no supiera del chattr. Pero es un dato que antes no tenías, y la conversación que provoca —canalizar los cambios de configuración por desplegar-seguro en vez de editar a mano en producción— es exactamente el valor de un control detectivo.
Los informes agregados salen con aureport:
$ sudo aureport --file --summary -ts this-week | head -6
File Summary Report
===========================
total file
===========================
7 /etc/tramontana/app.conf
3 /home/operador/.ssh/authorized_keysY esa segunda línea vuelve a apuntar a lo mismo que AIDE detectó. Dos controles independientes señalando el mismo sitio es una señal fuerte.
El coste de auditar de más
auditd no es gratis. Cada regla añade trabajo en el camino de las llamadas al sistema, y una regla amplia sobre una ruta con mucha actividad puede degradar el rendimiento de forma perceptible y llenar el disco.
| Regla | Efecto |
|---|---|
-w /etc/tramontana/ -p wa |
Coste despreciable: poca actividad |
-w /var/log/ -p wa |
Muy costosa: cada escritura de cada log genera un evento |
-a always,exit -S all |
Inutilizable en producción |
Vigila lo que importa, mide el volumen (du -sh /var/log/audit/) y controla la retención en /etc/audit/auditd.conf con max_log_file, num_logs y max_log_file_action. Y cuando la configuración esté cerrada, -e 2 al final de las reglas las hace inmutables hasta el próximo reinicio: ni root puede modificarlas, lo que impide que un atacante desactive la auditoría antes de actuar. El precio es que un cambio legítimo exige reiniciar.
Análisis de registros para detección
Tienes journald persistente desde 05-06 y sabes manejar journalctl. Lo que falta es saber qué buscar. Estas son las señales que un administrador revisa, con la consulta que las obtiene:
# 1. Autenticaciones fallidas agrupadas por origen
$ sudo lastb -F | awk '{print $3}' | sort | uniq -c | sort -rn | head -5
47 203.0.113.44
3 10.0.2.31
# 2. Sesiones SSH aceptadas: quien entro, desde donde y con que metodo
$ sudo journalctl -u ssh --since "7 days ago" | grep -E 'Accepted' \
| awk '{print $1, $2, $3, $9, $11, $7}' | tail -5
ago 18 08:12:04 operador 10.0.2.31 publickey
ago 18 09:41:57 luis 10.0.2.44 password
# 3. Accesos fuera del horario habitual (antes de las 07:00 o despues de las 21:00)
$ sudo journalctl -u ssh --since "30 days ago" -o short-iso | grep 'Accepted' \
| awk -F'T' '{split($2,h,":"); if (h[1] < 7 || h[1] > 21) print}'
# 4. Uso de sudo: que se ejecuto, quien y desde donde
$ sudo journalctl --since today | grep -E 'sudo:.*COMMAND' | tail -3
# 5. Cambios en identidades y privilegios
$ sudo journalctl --since "7 days ago" | grep -E 'useradd|usermod|groupadd|passwd\['Dos observaciones sobre estos resultados, que son las que convierten una consulta en una decisión:
- La línea 2 muestra que
luisentró conpassword. Pero en 06-02 configurastePasswordAuthentication no. Que esa autenticación tuviera éxito significa que hay una excepción en algúnMatchdesshd_config.d/, o que se aplicó a una interfaz que no revisaste. Es el asunto pendiente que dejó abierto 06-03, y ahora tiene evidencia: hay que resolverlo, no solo pedirle a Luis que use su clave. - Los 47 intentos desde
203.0.113.44ya están bloqueados porfail2ban, pero el recuento sigue siendo útil como línea base: si mañana son 4.700, o si aparecen desde un rango nuevo, el cambio de forma es la señal.
La técnica que estás aplicando es la misma del Módulo 3 —grep, awk, sort | uniq -c | sort -rn— sobre una fuente distinta. Y la razón por la que en 05-06 insististe en el journal persistente es esta: sin él, la consulta número 3 no tendría 30 días de historia que consultar.
Un aviso importante: los registros de la propia máquina son evidencia manipulable. Un atacante con root puede borrar entradas del journal. Por eso la centralización de registros que se mencionó en 05-06 no es un lujo organizativo: enviar los registros a otra máquina en el momento en que se generan es lo que impide que se borren a posteriori.
NIDS: panorámica honesta de Suricata
Suricata es el NIDS de referencia en software libre: inspecciona el tráfico de red, lo compara con un catálogo de firmas (el conjunto gratuito ET Open de Emerging Threats es el punto de partida habitual) y registra o bloquea las coincidencias.
Dónde se coloca determina lo que ve:
graph LR
I[Internet] --> R[Router / cortafuegos]
R -->|copia del trafico<br/>modo IDS| S[Suricata]
R --> SW[Red interna]
SW --> A[srv-tramontana]
SW --> B[portatil-luis]
S -.->|alertas| L[Registro central]
En modo IDS recibe una copia del tráfico y solo avisa. En modo IPS se sitúa en el camino del tráfico y puede descartar paquetes, con el riesgo asociado: si se equivoca o se cae, corta el servicio.
Y ahora la parte honesta, porque montar Suricata en srv-tramontana sería un error de criterio en este momento:
| Situación | Qué aporta un NIDS |
|---|---|
| Un servidor único, tráfico HTTPS cifrado de extremo a extremo | Muy poco: no puede inspeccionar lo que no puede descifrar |
| Varios equipos y un punto de paso del tráfico | Mucho: es el único control que ve la red completa |
| Necesidad de detectar movimiento lateral entre máquinas | Es la herramienta indicada |
En una infraestructura de una sola máquina, el esfuerzo invertido en AIDE y auditd rinde bastante más. Cuando Tramontana crezca a varios servidores —y en 07-07 verás cómo—, el NIDS pasará a la lista.
Auditoría de configuración con Lynis
Un eje distinto: en vez de detectar actividad, Lynis evalúa la configuración del sistema contra un catálogo de buenas prácticas y devuelve una puntuación con sugerencias.
$ sudo apt install lynis
$ sudo lynis audit system --quiet
...
Hardening index : 68 [############# ]
Tests performed : 267
Suggestions : 31
Warnings : 2Cómo leerlo, que es menos evidente de lo que parece:
- El índice de endurecimiento no es una nota académica ni tiene un valor «aprobado». Es una métrica de seguimiento: lo que importa es su tendencia y que no baje sin que sepas por qué. Un 68 en un servidor con propósito definido puede ser correcto; un 95 conseguido aplicando sugerencias sin entenderlas es peor.
- Las sugerencias no se aplican a ciegas. Lynis evalúa contra un perfil genérico y no conoce el propósito de tu máquina. Algunas de sus recomendaciones aquí serían activamente contraproducentes.
Un ejemplo real de cada categoría:
| Sugerencia de Lynis | Decisión razonada |
|---|---|
| Instalar un demonio de auditoría | Ya hecho: auditd está activo. El aviso es de una comprobación previa a instalarlo |
Configurar noexec en /tmp |
Se acepta, pero se verifica antes: hay instaladores que fallan (se hace en 06-06) |
| Instalar un antivirus (ClamAV) | Se descarta: en un servidor sin ficheros de terceros aporta poco y consume memoria que MemoryMax=512M no tiene de sobra |
| Deshabilitar el reenvío de IP | Se descarta: será necesario cuando se monte la VPN en 08-04 |
El resultado del ejercicio no es una puntuación alta, sino un informe con decisiones documentadas. Eso es lo que se entrega a Marta y lo que resiste una auditoría, mientras que «hemos aplicado todo lo que decía la herramienta» no resiste ninguna.
Lynis se ejecuta de forma recurrente —mensualmente, con su propio timer— y su índice se anota junto a la línea base de rendimiento de 05-07.
Respuesta a incidentes y obligaciones legales
Tienes una detección real: un authorized_keys2 que nadie creó. Lo que hagas en los próximos veinte minutos determina si conservas la información necesaria para entender qué pasó. Este es el procedimiento, y el orden importa:
-
No apagues la máquina. Apagar destruye toda la evidencia que vive en memoria: procesos, conexiones abiertas, ficheros borrados pero aún abiertos, claves en claro. Aísla en su lugar: corta el tráfico con el cortafuegos o desconecta la interfaz de red virtual desde el hipervisor, conservando el acceso por consola.
-
Anota la hora y el hallazgo por escrito, fuera del servidor. A partir de aquí, cada acción se registra con su hora. Esta bitácora es lo que después permite distinguir tus propias huellas de las del atacante.
-
Preserva la evidencia volátil antes de tocar nada, guardando la salida fuera de la máquina:
$ ss -tunap # conexiones y a que proceso pertenecen $ ps auxf # arbol de procesos completo $ sudo lsof -n # ficheros y sockets abiertos $ sudo ls -l /proc/*/exe 2>/dev/null | grep deleted # binarios borrados en ejecucion $ w; last -F | head -20 $ sudo cp -a /var/log /media/evidencia/ # y el journal: journalctl -o exportLa última consulta es especialmente valiosa: un proceso cuyo binario ya no existe en disco pero sigue ejecutándose es una señal muy fuerte.
-
Toma una instantánea del disco con la máquina aún encendida. En tu VM es una operación del hipervisor; en LVM, un snapshot como el de 05-04. Esa imagen es la copia sobre la que se investiga, para no alterar el original.
-
Determina el alcance: qué se accedió, desde cuándo, y si hay datos personales implicados.
auditdy el journal son las fuentes. La pregunta que hay que poder responder es sireservas.csv—con nombres de huéspedes— fue leído o exfiltrado. -
Comunica. Marta primero, y en cuanto haya sospecha de acceso a datos personales, el responsable de seguridad y el de protección de datos. Esto no es una decisión técnica.
-
Recupera reinstalando.
La cadena de custodia es el concepto que sostiene los pasos 2 a 4: un registro de quién tuvo acceso a cada evidencia, cuándo y qué hizo con ella, junto a las sumas de comprobación que demuestran que no se ha alterado. Sin ella, la evidencia sirve para entender lo ocurrido pero no para sustentar una reclamación o una denuncia.
La regla que nadie quiere oír
Un servidor comprometido se reinstala, no se limpia.
No es pesimismo profesional, es aritmética. Para «limpiar» tendrías que demostrar que has encontrado todos los mecanismos de persistencia: cada binario sustituido, cada unidad de systemd añadida, cada línea de crontab, cada clave autorizada, cada módulo del kernel, cada biblioteca precargada por LD_PRELOAD. Un atacante competente deja varios y algunos difíciles de encontrar. Y las herramientas con las que buscarías corren sobre el sistema que quizá te esté mintiendo.
Por eso todo el trabajo del Módulo 5 tiene un valor que no era evidente entonces:
- La copia con
restic(05-08) permite restaurar los datos, no el sistema comprometido. - El runbook guardado fuera del servidor contiene el procedimiento de reconstrucción.
- La configuración documentada —netplan,
sshd_config, reglas deufw, unidades de systemd,app.conf— permite reconstruir la máquina. - El RTO de 8 horas que aprobó Marta es exactamente el presupuesto de tiempo de esta operación.
Reinstalar es la opción rápida y segura, no la drástica. Y la reconstrucción por código que verás en 07-06 con Ansible convierte estas 8 horas en bastante menos.
Obligaciones legales y de cumplimiento
- Notificación de brechas (RGPD, art. 33). Si hay una violación de seguridad que afecta a datos personales, la organización debe notificarla a la autoridad de control en un máximo de 72 horas desde que tiene conocimiento de ella, y en algunos casos también a las personas afectadas.
srv-tramontanaguarda nombres de huéspedes enreservas.csv: el supuesto es plenamente aplicable. El plazo empieza a contar desde el conocimiento, no desde que acabas la investigación, así que la comunicación del paso 6 no puede esperar. - Límites a la monitorización de personas. Las reglas de
auditdque vigilan qué haceluisregistran actividad de una persona trabajadora identificable. Eso está sujeto a la normativa laboral y de protección de datos: exige finalidad legítima, proporcionalidad, y —de forma determinante— información previa a las personas afectadas. Auditar en secreto la actividad del personal no es una decisión que corresponda al administrador. - En un entorno real, tanto el diseño de la detección como cualquier decisión sobre una brecha deben revisarlos el responsable de seguridad y el de protección de datos. Este curso te da las herramientas técnicas; no sustituye ese criterio ni una auditoría formal.
El informe para Marta
Siguiendo la convención del curso —decir qué protege y qué no protege cada medida—, el entregable de esta lección:
Se corrige:
- El
authorized_keys2no explicado: se activa el procedimiento de respuesta a incidentes; hasta cerrarlo, se asume compromiso. - La autenticación por contraseña de
luis, que funciona pese a estar deshabilitada: hay una excepción en la configuración de SSH que hay que localizar y eliminar. - Los cambios de configuración hechos editando en producción: se canalizan por
desplegar-seguro, yauditdverifica que se cumple.
Se asume, con motivo:
- Sin NIDS, no hay visibilidad del tráfico de red. Se acepta mientras haya un único servidor; se revisa cuando haya varios.
- Sin registros centralizados, un atacante con root puede borrar el journal. Se acepta con el coste actual; es la primera inversión cuando el presupuesto lo permita.
Qué protege esto y qué no. AIDE y auditd detectan cambios y accesos, y por tanto acortan el tiempo hasta detectar un compromiso, que es la variable que determina el daño. No lo impiden. Y ninguno de los dos protege contra un atacante que llegue con credenciales válidas y no modifique nada — para eso hace falta que los secretos dejen de estar donde están.
Errores Comunes y Consejos
- Guardar la base de datos de AIDE solo en el servidor vigilado. Es el error que anula toda la medida. La base de datos, o al menos su suma de comprobación, tiene que estar fuera.
- Vigilar ficheros que cambian legítimamente con
sha256. Produce un informe con cambios todos los días, y en una semana nadie los lee. La saturación de alertas es la principal causa de muerte de un sistema de detección: si suena siempre, no suena nunca. - Actualizar la base de datos de AIDE sin investigar el cambio.
aide --updatedespués de cada informe convierte la herramienta en un registro de historia sin capacidad de alertar. Primero se clasifica cada cambio, luego se actualiza. - Auditar demasiado con
auditd. Una regla amplia sobre/var/logo/procdegrada el rendimiento y llena el disco. Empieza estrecho y amplía con criterio, midiendodu -sh /var/log/audit/. - Confiar en un único control. AIDE detectó el fichero añadido y
aureportlo confirmó de forma independiente. Dos fuentes que coinciden dan una confianza que ninguna da por separado. - Apagar la máquina al detectar un compromiso. Es el reflejo natural y destruye la evidencia de memoria. Aísla la red, conserva la máquina encendida.
- Tratar los falsos positivos como ruido a silenciar. Cada aviso de
rkhuntero Lynis que descartas debe quedar documentado con su motivo. Silenciar sin registrar es cómo se pierde el único aviso que era real. - Consejo de método. Guarda las consultas de detección en un script (
revision_seguridad.sh) que uselib/comunes.shy se ejecute por timer. Una comprobación que depende de tu memoria no es un control.
Ejercicios
Ejercicio 1
Diseña la configuración de AIDE para vigilar /home/operador/bin/, el directorio que contiene el envoltorio desplegar-seguro con permisos 0755 de root. Justifica el grupo de atributos que eliges y explica qué ataque concreto detectaría tu regla que no detectaría vigilar solo la suma de comprobación del contenido.
Ejercicio 2
Escribe la regla de auditd que registre cualquier ejecución del binario /home/operador/bin/desplegar-seguro, y la consulta de ausearch que muestre quién lo ha ejecutado hoy. Explica qué información aporta esto que no aporte ya el despliegue.log que escribe desplegar.sh.
Ejercicio 3
aide --check informa de un cambio en /etc/tramontana/app.conf: el atributo de contenido y el mtime han cambiado, y los permisos han pasado de 640 a 644. Describe el procedimiento completo de investigación, indicando qué fuentes consultarías y en qué orden, y qué decisión tomarías en cada uno de los dos desenlaces posibles.
Soluciones
Solución 1
# /etc/aide/aide.conf.d/99_tramontana (adicion)
TramoTodo = p+i+n+u+g+s+m+c+md5+sha256
/home/operador/bin$ TramoTodoEl grupo completo, y no solo sha256, por tres razones concretas, cada una asociada a un ataque distinto:
p(permisos).desplegar-seguroestá en la regla desudoerscomo comando permitido aoperador. Si un atacante consigue cambiarle los permisos a0777, cualquier usuario del sistema puede reescribir su contenido y, a través de la regla desudo, ejecutar código arbitrario con privilegios. El contenido no habría cambiado todavía, así que una regla que solo compruebesha256no vería nada. Este es el ataque que la respuesta debe identificar.uyg(propietario y grupo). El fichero debe serroot:root. Si pasa a ser propiedad deluiso del grupotramontana, su dueño puede modificarlo sin necesidad de privilegios, y de nuevo el contenido aún coincide.i(inodo) yn(enlaces). Un cambio de inodo con el mismo contenido significa que el fichero fue sustituido, no editado —por ejemplo, reemplazado por un enlace simbólico a otro binario—. Un contador de enlaces que sube de 1 a 2 indica que alguien creó un enlace duro al fichero, lo que permite conservar acceso al binario original aunque se reemplace el que está en/home/operador/bin/.
En resumen: la suma de comprobación detecta la modificación del binario, pero los atributos detectan la preparación para modificarlo, que ocurre antes y es el momento en el que la detección todavía sirve para prevenir el daño.
Solución 2
# /etc/audit/rules.d/50-tramontana.rules (adicion)
-a always,exit -F arch=b64 -F path=/home/operador/bin/desplegar-seguro \
-F perm=x -k despliegue_ejecucionLectura de la regla: -a always,exit registra siempre, al salir de la llamada; -F arch=b64 la limita a binarios de 64 bits (necesario porque el filtro por path con perm opera sobre la arquitectura); -F path= es el fichero concreto; -F perm=x restringe el registro a las ejecuciones y no a las lecturas o escrituras; -k etiqueta el evento.
Qué aporta frente a despliegue.log, que es la parte de fondo del ejercicio. desplegar.sh escribe en su registro lo que él mismo decide escribir, y solo si llega a ejecutarse:
| Situación | despliegue.log |
auditd |
|---|---|---|
| Despliegue normal | Lo registra | Lo registra |
| El script falla antes de abrir su registro | No hay rastro | Registra la ejecución |
| El script es sustituido por otro binario | Registra lo que el atacante quiera | Registra la ejecución real, con uid, auid y PID |
Alguien borra despliegue.log |
Desaparece | El registro está en /var/log/audit/, con reglas -e 2 inmutables |
La diferencia esencial es de confianza: despliegue.log es el testimonio de la aplicación sobre sí misma; el registro de auditd lo genera el kernel, por debajo del proceso, y no depende de la buena fe ni del correcto funcionamiento de lo auditado. Además auditd conserva el auid —el usuario que inició la sesión original—, que sobrevive a los cambios de identidad por sudo y responde a «¿quién fue realmente?» cuando uid ya es root.
Solución 3
El cambio de permisos de 640 a 644 es lo relevante: significa que cualquier usuario del sistema puede ahora leer el fichero, y ese fichero contiene db_password en claro. Se trata igual que una credencial expuesta, exactamente como el incidente de la copia con permisos 644.
Procedimiento, en este orden y por este motivo:
-
auditdprimero, porque responde a quién y cuándo, y es la fuente que un atacante tendría más difícil manipular:$ sudo ausearch -k tramontana_conf -ts today -iBusca el evento
chmod/fchmodatcon éxito y anotaauid,uid,comm,exey la hora exacta. -
Correlaciona con las sesiones, para saber desde dónde llegó ese usuario:
$ sudo journalctl -u ssh --since today | grep -E 'Accepted|Disconnected' $ sudo journalctl --since today | grep -E 'sudo:.*COMMAND' -
Comprueba si hay una explicación legítima: ¿hubo un despliegue en esa ventana? ¿Coincide con
apt?$ tail -20 /var/log/tramontana/despliegue.log $ grep -E "$(date +%Y-%m-%d)" /var/log/apt/history.log -
Evalúa la exposición, que es la pregunta que determina la gravedad: durante cuánto tiempo el fichero estuvo legible, y si alguien lo leyó. El
mtimecambiado indica además que el contenido también se modificó, así que hay que ver qué se cambió comparando con la última copia:$ sudo restic dump latest /etc/tramontana/app.conf | diff -u - /etc/tramontana/app.confY buscar lecturas del fichero en el intervalo:
$ sudo ausearch -k tramontana_conf -ts recent -i | grep -E 'syscall=openat.*success=yes'
Desenlace A — cambio legítimo: el auid es operador, la hora coincide con un despliegue registrado, y el diff muestra solo max_conexiones ajustado. Aun así hay dos acciones obligatorias, porque el resultado es incorrecto aunque la intención fuera buena: restaurar chmod 640 y chown root:tramontana, y corregir la causa raíz —el procedimiento o el script que deja el fichero en 644— para que no se repita. Se documenta y se actualiza la base de datos de AIDE. La lección de fondo: un cambio autorizado con un resultado insegura sigue siendo un hallazgo.
Desenlace B — sin explicación, o auid inesperado, o diff con cambios que nadie reconoce: se trata como compromiso confirmado. Se aplica el procedimiento de respuesta a incidentes completo (aislar, no apagar, preservar evidencia volátil, instantánea del disco, determinar alcance, comunicar). Y con independencia de cómo acabe la investigación, la db_password se considera comprometida y se rota de inmediato, porque estuvo legible para todo el sistema durante un tiempo que no puedes acotar con certeza. Al haber datos personales implicados, la comunicación al responsable de protección de datos entra dentro del plazo de 72 horas.
En ambos desenlaces se llega a la misma conclusión estructural: mientras la contraseña esté en claro en un fichero de configuración, cualquier fallo de permisos es una fuga. Ese problema no se resuelve vigilando mejor el fichero.
Conclusión
Has pasado de un servidor que se defiende a un servidor que además se observa. AIDE vigila la integridad de la configuración, los binarios y los scripts, con su base de datos protegida fuera de la máquina y una comprobación diaria por timer que solo habla cuando hay algo que decir. auditd registra en el kernel quién toca app.conf, quién modifica identidades y privilegios, y quién intenta cargar un módulo — y ya te ha dado un hallazgo real que ningún otro control veía: el intento fallido de Luis contra un fichero inmutable. Sabes leer los registros buscando señales concretas en lugar de mirarlos por encima, sabes que rkhunter y Lynis se interpretan y no se obedecen, y tienes un procedimiento de respuesta a incidentes que no depende de la improvisación, con su regla incómoda incluida: un servidor comprometido se reinstala, no se limpia.
Y la detección ha hecho justamente lo que se le pide: te ha dicho dónde está el problema de fondo. Los tres hallazgos de esta lección apuntan al mismo sitio. El authorized_keys2 sin explicar, la sesión de luis autenticada por contraseña, y sobre todo la conclusión del último ejercicio: mientras la db_password viva en claro dentro de app.conf, cualquier fallo de permisos —tuyo, de un script, de un atacante— es una fuga de credenciales, y ninguna cantidad de vigilancia sobre ese fichero lo cambia. A eso se añade una segunda pieza que arrastras desde el Módulo 5: el tráfico de reservas, con los nombres de los huéspedes que tanto cuidado has puesto en proteger en las copias, sigue viajando sin cifrar por el puerto 8080. En la lección 06-05: Gestión de Secretos y Certificados TLS se resuelven las dos: sacarás la contraseña del fichero de configuración a un secreto cifrado que systemd entrega al servicio y nadie más puede leer, aprenderás a gestionar claves con GPG y pass y a cifrar en reposo con LUKS, y montarás el material criptográfico de reservas.tramontana.example —clave, CSR, certificado de Let's Encrypt y vigilancia de su caducidad— para que el día que el proxy inverso entre en juego en el Módulo 8 el cifrado en tránsito ya esté resuelto y verificado.
Curso de Linux: De Principiante a Administrador de Sistemas
Módulo 1: Introducción a Linux
- ¿Qué es Linux?
- Historia de Linux
- Distribuciones de Linux
- Instalando Linux
- Primer Contacto con el Sistema
- Estructura del Sistema de Archivos de Linux
Módulo 2: Comandos Básicos de Linux
- Introducción a la Línea de Comandos
- Obtener Ayuda y Documentación del Sistema
- Navegando el Sistema de Archivos
- Operaciones con Archivos y Directorios
- Visualización y Edición de Archivos
- Enlaces Duros y Simbólicos
- Permisos y Propiedad de Archivos
Módulo 3: Habilidades Avanzadas en la Línea de Comandos
- El Entorno del Shell: Variables, Alias e Historial
- Uso de Comodines y Expresiones Regulares
- Búsqueda de Archivos y Contenido: find, locate y grep
- Tuberías y Redirección
- Procesamiento de Texto: cut, sort, uniq, sed y awk
- Gestión de Procesos
- Programación de Tareas con Cron
- Comandos de Redes
Módulo 4: Scripting en Shell
- Introducción al Scripting en Shell
- Variables y Tipos de Datos
- Entrada, Salida y Argumentos de un Script
- Estructuras de Control
- Funciones y Librerías
- Depuración y Manejo de Errores
- Scripts de Producción: Buenas Prácticas
Módulo 5: Administración del Sistema
- Gestión de Usuarios y Grupos
- sudo y Permisos Especiales
- Gestión de Paquetes
- Gestión de Discos
- systemd y la Gestión de Servicios
- Registros del Sistema: journald y syslog
- Monitoreo del Sistema y Optimización del Rendimiento
- Respaldo y Restauración
Módulo 6: Redes y Seguridad
- Configuración de Redes
- SSH y Acceso Remoto
- Firewall y Seguridad Perimetral
- Sistemas de Detección de Intrusos
- Gestión de Secretos y Certificados TLS
- Asegurando Sistemas Linux
Módulo 7: Temas Avanzados
- El Proceso de Arranque y la Recuperación del Sistema
- Diagnóstico Avanzado: strace, perf y eBPF
- Optimización del Kernel de Linux
- Virtualización con Linux
- Contenedores de Linux y Docker
- Automatización con Ansible
- Alta Disponibilidad y Balanceo de Carga
