Implementación de un Bastión de Seguridad con Kernel Hardening (Grsecurity/Self-Protection) y Cifrado de Memoria en Linux

1. Introducción: La Superficie de Ataque del Kernel

La mayoría de las guías de hardening se quedan en la superficie: configurar firewalls, endurecer SSH, desactivar servicios innecesarios. Son medidas necesarias pero insuficientes. Un adversario sofisticado no ataca tus reglas de iptables; ataca el Kernel Space, donde residen los privilegios absolutos del sistema.

El Kernel Self-Protection Project (KSPP) representa un cambio de paradigma: en lugar de depender exclusivamente de mecanismos externos (antivirus, IDS), reconfiguramos el propio núcleo de Linux para que sea resistente por diseño contra explotación de memoria, escalada de privilegios y ejecución de código arbitrario.

Este manual no utiliza herramientas de terceros. Vamos a modificar cómo el kernel gestiona la memoria, las llamadas al sistema y la ejecución de procesos. El objetivo: crear un sistema inmune a clases enteras de vulnerabilidades, incluyendo exploits de día cero (0-days) que aún no han sido descubiertos.

2. Implementación de KSPP: Configuración del Bootloader

Los parámetros de arranque son la primera línea de defensa. Estas configuraciones se aplican antes de que el sistema operativo cargue completamente, estableciendo invariantes de seguridad que ningún proceso de usuario puede anular.

Acción: Modificar parámetros de GRUB

Edita /etc/default/grub y modifica la línea GRUB_CMDLINE_LINUX_DEFAULT:
GRUB_CMDLINE_LINUX_DEFAULT="quiet slab_nomerge page_alloc.shuffle=1 vsyscall=none init_on_alloc=1 init_on_free=1 pti=on spectre_v2=on spec_store_bypass_disable=seccomp l1tf=full mds=full,nosmt tsx=off kvm.nx_huge_pages=force"

Análisis de parámetros críticos

 
ParámetroMecanismo de ProtecciónVector de Ataque Mitigado
slab_nomergeEvita que el kernel fusione cachés de objetos de diferente tamañoHeap overflow attacks que dependen de manipular cachés adyacentes
page_alloc.shuffle=1Aleatoriza la asignación de páginas de memoriaAtaques de predicción de direcciones de memoria (ASLR bypass)
vsyscall=noneDeshabilita la emulación de vsyscall legacyROP (Return-Oriented Programming) gadgets en memoria fija
init_on_alloc=1Inicializa a cero toda memoria asignadaUso de datos residuales de kernel previos (information leaks)
init_on_free=1Sobrescribe memoria liberada antes de reasignarUse-after-free exploits
pti=onAisla las tablas de páginas de kernel y usuarioMeltdown y ataques de lectura de memoria kernel desde userland
spectre_v2=onHabilita mitigaciones de branch target injectionSpectre v2 (Branch Target Injection)
spec_store_bypass_disable=seccompProtección contra Speculative Store BypassVariant 4 de ataques especulativos
l1tf=fullMitigación completa contra L1 Terminal FaultL1TF (Foreshadow)
mds=full,nosmtProtección contra Microarchitectural Data SamplingRIDL, Fallout, ZombieLoad
tsx=offDeshabilita Intel TSX (Transactional Synchronization Extensions)TAA (TSX Asynchronous Abort)
kvm.nx_huge_pages=forceFuerza No-Execute en páginas huge del hipervisorAtaques de corrupción de memoria en entornos virtualizados

Aplicar cambios:

sysctl --system

Aplicar cambios grub

sudo update-grub
sudo reboot

Nota para entornos virtualizados: Estos parámetros funcionan tanto en hardware bare-metal como en VMs (KVM, VMware, VirtualBox). El hipervisor emula las protecciones de hardware, permitiéndote probar configuraciones de seguridad extrema sin riesgo para el sistema host.

3. Hardening del Stack de Red: Sysctl Avanzado

Las configuraciones de red estándar se centran en el rendimiento. Aquí priorizamos la integridad de recursos y la prevención de spoofing a nivel de kernel.

Configuración de /etc/sysctl.d/99-security.conf

# === Protección contra spoofing y redirección ===
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.ipv4.conf.all.secure_redirects = 0
net.ipv4.conf.all.accept_source_route = 0
net.ipv6.conf.all.accept_source_route = 0

# === Prevención de inundaciones y DoS ===
net.ipv4.icmp_echo_ignore_broadcasts = 1
net.ipv4.icmp_ignore_bogus_error_responses = 1
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_max_syn_backlog = 2048
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_syn_retries = 5
net.netfilter.nf_conntrack_max = 2000000
net.netfilter.nf_conntrack_tcp_loose = 0

# === Ocultamiento de información del kernel ===
kernel.kptr_restrict = 2
kernel.dmesg_restrict = 1
kernel.yama.ptrace_scope = 2
kernel.unprivileged_bpf_disabled = 1
net.core.bpf_jit_harden = 2

# === Protección de memoria ===
vm.mmap_rnd_bits = 32
vm.mmap_rnd_compat_bits = 16
vm.unprivileged_userfaultfd = 0

Explicación técnica de parámetros clave

kernel.kptr_restrict = 2: Oculta las direcciones de memoria de símbolos del kernel incluso para el usuario root. Los exploits de escalada de privilegios a menudo requieren conocer direcciones específicas del kernel para construir gadgets de ROP. Con esta configuración, /proc/kallsyms muestra 0000000000000000 para todos los símbolos del kernel.
kernel.yama.ptrace_scope = 2: Limita el uso de ptrace (herramienta de debugging) solo a procesos con capacidad CAP_SYS_PTRACE. Esto bloquea técnicas comunes de inyección de código y dumping de credenciales desde procesos comprometidos.
vm.unprivileged_userfaultfd = 0: Deshabilita userfaultfd para usuarios no privilegiados. Esta syscall ha sido explotada en múltiples vulnerabilidades (como la cadena de exploit de DirtyPipe) para manipular la gestión de memoria del kernel.

Aplicación de configuraciones

 
sudo sysctl --system

4. Control de Ejecución: Seccomp y Capabilities

La seguridad tradicional se basa en usuarios y permisos de archivos. La seguridad experta se basa en capacidades del kernel y filtros de llamadas al sistema.

Concepto: Reducción de superficie de ataque por syscall

Un proceso comprometido solo puede ejecutar las syscalls que el kernel le permite. Si eliminamos execve, el proceso no puede lanzar nuevos programas. Si eliminamos openat, no puede abrir archivos arbitrarios.

Práctica: Perfil Seccomp para Nginx

Creamos un perfil que permite a Nginx operar normalmente pero bloquea cualquier intento de ejecución de código adicional después del arranque.
Archivo: /etc/nginx/seccomp-bpf.json
{
  "defaultAction": "SCMP_ACT_ERRNO",
  "architectures": ["SCMP_ARCH_X86_64", "SCMP_ARCH_X86"],
  "syscalls": [
    {
      "names": [
        "accept", "accept4", "bind", "clone", "close", "connect",
        "epoll_create", "epoll_create1", "epoll_ctl", "epoll_pwait",
        "epoll_wait", "eventfd2", "exit", "exit_group", "fchdir",
        "fchmod", "fchown", "fcntl", "fstat", "fstatfs", "fsync",
        "ftruncate", "getcwd", "getdents", "getdents64", "getegid",
        "geteuid", "getgid", "getpgrp", "getpid", "getppid", "getrlimit",
        "getuid", "ioctl", "io_setup", "listen", "lseek", "mkdir",
        "mmap", "mprotect", "munmap", "nanosleep", "openat", "pipe",
        "pipe2", "poll", "pread64", "pselect6", "pwrite64", "read",
        "recvfrom", "recvmsg", "rename", "rmdir", "rt_sigaction",
        "rt_sigprocmask", "rt_sigreturn", "select", "sendfile",
        "sendmsg", "sendto", "setitimer", "setrlimit", "setsockopt",
        "shutdown", "sigaltstack", "socket", "socketpair", "stat",
        "statfs", "sysinfo", "umask", "uname", "unlink", "utimensat",
        "write", "writev"
      ],
      "action": "SCMP_ACT_ALLOW"
    },
    {
      "names": ["execve", "execveat", "fork", "vfork"],
      "action": "SCMP_ACT_KILL"
    }
  ]
}

Integración con Systemd

Modifica el servicio de Nginx (/etc/systemd/system/nginx.service.d/override.conf):
[Service]
SystemCallFilter=@system-service
SystemCallErrorNumber=EPERM
SystemCallArchitectures=native
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
ProtectKernelTunables=true
ProtectKernelModules=true
ProtectControlGroups=true
RestrictRealtime=true
RestrictSUIDSGID=true
LockPersonality=true
MemoryDenyWriteExecute=true
CapabilityBoundingSet=CAP_NET_BIND_SERVICE CAP_SETGID CAP_SETUID

Análisis de protecciones

  • SystemCallFilter=@system-service: Utiliza el conjunto predefinido de syscalls seguras para servicios de sistema.
  • NoNewPrivileges=true: Previene que el proceso gane privilegios adicionales (bloquea setuid binaries).
  • ProtectSystem=strict: Monta el sistema de archivos raíz como solo lectura e inaccesible para el servicio.
  • MemoryDenyWriteExecute=true: Activa W^X (Write XOR Execute), previniendo que la memoria sea simultáneamente escribible y ejecutable (mitigación contra shellcode).
Recarga y reinicia:
sudo systemctl daemon-reload
sudo systemctl restart nginx

Ejemplo plantillas Seccomp-BPF para Servicios Comunes

Crear directorio y archivo

sudo mkdir -p /etc/seccomp
sudo vi /etc/seccomp/profiles.json
Archivo: /etc/seccomp/profiles.json (formato compatible con Docker, containerd, systemd y runc)
 
{
  "profiles": {
    "nginx-web-server": {
      "defaultAction": "SCMP_ACT_ERRNO",
      "architectures": [
        "SCMP_ARCH_X86_64",
        "SCMP_ARCH_X86",
        "SCMP_ARCH_AARCH64"
      ],
      "syscalls": [
        {
          "names": [
            "accept", "accept4", "access", "alarm", "bind", "brk",
            "capget", "capset", "chdir", "chmod", "chown", "clock_gettime",
            "clone", "clone3", "close", "close_range", "connect", "copy_file_range",
            "creat", "dup", "dup2", "dup3", "epoll_create", "epoll_create1",
            "epoll_ctl", "epoll_pwait", "epoll_pwait2", "epoll_wait", "eventfd2",
            "execve", "execveat", "exit", "exit_group", "faccessat", "faccessat2",
            "fadvise64", "fallocate", "fanotify_mark", "fchdir", "fchmod",
            "fchmodat", "fchown", "fchownat", "fcntl", "fdatasync", "fgetxattr",
            "flistxattr", "flock", "fork", "fremovexattr", "fsetxattr", "fstat",
            "fstatfs", "fsync", "ftruncate", "futex", "getcwd", "getdents",
            "getdents64", "getegid", "geteuid", "getgid", "getgroups",
            "getitimer", "getpeername", "getpgid", "getpgrp", "getpid",
            "getppid", "getpriority", "getrandom", "getresgid", "getresuid",
            "getrlimit", "getrusage", "getsid", "getsockname", "getsockopt",
            "gettid", "gettimeofday", "getuid", "getxattr", "inotify_add_watch",
            "inotify_init1", "inotify_rm_watch", "io_cancel", "io_destroy",
            "io_getevents", "io_setup", "io_submit", "ioctl", "ioprio_get",
            "ioprio_set", "kcmp", "kill", "lchown", "lgetxattr", "link",
            "linkat", "listen", "listxattr", "llistxattr", "lremovexattr",
            "lseek", "lsetxattr", "lstat", "madvise", "memfd_create",
            "mincore", "mkdir", "mkdirat", "mknod", "mknodat", "mlock",
            "mlock2", "mlockall", "mmap", "mprotect", "mq_getsetattr",
            "mq_notify", "mq_open", "mq_timedreceive", "mq_timedsend",
            "mq_unlink", "mremap", "msgctl", "msgget", "msgrcv", "msgsnd",
            "msync", "munlock", "munlockall", "munmap", "nanosleep",
            "newfstatat", "open", "openat", "openat2", "pause", "pipe",
            "pipe2", "poll", "ppoll", "prctl", "pread64", "preadv",
            "preadv2", "prlimit64", "pselect6", "pwrite64", "pwritev",
            "pwritev2", "read", "readahead", "readdir", "readlink",
            "readlinkat", "readv", "recv", "recvfrom", "recvmmsg",
            "recvmsg", "remap_file_pages", "removexattr", "rename",
            "renameat", "renameat2", "restart_syscall", "rmdir", "rseq",
            "rt_sigaction", "rt_sigpending", "rt_sigprocmask", "rt_sigqueueinfo",
            "rt_sigreturn", "rt_sigsuspend", "rt_sigtimedwait", "rt_tgsigqueueinfo",
            "sched_getaffinity", "sched_getattr", "sched_getparam",
            "sched_get_priority_max", "sched_get_priority_min", "sched_getscheduler",
            "sched_rr_get_interval", "sched_setaffinity", "sched_setattr",
            "sched_setparam", "sched_setscheduler", "sched_yield", "seccomp",
            "select", "semctl", "semget", "semop", "semtimedop", "send",
            "sendfile", "sendmmsg", "sendmsg", "sendto", "setfsgid", "setfsuid",
            "setgid", "setgroups", "setitimer", "setpgid", "setpriority",
            "setregid", "setresgid", "setresuid", "setreuid", "setrlimit",
            "setsid", "setsockopt", "setuid", "setxattr", "shmat", "shmctl",
            "shmdt", "shmget", "shutdown", "sigaltstack", "signalfd4",
            "socket", "socketpair", "splice", "stat", "statfs", "statx",
            "symlink", "symlinkat", "sync", "sync_file_range", "syncfs",
            "sysinfo", "tee", "tgkill", "time", "timer_create", "timer_delete",
            "timer_getoverrun", "timer_gettime", "timer_settime", "timerfd_create",
            "timerfd_gettime", "timerfd_settime", "times", "tkill", "truncate",
            "umask", "uname", "unlink", "unlinkat", "utime", "utimensat",
            "utimes", "vfork", "wait4", "waitid", "write", "writev"
          ],
          "action": "SCMP_ACT_ALLOW"
        },
        {
          "names": [
            "bpf",
            "clock_adjtime",
            "clock_settime",
            "create_module",
            "delete_module",
            "finit_module",
            "get_kernel_syms",
            "get_mempolicy",
            "init_module",
            "ioperm",
            "iopl",
            "kexec_file_load",
            "kexec_load",
            "keyctl",
            "lookup_dcookie",
            "mbind",
            "nfsservctl",
            "open_by_handle_at",
            "perf_event_open",
            "personality",
            "pivot_root",
            "process_vm_readv",
            "process_vm_writev",
            "ptrace",
            "query_module",
            "quotactl",
            "reboot",
            "request_key",
            "set_mempolicy",
            "setns",
            "settimeofday",
            "stime",
            "swapoff",
            "swapon",
            "_sysctl",
            "syslog",
            "tuxcall",
            "umount2",
            "uselib",
            "userfaultfd",
            "ustat",
            "vm86",
            "vm86old"
          ],
          "action": "SCMP_ACT_KILL"
        }
      ]
    },
    
    "database-server": {
      "defaultAction": "SCMP_ACT_ERRNO",
      "architectures": ["SCMP_ARCH_X86_64"],
      "syscalls": [
        {
          "names": [
            "accept", "accept4", "access", "bind", "brk", "capget", "capset",
            "chdir", "chmod", "chown", "clock_gettime", "clone", "clone3",
            "close", "connect", "creat", "dup", "dup2", "dup3", "epoll_create",
            "epoll_create1", "epoll_ctl", "epoll_pwait", "epoll_wait", "eventfd2",
            "execve", "exit", "exit_group", "faccessat", "fadvise64", "fallocate",
            "fchdir", "fchmod", "fchmodat", "fchown", "fchownat", "fcntl",
            "fdatasync", "flock", "fork", "fstat", "fstatfs", "fsync", "ftruncate",
            "futex", "getcwd", "getdents", "getdents64", "getegid", "geteuid",
            "getgid", "getgroups", "getitimer", "getpeername", "getpgrp", "getpid",
            "getppid", "getpriority", "getrandom", "getresgid", "getresuid",
            "getrlimit", "getrusage", "getsockname", "getsockopt", "gettid",
            "gettimeofday", "getuid", "ioctl", "kill", "link", "linkat", "listen",
            "lseek", "lstat", "madvise", "mkdir", "mkdirat", "mknod", "mknodat",
            "mlock", "mlockall", "mmap", "mprotect", "mq_getsetattr", "mq_notify",
            "mq_open", "mq_timedreceive", "mq_timedsend", "mq_unlink", "mremap",
            "msync", "munlock", "munlockall", "munmap", "nanosleep", "newfstatat",
            "open", "openat", "pause", "pipe", "pipe2", "poll", "ppoll", "prctl",
            "pread64", "preadv", "prlimit64", "pselect6", "pwrite64", "pwritev",
            "read", "readahead", "readlink", "readlinkat", "readv", "recv",
            "recvfrom", "recvmmsg", "recvmsg", "rename", "renameat", "renameat2",
            "rmdir", "rt_sigaction", "rt_sigpending", "rt_sigprocmask",
            "rt_sigqueueinfo", "rt_sigreturn", "rt_sigsuspend", "rt_sigtimedwait",
            "sched_getaffinity", "sched_getattr", "sched_getparam",
            "sched_get_priority_max", "sched_get_priority_min", "sched_getscheduler",
            "sched_rr_get_interval", "sched_setaffinity", "sched_setattr",
            "sched_setparam", "sched_setscheduler", "sched_yield", "select",
            "semctl", "semget", "semop", "semtimedop", "send", "sendfile",
            "sendmmsg", "sendmsg", "sendto", "setfsgid", "setfsuid", "setgid",
            "setgroups", "setitimer", "setpgid", "setpriority", "setregid",
            "setresgid", "setresuid", "setreuid", "setrlimit", "setsid",
            "setsockopt", "setuid", "shmat", "shmctl", "shmdt", "shmget",
            "shutdown", "sigaltstack", "signalfd4", "socket", "socketpair",
            "splice", "stat", "statfs", "sync", "sync_file_range", "syncfs",
            "sysinfo", "tee", "tgkill", "time", "timer_create", "timer_delete",
            "timer_getoverrun", "timer_gettime", "timer_settime", "timerfd_create",
            "timerfd_gettime", "timerfd_settime", "times", "tkill", "truncate",
            "umask", "uname", "unlink", "unlinkat", "utime", "utimensat",
            "utimes", "vfork", "wait4", "waitid", "write", "writev"
          ],
          "action": "SCMP_ACT_ALLOW"
        },
        {
          "names": ["execveat", "ptrace", "process_vm_readv", "process_vm_writev", 
                   "userfaultfd", "perf_event_open", "bpf", "mount", "umount2"],
          "action": "SCMP_ACT_KILL"
        }
      ]
    },
    
    "minimal-microservice": {
      "defaultAction": "SCMP_ACT_ERRNO",
      "architectures": ["SCMP_ARCH_X86_64"],
      "syscalls": [
        {
          "names": [
            "accept", "accept4", "bind", "brk", "capget", "capset", "chdir",
            "chmod", "clock_gettime", "clone", "clone3", "close", "connect",
            "creat", "dup", "dup2", "dup3", "epoll_create", "epoll_create1",
            "epoll_ctl", "epoll_pwait", "epoll_wait", "eventfd2", "exit",
            "exit_group", "faccessat", "fadvise64", "fallocate", "fchdir",
            "fchmod", "fchmodat", "fchown", "fchownat", "fcntl", "fdatasync",
            "flock", "fstat", "fstatfs", "fsync", "ftruncate", "futex", "getcwd",
            "getdents", "getdents64", "getegid", "geteuid", "getgid", "getgroups",
            "getitimer", "getpeername", "getpgrp", "getpid", "getppid",
            "getpriority", "getrandom", "getresgid", "getresuid", "getrlimit",
            "getrusage", "getsockname", "getsockopt", "gettid", "gettimeofday",
            "getuid", "ioctl", "listen", "lseek", "lstat", "madvise", "mkdir",
            "mkdirat", "mmap", "mprotect", "mremap", "munmap", "nanosleep",
            "newfstatat", "open", "openat", "pipe", "pipe2", "poll", "ppoll",
            "pread64", "preadv", "prlimit64", "pselect6", "pwrite64", "pwritev",
            "read", "readahead", "readlink", "readlinkat", "readv", "recv",
            "recvfrom", "recvmmsg", "recvmsg", "rename", "renameat", "renameat2",
            "rmdir", "rt_sigaction", "rt_sigpending", "rt_sigprocmask",
            "rt_sigreturn", "rt_sigsuspend", "rt_sigtimedwait", "sched_getaffinity",
            "sched_getattr", "sched_getparam", "sched_get_priority_max",
            "sched_get_priority_min", "sched_getscheduler", "sched_rr_get_interval",
            "sched_setaffinity", "sched_setattr", "sched_setparam",
            "sched_setscheduler", "sched_yield", "select", "send", "sendfile",
            "sendmmsg", "sendmsg", "sendto", "setfsgid", "setfsuid", "setgid",
            "setgroups", "setitimer", "setpgid", "setpriority", "setregid",
            "setresgid", "setresuid", "setreuid", "setrlimit", "setsid",
            "setsockopt", "setuid", "shutdown", "sigaltstack", "signalfd4",
            "socket", "socketpair", "splice", "stat", "statfs", "sync",
            "sync_file_range", "syncfs", "sysinfo", "tee", "tgkill", "time",
            "timer_create", "timer_delete", "timer_getoverrun", "timer_gettime",
            "timer_settime", "timerfd_create", "timerfd_gettime", "timerfd_settime",
            "times", "tkill", "truncate", "umask", "uname", "unlink", "unlinkat",
            "utime", "utimensat", "utimes", "wait4", "waitid", "write", "writev"
          ],
          "action": "SCMP_ACT_ALLOW"
        },
        {
          "names": ["execve", "execveat", "fork", "vfork", "ptrace", "mount", 
                   "umount2", "chroot", "pivot_root", "setns", "unshare"],
          "action": "SCMP_ACT_KILL"
        }
      ]
    }
  }
}
Script de aplicación para systemd:
 

Archivo: /usr/local/bin/apply-seccomp.sh

#!/bin/bash
# Aplica perfiles seccomp a servicios systemd

PROFILE=$1
SERVICE=$2

if [[ -z "$PROFILE" || -z "$SERVICE" ]]; then
    echo "Uso: $0 <nginx-web-server|database-server|minimal-microservice> <nombre-servicio>"
    exit 1
fi

# Crear directorios necesarios si no existen
mkdir -p /var/log/nginx /var/lib/nginx /var/cache/nginx /run/nginx

mkdir -p /etc/systemd/system/${SERVICE}.service.d/

cat > /etc/systemd/system/${SERVICE}.service.d/seccomp.conf << EOF
[Service]
# 1. Primero: definir rutas de lectura/escritura
ReadWritePaths=/var/log/nginx /var/lib/nginx /var/cache/nginx /run/nginx

# 2. Luego: protecciones de sistema
ProtectSystem=strict
ProtectHome=true
ProtectKernelTunables=true
ProtectKernelModules=true
ProtectControlGroups=true

# 3. Restricciones de seguridad
NoNewPrivileges=true
RestrictRealtime=true
RestrictSUIDSGID=true
LockPersonality=true
MemoryDenyWriteExecute=true

# 4. Filtro de syscalls
SystemCallFilter=@system-service
SystemCallErrorNumber=EPERM
SystemCallArchitectures=native
EOF

systemctl daemon-reload
systemctl restart $SERVICE
echo "Perfil seccomp aplicado a $SERVICE"

Damos permisos y ejecutamos el script

 chmod +x /usr/local/bin/apply-seccomp.sh
 /usr/local/bin/apply-seccomp.sh nginx-web-server nginx
Perfil seccomp aplicado a nginx

Comprobamos que el servicio

root@srvlhm01:~# systemctl status nginx
● nginx.service - A high performance web server and a reverse proxy server
     Loaded: loaded (/lib/systemd/system/nginx.service; enabled; preset: enabled)
    Drop-In: /etc/systemd/system/nginx.service.d
             └─seccomp.conf
     Active: active (running) since Fri 2026-02-13 17:49:06 UTC; 45s ago
       Docs: man:nginx(8)
    Process: 753 ExecStartPre=/usr/sbin/nginx -t -q -g daemon on; master_process on; (code=exited, status=0/SUCCESS)
    Process: 754 ExecStart=/usr/sbin/nginx -g daemon on; master_process on; (code=exited, status=0/SUCCESS)
   Main PID: 755 (nginx)
      Tasks: 3 (limit: 4700)
     Memory: 2.4M
        CPU: 129ms
     CGroup: /system.slice/nginx.service
             ├─755 "nginx: master process /usr/sbin/nginx -g daemon on; master_process on;"
             ├─756 "nginx: worker process"
             └─757 "nginx: worker process"

Como modificar Script para Nuevo Servicio

Agregar caso en apply-seccomp.sh:

#!/bin/bash
PROFILE=$1
SERVICE=$2

# Crear directorios específicos del servicio
case "$SERVICE" in
    nginx)
        mkdir -p /var/log/nginx /var/lib/nginx /var/cache/nginx /run/nginx
        READWRITE="/var/log/nginx /var/lib/nginx /var/cache/nginx /run/nginx"
        ;;
    mysql|mariadb)
        mkdir -p /var/log/mysql /var/lib/mysql /var/run/mysqld /tmp
        READWRITE="/var/log/mysql /var/lib/mysql /var/run/mysqld /tmp"
        ;;
    postgresql)
        mkdir -p /var/log/postgresql /var/lib/postgresql /var/run/postgresql /tmp
        READWRITE="/var/log/postgresql /var/lib/postgresql /var/run/postgresql /tmp"
        ;;
    redis)
        mkdir -p /var/log/redis /var/lib/redis /var/run/redis /tmp
        READWRITE="/var/log/redis /var/lib/redis /var/run/redis /tmp"
        ;;
    *)
        echo "Servicio no configurado. Usando rutas genéricas."
        READWRITE="/var/log/$SERVICE /var/lib/$SERVICE /var/run/$SERVICE /tmp"
        mkdir -p $READWRITE
        ;;
esac

mkdir -p /etc/systemd/system/${SERVICE}.service.d/

cat > /etc/systemd/system/${SERVICE}.service.d/seccomp.conf << EOF
[Service]
ReadWritePaths=$READWRITE
ProtectSystem=strict
ProtectHome=true
ProtectKernelTunables=true
ProtectKernelModules=true
ProtectControlGroups=true
NoNewPrivileges=true
RestrictRealtime=true
RestrictSUIDSGID=true
LockPersonality=true
MemoryDenyWriteExecute=true
SystemCallFilter=@system-service
SystemCallErrorNumber=EPERM
SystemCallArchitectures=native
EOF

systemctl daemon-reload
systemctl restart $SERVICE
echo "Perfil seccomp aplicado a $SERVICE"

Gestión de Excepciones

Cuando un Servicio Falla

Paso 1: Verificar error específico

 

journalctl -xeu SERVICIO --no-pager -n 50

Paso 2: Identificar tipo de error

ErrorCausaSolución
Read-only file systemFalta directorio en ReadWritePathsAñadir ruta
No such file or directory + NAMESPACEDirectorio no existemkdir -p antes
Operation not permittedSyscall bloqueadaRevisar SystemCallFilter
Permission deniedCapabilities insuficientesAjustar CapabilityBoundingSet
Paso 3: Modificar configuración
Editar /etc/systemd/system/SERVICIO.service.d/seccomp.conf:
[Service]
# Añadir excepción de ruta
ReadWritePaths=/var/log/nginx /var/lib/nginx /var/cache/nginx /run/nginx /NUEVA/RUTA

# O añadir capability específica
CapabilityBoundingSet=CAP_NET_BIND_SERVICE CAP_SETGID CAP_SETUID CAP_NUEVA

# O relajar SystemCallFilter para syscalls específicas
SystemCallFilter=@system-service personality  # añadir syscall al allowlist

Paso 4: Recargar y reiniciar

systemctl daemon-reload
systemctl restart SERVICIO

Ejemplos Prácticos

MySQL/MariaDB

 

/usr/local/bin/apply-seccomp.sh database-server mysql

Excepciones típicas:

  • /var/lib/mysql – Datos
  • /var/log/mysql – Logs
  • /var/run/mysqld – Socket
  • /tmp – Temporales

Capability adicional:

CapabilityBoundingSet=CAP_IPC_LOCK  # Para bloquear memoria con mlock

PostgreSQL

/usr/local/bin/apply-seccomp.sh database-server postgresql
  • /var/lib/postgresql
  • /var/log/postgresql
  • /var/run/postgresql

Redis

/usr/local/bin/apply-seccomp.sh minimal-microservice redis

Excepciones:

  • /var/lib/redis
  • /var/log/redis
  • /var/run/redis

Verificación de Funcionamiento

# Verificar que el servicio está activo
systemctl status SERVICIO

# Verificar que las restricciones están aplicadas
systemctl show SERVICIO --property=ProtectSystem,ProtectHome,NoNewPrivileges,MemoryDenyWriteExecute

# Verificar syscalls bloqueadas (auditar denegaciones)
dmesg | grep -i "audit.*seccomp\|syscall"
grep -E "CONFIG_IMA|CONFIG_IMA_APPRAISE|CONFIG_IMA_KEYRINGS_PERMIT_SIGNED_BY_BUILTIN_OR_SECONDARY" /boot/config-$(uname -r)

5. Auditoría de Integridad: AIDE (Advanced Intrusion Detection Environment)

AIDE es un sistema de detección de intrusiones que crea una base de datos de integridad de archivos y verifica periódicamente si han ocurrido cambios no autorizados. A diferencia de IMA, AIDE opera en espacio de usuario, proporcionando una capa adicional de detección post-compromiso sin modificar el kernel ni requerir firmas criptográficas en tiempo real.

Requisitos de la Raíz de Confianza (Root of Trust)

Para que AIDE sea efectivo en un entorno profesional, debe estar anclado a controles externos:
  • Almacenamiento seguro: La base de datos de AIDE debe guardarse en medio de solo lectura o sistema de archivos remoto inmutable
  • Kernel hardening: Las protecciones KSPP previenen la modificación de AIDE en tiempo de ejecución
  • Monitoreo: Integración con SIEM para alertas en tiempo real de modificaciones críticas

Verificación del Soporte e Instalación

# Instalación en Debian/Ubuntu
sudo apt update && sudo apt install -y aide aide-common

# Verificar instalación
aide --version

Configuración de AIDE

Archivo: /etc/aide/aide.conf
# === CONFIGURACIÓN BASE ===
database_in=file:/var/lib/aide/aide.db
database_out=file:/var/lib/aide/aide.db.new
database_new=file:/var/lib/aide/aide.db.new
gzip_dbout=yes
verbose=5

# === REGLAS DE DEFINICIÓN ===
# Atributos a monitorear:
# p: permisos
# i: inode
# n: número de enlaces
# u: usuario
# g: grupo
# s: tamaño
# b: bloques
# m: mtime
# a: atime
# c: ctime
# S: checksum SHA256
# sha256: hash SHA256 completo

# Binarios críticos - monitoreo estricto
Binlib = p+u+g+s+b+m+c+sha256

# Archivos de configuración - detectar modificaciones
ConfFiles = p+u+g+s+b+m+c+sha256

# Logs - solo permisos y ownership (cambian frecuentemente)
Logs = p+u+g

# Directorios - estructura básica
Dirs = p+u+g

# === RUTAS A MONITOREAR ===

# Directorios de sistema críticos
/boot   Binlib
/bin    Binlib
/sbin   Binlib
/lib    Binlib
/lib64  Binlib
/usr/bin    Binlib
/usr/sbin   Binlib
/usr/lib    Binlib
/usr/lib64  Binlib

# Archivos de configuración críticos
/etc    ConfFiles
!/etc/mtab
!/etc/resolv.conf
!/etc/hdparam
!/etc/udev/devices
!/etc/network/run
!/etc/network/interfaces
!/etc/network/if-*
!/etc/network/if-*/.*
!/etc/puppet/ssl
!/etc/rc*.d
!/etc/init.d
!/etc/cron.d
!/etc/cron.daily
!/etc/cron.hourly
!/etc/cron.weekly
!/etc/cron.monthly
!/etc/logrotate.d
!/etc/logrotate.status
!/etc/prelink.cache

# Kernel y módulos
/lib/modules  Binlib
/usr/src      Binlib

# Archivos de servicios críticos
/usr/local/bin  Binlib
/opt            Binlib

# Exclusiones para reducir ruido
!/var/log/.*
!/var/cache/.*
!/var/tmp/.*
!/var/spool/.*
!/var/run/.*
!/var/lock/.*
!/proc
!/sys
!/dev
!/run
!/tmp
!/home
!/root/.bash_history
!/root/.lesshst
!/root/.viminfo

Inicialización de la Base de Datos

 
# Crear directorio para la base de datos
sudo mkdir -p /var/lib/aide
sudo chmod 700 /var/lib/aide

# Inicializar base de datos (primera vez - toma tiempo)
sudo aideinit

# El comando anterior crea /var/lib/aide/aide.db.new
# Mover a ubicación definitiva
sudo mv /var/lib/aide/aide.db.new /var/lib/aide/aide.db
sudo chmod 600 /var/lib/aide/aide.db

# Verificar que se creó correctamente
ls -la /var/lib/aide/

Verificación y Chequeos Manuales

 
# Verificar integridad del sistema contra la base de datos
sudo aide --check

# Actualizar base de datos después de cambios legítimos
sudo aide --update
sudo mv /var/lib/aide/aide.db.new /var/lib/aide/aide.db

Automatización con Cron

Archivo: /etc/cron.d/aide-check

 

# Verificación diaria de integridad a las 3:00 AM
0 3 * * * root /usr/bin/aide --check | mail -s "AIDE Check $(hostname)" root@localhost

# Actualización semanal de la base de datos (domingos a las 2:00 AM)
0 2 * * 0 root /usr/bin/aide --update && mv /var/lib/aide/aide.db.new /var/lib/aide/aide.db

Integración con Systemd para Alertas en Tiempo Real

Archivo: /etc/systemd/system/aide-check.service

 

[Unit]
Description=AIDE Integrity Check
After=network.target

[Service]
Type=oneshot
ExecStart=/usr/bin/aide --check
StandardOutput=journal
StandardError=journal
Archivo: /etc/systemd/system/aide-check.timer
 
[Unit]
Description=Run AIDE check every hour
Requires=aide-check.service

[Timer]
OnCalendar=hourly
Persistent=true

[Install]
WantedBy=timers.target

Activar timer:

sudo systemctl daemon-reload
sudo systemctl enable aide-check.timer
sudo systemctl start aide-check.timer

Configuración de GRUB con Soporte para AIDE

Dado que AIDE opera en espacio de usuario, no requiere parámetros especiales de kernel. Sin embargo, mantenemos el hardening KSPP:

 

GRUB_CMDLINE_LINUX_DEFAULT="quiet slab_nomerge page_alloc.shuffle=1 vsyscall=none pti=on spectre_v2=on spec_store_bypass_disable=seccomp l1tf=full mds=full,nosmt tsx=off net.ifnames=0 biosdevname=0"
Actualiza y reinicia:
 
sudo update-grub
sudo reboot

Verificación del Funcionamiento

 
# Verificar que AIDE está instalado
which aide
aide --version

# Verificar base de datos
ls -la /var/lib/aide/aide.db

# Ejecutar chequeo manual
sudo aide --check

# Ver logs de systemd si usas timer
journalctl -u aide-check.service --no-pager -n 20

Script de Configuración Automatizada para Servidores Web

Archivo: aide-setup-webserver.sh

 

#!/bin/bash
# AIDE Setup for Web Servers
# Configura AIDE para servidores web con monitoreo específico

set -euo pipefail

AIDE_DIR="/var/lib/aide"
CONF_DIR="/etc/aide"
LOG_DIR="/var/log/aide"
KEYS_DIR="/etc/keys/aide"

log() {
    echo "[$(date +%Y-%m-%d\ %H:%M:%S)] $1"
}

error() {
    echo "[ERROR] $1" >&2
    exit 1
}

check_aide_support() {
    if ! command -v aide &> /dev/null; then
        log "Instalando AIDE..."
        apt-get update && apt-get install -y aide aide-common || \
        yum install -y aide || \
        pacman -S aide
    fi
    
    if ! command -v aide &> /dev/null; then
        error "No se pudo instalar AIDE"
    fi
    
    log "AIDE instalado: $(aide --version | head -1)"
}

setup_directories() {
    mkdir -p "$AIDE_DIR" "$CONF_DIR" "$LOG_DIR" "$KEYS_DIR"
    chmod 700 "$AIDE_DIR" "$KEYS_DIR"
    chmod 755 "$CONF_DIR" "$LOG_DIR"
    log "Directorios creados"
}

create_custom_config() {
    log "Creando configuración personalizada para servidor web..."
    
    cat > "${CONF_DIR}/aide-web.conf" << 'EOF'
# AIDE Configuration for Web Servers

database_in=file:/var/lib/aide/aide.db
database_out=file:/var/lib/aide/aide.db.new
database_new=file:/var/lib/aide/aide.db.new
gzip_dbout=yes
verbose=5

# Definiciones de reglas
Binlib = p+u+g+s+b+m+c+sha256
ConfFiles = p+u+g+s+b+m+c+sha256
WebFiles = p+u+g+s+b+m+c+sha256
Logs = p+u+g

# Sistema base
/boot   Binlib
/bin    Binlib
/sbin   Binlib
/lib    Binlib
/lib64  Binlib
/usr/bin    Binlib
/usr/sbin   Binlib
/usr/lib    Binlib
/usr/lib64  Binlib

# Configuración del sistema
/etc    ConfFiles

# Servidores web específicos
/etc/nginx      ConfFiles
/etc/apache2    ConfFiles
/etc/httpd      ConfFiles
/etc/php        ConfFiles
/usr/share/nginx    Binlib
/usr/share/apache2  Binlib
/var/www        WebFiles
/var/www/html   WebFiles
/var/www/cgi-bin WebFiles

# Aplicaciones web comunes
/opt/lampp      Binlib
/usr/local/lampp Binlib

# Exclusiones
!/var/log/.*
!/var/cache/.*
!/var/tmp/.*
!/var/spool/.*
!/var/run/.*
!/var/lock/.*
!/proc
!/sys
!/dev
!/run
!/tmp
!/home
!/root/.bash_history
!/root/.lesshst
!/root/.viminfo
!/var/lib/aide
!/var/log/aide
EOF

    chmod 644 "${CONF_DIR}/aide-web.conf"
    log "Configuración creada en ${CONF_DIR}/aide-web.conf"
}

initialize_database() {
    log "Inicializando base de datos AIDE..."
    
    if [[ -f "${AIDE_DIR}/aide.db" ]]; then
        log "Base de datos existente encontrada. ¿Regenerar? (s/N)"
        read -r response
        if [[ ! "$response" =~ ^[Ss]$ ]]; then
            return
        fi
        backup_file="${AIDE_DIR}/aide.db.backup.$(date +%Y%m%d%H%M%S)"
        cp "${AIDE_DIR}/aide.db" "$backup_file"
        log "Backup creado: $backup_file"
    fi
    
    aide --config="${CONF_DIR}/aide-web.conf" --init
    
    if [[ -f "${AIDE_DIR}/aide.db.new" ]]; then
        mv "${AIDE_DIR}/aide.db.new" "${AIDE_DIR}/aide.db"
        chmod 600 "${AIDE_DIR}/aide.db"
        log "Base de datos inicializada correctamente"
    else
        error "No se pudo crear la base de datos"
    fi
}

setup_cron_jobs() {
    log "Configurando cron jobs..."
    
    # Script de chequeo con notificación
    cat > /usr/local/bin/aide-check-wrapper.sh << 'EOF'
#!/bin/bash
# Wrapper para AIDE con logging y alertas

LOG_FILE="/var/log/aide/aide-check-$(date +%Y%m%d-%H%M%S).log"
REPORT_FILE="/var/log/aide/aide-report-$(date +%Y%m%d-%H%M%S).txt"

echo "=== AIDE Check Started: $(date) ===" > "$LOG_FILE"

# Ejecutar chequeo
aide --config=/etc/aide/aide-web.conf --check > "$REPORT_FILE" 2>&1
RESULT=$?

if [ $RESULT -eq 0 ]; then
    echo "AIDE check completed: No changes detected" >> "$LOG_FILE"
    logger -t aide "Integrity check passed - no changes"
else
    echo "AIDE check completed: CHANGES DETECTED" >> "$LOG_FILE"
    echo "See report: $REPORT_FILE" >> "$LOG_FILE"
    logger -t aide "ALERT: Integrity check failed - changes detected"
    
    # Enviar alerta (personalizar según infraestructura)
    if command -v mail &> /dev/null; then
        mail -s "AIDE ALERT: Changes detected on $(hostname)" root@localhost < "$REPORT_FILE"
    fi
    
    # Opcional: Integración con Slack/Discord/webhook
    # curl -X POST -H 'Content-type: application/json' \
    #   --data '{"text":"AIDE Alert: Changes detected on '$(hostname)'"}' \
    #   YOUR_WEBHOOK_URL
fi

# Mantener solo los últimos 30 días de logs
find /var/log/aide -name "aide-check-*.log" -mtime +30 -delete
find /var/log/aide -name "aide-report-*.txt" -mtime +30 -delete

exit $RESULT
EOF

    chmod +x /usr/local/bin/aide-check-wrapper.sh
    
    # Cron job para chequeo diario
    echo "0 3 * * * root /usr/local/bin/aide-check-wrapper.sh" > /etc/cron.d/aide-web-check
    
    log "Cron jobs configurados"
}

create_status_script() {
    cat > /usr/local/bin/aide-status << 'EOF'
#!/bin/bash
# AIDE Status Checker

echo "=== AIDE Status Report ==="
echo "Fecha: $(date)"
echo ""

if command -v aide &> /dev/null; then
    echo "AIDE está instalado"
    aide --version | head -1
    echo ""
    
    if [[ -f /var/lib/aide/aide.db ]]; then
        echo "Base de datos: $(ls -lh /var/lib/aide/aide.db | awk '{print $5, $6, $7, $8}')"
        echo "Última modificación: $(stat -c %y /var/lib/aide/aide.db)"
    else
        echo "ADVERTENCIA: No se encontró base de datos"
    fi
    
    echo ""
    echo "Últimos chequeos:"
    ls -lt /var/log/aide/aide-check-*.log 2>/dev/null | head -5 | awk '{print $6, $7, $8, $9}'
    
    echo ""
    echo "Para ejecutar chequeo manual: sudo aide --config=/etc/aide/aide-web.conf --check"
    echo "Para actualizar base de datos: sudo aide --config=/etc/aide/aide-web.conf --update"
else
    echo "AIDE NO está instalado"
fi
EOF
    chmod +x /usr/local/bin/aide-status
    log "Script de verificación creado: /usr/local/bin/aide-status"
}

create_emergency_script() {
    cat > /usr/local/bin/aide-emergency << 'EOF'
#!/bin/bash
# AIDE Emergency Procedures

echo "=== AIDE Emergency Tools ==="
echo ""

case "$1" in
    update)
        echo "Actualizando base de datos AIDE..."
        aide --config=/etc/aide/aide-web.conf --update
        if [[ -f /var/lib/aide/aide.db.new ]]; then
            mv /var/lib/aide/aide.db.new /var/lib/aide/aide.db
            echo "Base de datos actualizada"
        fi
        ;;
    compare)
        echo "Comparando con backup..."
        if [[ -f /var/lib/aide/aide.db.backup.* ]]; then
            latest=$(ls -t /var/lib/aide/aide.db.backup.* | head -1)
            echo "Comparando con: $latest"
            # Nota: AIDE no soporta comparación directa de DBs, se requiere exportar
            echo "Use: aide --config=/etc/aide/aide-web.conf --check"
        else
            echo "No se encontraron backups"
        fi
        ;;
    reset)
        echo "REINICIALIZANDO BASE DE DATOS AIDE..."
        echo "¿Estás seguro? Esto eliminará la base actual. (yes/no)"
        read -r confirm
        if [[ "$confirm" == "yes" ]]; then
            rm -f /var/lib/aide/aide.db
            aide --config=/etc/aide/aide-web.conf --init
            mv /var/lib/aide/aide.db.new /var/lib/aide/aide.db
            echo "Base de datos reinicializada"
        else
            echo "Operación cancelada"
        fi
        ;;
    *)
        echo "Uso: $0 {update|compare|reset}"
        echo ""
        echo "  update  - Actualizar base de datos después de cambios legítimos"
        echo "  compare - Intentar comparar con backup (manual)"
        echo "  reset   - Reinicializar base de datos (¡PELIGROSO!)"
        ;;
esac
EOF
    chmod +x /usr/local/bin/aide-emergency
    log "Script de emergencia creado: /usr/local/bin/aide-emergency"
}

main() {
    echo "=========================================="
    echo "  AIDE Setup for Web Servers"
    echo "=========================================="
    echo ""
    echo "ADVERTENCIA: Este script configura AIDE para"
    echo "monitoreo de integridad de archivos."
    echo "Asegúrate de tener snapshots antes de continuar."
    echo ""
    echo "¿Continuar? (s/N)"
    read -r confirm
    
    if [[ ! "$confirm" =~ ^[Ss]$ ]]; then
        log "Operación cancelada"
        exit 0
    fi
    
    check_aide_support
    setup_directories
    create_custom_config
    initialize_database
    setup_cron_jobs
    create_status_script
    create_emergency_script
    
    echo ""
    echo "=========================================="
    log "Configuración AIDE completada"
    echo ""
    echo "PRÓXIMOS PASOS:"
    echo "1. Verificar estado con: /usr/local/bin/aide-status"
    echo "2. Ejecutar chequeo manual: sudo aide --config=/etc/aide/aide-web.conf --check"
    echo "3. Revisar logs en: /var/log/aide/"
    echo ""
    echo "IMPORTANTE:"
    echo "- La base de datos debe almacenarse en medio de solo lectura"
    echo "- Configurar notificaciones en /usr/local/bin/aide-check-wrapper.sh"
    echo "- Programar actualizaciones de DB después de actualizaciones del sistema"
    echo "=========================================="
}

main "$@"

Archivo complementario: aide-emergency-fix.sh

#!/bin/bash
# AIDE Emergency Procedures - Usar si hay demasiados falsos positivos

echo "=== AIDE Emergency Tools ==="

case "$1" in
    log-only)
        echo "Cambiando a modo solo-log (sin alertas)..."
        sed -i 's/verbose=5/verbose=1/' /etc/aide/aide-web.conf
        systemctl stop aide-check.timer 2>/dev/null || true
        echo "AIDE configurado para logging mínimo"
        ;;
    restore)
        echo "Restaurando configuración normal..."
        sed -i 's/verbose=1/verbose=5/' /etc/aide/aide-web.conf
        systemctl start aide-check.timer 2>/dev/null || true
        echo "AIDE restaurado"
        ;;
    disable)
        echo "Deshabilitando chequeos automáticos..."
        systemctl disable aide-check.timer 2>/dev/null || true
        systemctl stop aide-check.timer 2>/dev/null || true
        rm -f /etc/cron.d/aide-web-check
        echo "Chequeos automáticos deshabilitados"
        ;;
    *)
        echo "Uso: $0 {log-only|restore|disable}"
        echo ""
        echo "  log-only - Reducir verbosidad temporalmente"
        echo "  restore  - Restaurar configuración normal"
        echo "  disable  - Detener todos los chequeos automáticos"
        ;;
esac

Instrucciones de Uso Rápido

# 1. Preparar entorno (VM recomendada)
sudo apt update && sudo apt install -y aide aide-common

# 2. Ejecutar hardening de GRUB
chmod +x kspp-grub-hardening.sh
sudo ./kspp-grub-hardening.sh

# 3. Configurar AIDE (antes de reiniciar)
chmod +x aide-setup-webserver.sh
sudo ./aide-setup-webserver.sh

# 4. Aplicar seccomp a servicios
chmod +x apply-seccomp.sh
sudo ./apply-seccomp.sh nginx-web-server nginx

# 5. Reiniciar y verificar
sudo reboot
# Después del reinicio:
sudo /usr/local/bin/aide-status
sudo aide --config=/etc/aide/aide-web.conf --check

6. Análisis y Gestión de Entropía

Un sistema criptográficamente seguro depende de la calidad de su generador de números aleatorios (RNG). En entornos virtualizados, la entropía es frecuentemente insuficiente porque las VMs carecen de fuentes de ruido hardware (interrupciones de disco, variaciones térmicas, etc.).

Diagnóstico de entropía

Verifica el estado actual:

 

cat /proc/sys/kernel/random/entropy_avail
# Valor ideal: > 3000
# En VMs recién iniciadas: frecuentemente < 1000

Configuración avanzada

Archivo: /etc/default/haveged

 

DAEMON_ARGS="-w 1024 -v 1"
# -w 1024: Mantener reserva de 1024 bits de entropía
# -v 1: Nivel de verbosidad para logging

Verificación post-implementación

# Monitoreo continuo de entropía
watch -n 1 cat /proc/sys/kernel/random/entropy_avail

# Prueba de calidad del RNG
rngtest -c 1000 < /dev/random

Alternativa: VirtIO-RNG (entornos virtualizados)

Si tu hipervisor lo soporta (KVM/QEMU), utiliza el generador de entropía del host:

 

# Verificar dispositivo virtio-rng
ls /sys/devices/virtual/misc/hw_random/rng_available
# Debe mostrar "virtio_rng.0"

# Configurar como fuente primaria
sudo rngd -r /dev/hwrng

Impacto en el hardening

La baja entropía compromete:

  • Generación de claves SSH/TLS (claves predecibles)
  • ASLR efectivo (direcciones de memoria predecibles)
  • Nonces criptográficos (ataques de repetición)

Con haveged o virtio-rng, garantizamos que el sistema tiene suficiente aleatoriedad para mantener la efectividad de todas las mitigaciones anteriores.


Arquitectura de Defensa en Profundidad

Este manual ha implementado un hardening estructural que opera en múltiples capas:Table

CapaMecanismoProtección
ArranqueParámetros de kernel KSPPInvariantes de seguridad antes del espacio de usuario
MemoriaAleatorización, aislamientoPrevención de corrupción y explotación
RedSysctl hardeningFiltrado estricto y ocultamiento de información
ProcesoSeccomp + CapabilitiesReducción de syscalls y superficie de ataque
IntegridadAIDEDetección de modificaciones no autorizadas
CriptográficaEntropía garantizadaOperaciones seguras de RNG

El resultado es un sistema donde:

  • Un exploit de buffer overflow en Nginx no puede ejecutar shellcode (W^X, seccomp)
  • Un atacante con acceso root deja trazas detectables (AIDE monitoreando binarios críticos)
  • Un proceso comprometido no puede escalar privilegios (kptr_restrict, yama)
  • La ejecución de código arbitrario es prevenida por diseño, no solo por parches
  • Las modificaciones no autorizadas son detectadas y alertadas (AIDE + logging centralizado)

Diferencias Clave: IMA vs AIDE

 

CaracterísticaIMA (Integrity Measurement Architecture)AIDE (Advanced Intrusion Detection Environment)
Nivel de operaciónKernel spaceUser space
VerificaciónEn tiempo real, bloquea ejecuciónPeriódica, detecta post-modificación
Requisitos kernelCONFIG_IMA_APPRAISE, firmas en binariosNinguno especial
Riesgo de bloqueoKernel panic si falta firmaSolo alertas, no bloquea
ComplejidadAlta (MOK, firmas, initramfs)Media (configuración de reglas)
Uso de recursosBajo (integrado en kernel)Moderado (escaneos periódicos)
Detección de rootkitsLimitada (solo binarios firmados)Completa (todos los archivos monitoreados)
Ideal paraSistemas críticos de alta seguridadServidores web, detección de intrusiones
AIDE es más adecuado para entornos donde:
  • Se necesita flexibilidad en la gestión de actualizaciones
  • No se puede arriesgar la disponibilidad del sistema
  • Se requiere detección de cambios en configuraciones, no solo binarios
  • El equipo de seguridad necesita auditoría forense post-incidente
:wq!

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *