Home Linux & Systems Cybersecurity Cloud & DevOps Networks & Infrastructure SIEM & Monitoring DFIR & Threat Intel Development & Other All categories Projects About Tools

Implementing a Security Bastion with Kernel Hardening (Grsecurity/Self-Protection) and Memory Encryption on Linux

Leer en espanol
Implementing a Security Bastion with Kernel Hardening (Grsecurity/Self-Protection) and Memory Encryption on Linux

Table of contents

Most hardening guides remain on the surface: configure firewalls, harden SSH, disable unnecessary services. They are measurements ===

1. Introduction: The Kernel Attack Surface

Most hardening guides remain on the surface: configure firewalls, harden SSH, disable unnecessary services. They are necessary but insufficient measures. A sophisticated adversary does not attack your iptables rules; attacks the Kernel Space, where the absolute privileges of the system reside.

He Kernel Self-Protection Project (KSPP) represents a paradigm shift: instead of relying exclusively on external mechanisms (antivirus, IDS), we reconfigure the Linux kernel itself to be resilient by design against memory exploitation, privilege escalation, and arbitrary code execution.

This manual does not use third-party tools. We are going to modify how the kernel manages memory, system calls and process execution. The goal: create a system immune to entire classes of vulnerabilities, including zero-day exploits that have not yet been discovered.

2. KSPP Implementation: Bootloader Configuration

Boot parameters are the first line of defense. These settings are applied before the operating system fully loads, establishing safety invariants that no user process can override.

Action: Modify GRUB parameters

Edit /etc/default/grub and modify the line GRUB_CMDLINE_LINUX_DEFAULT:
CODE
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"

Analysis of critical parameters

 
ParameterProtection MechanismMitigated Attack Vector
slab_nomergePrevents the kernel from merging object caches of different sizesHeap overflow attacks that depend on manipulating adjacent caches
page_alloc.shuffle=1Randomize memory page allocationMemory address prediction attacks (ASLR bypass)
vsyscall=noneDisable vsyscall legacy emulationROP (Return-Oriented Programming) gadgets in fixed memory
init_on_alloc=1Initializes all allocated memory to zeroUsing previous kernel residual data (information leaks)
init_on_free=1Overwrite freed memory before reallocatingUse-after-free exploits
pti=onIsolates kernel and user page tablesMeltdown and kernel memory read attacks from userland
spectre_v2=onEnable branch target injection mitigationsSpecter v2 (Branch Target Injection)
spec_store_bypass_disable=seccompProtection against Speculative Store BypassVariant 4 of speculative attacks
l1tf=fullComplete mitigation against L1 Terminal FaultL1TF (Foreshadow)
mds=full,nosmtProtection against Microarchitectural Data SamplingRIDL, Fallout, ZombieLoad
tsx=offDisable Intel TSX (Transactional Synchronization Extensions)TAA (TSX Asynchronous Abort)
kvm.nx_huge_pages=forceForce No-Execute on hypervisor huge pagesMemory corruption attacks in virtualized environments

Apply changes:

CODE
sysctl --system

Apply grub changes

BASH
sudo update-grub
sudo reboot

Note for virtualized environments: These parameters work on both bare-metal hardware and VMs (KVM, VMware, VirtualBox). The hypervisor emulates hardware protections, allowing you to test extreme security configurations without risk to the host system.

3. Network Stack Hardening: Advanced Sysctl

Standard network configurations focus on performance. Here we prioritize resource integrity and the spoofing prevention at the kernel level.

Settings /etc/sysctl.d/99-security.conf

CODE
# === 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

Technical explanation of key parameters

kernel.kptr_restrict = 2: Hides kernel symbol memory addresses even from the root user. Privilege escalation exploits often require knowing specific kernel addresses to build ROP gadgets. With this configuration, /proc/kallsyms sample 0000000000000000 for all kernel symbols.
kernel.yama.ptrace_scope = 2: Limits the use of ptrace (debugging tool) only to processes with CAP_SYS_PTRACE capability. This blocks common code injection and credential dumping techniques from compromised processes.
vm.unprivileged_userfaultfd = 0: Disable userfaultfd for non-privileged users. This syscall has been exploited in multiple vulnerabilities (such as the DirtyPipe exploit chain) to manipulate kernel memory management.

Settings application

 
BASH
sudo sysctl --system

4. Execution Control: Seccomp and Capabilities

Traditional security is based on user and file permissions. Expert security is based on kernel capabilities and system call filters.

Concept: Reduction of attack surface by syscall

A compromised process can only execute the syscalls that the kernel allows it to. If we eliminate execve, the process cannot launch new programs. If we eliminate openat, you cannot open arbitrary files.

Practice: Seccomp Profile for Nginx

We created a profile that allows Nginx to operate normally but blocks any attempts to execute additional code after boot.
Archive: /etc/nginx/seccomp-bpf.json
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"
    }
  ]
}

Integration with Systemd

Modify the Nginx service (/etc/systemd/system/nginx.service.d/override.conf):
CODE
[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

Protection analysis

  • SystemCallFilter=@system-service: Uses the predefined set of safe syscalls for system services.
  • NoNewPrivileges=true: Prevents the process from gaining additional privileges (blocks setuid binaries).
  • ProtectSystem=strict: Mounts the root file system as read-only and inaccessible to the service.
  • MemoryDenyWriteExecute=true: Enables W^X (Write XOR Execute), preventing memory from being simultaneously writable and executable (anti-shellcode mitigation).
Recharge and restart:
BASH
sudo systemctl daemon-reload
sudo systemctl restart nginx

Example of Seccomp-BPF templates for Common Services

Create directory and file

BASH
sudo mkdir -p /etc/seccomp
sudo vi /etc/seccomp/profiles.json
Archive: /etc/seccomp/profiles.json (format supported by Docker, containerd, systemd and runc)
 
JSON
{
  "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"
        }
      ]
    }
  }
}
Application script for systemd:
 

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

BASH
#!/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"

We give permissions and execute the script

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

We verify that the service

CODE
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"

How to modify Script for New Service

Add case in apply-seccomp.sh:

BASH
#!/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"

Exception Management

When a Service Fails

Step 1: Check specific error

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

Step 2: Identify type of error

MistakeCauseSolution
Read-only file systemMissing directory in ReadWritePathsAdd route
No such file or directory + NAMESPACEDirectory does not existmkdir -p before
Operation not permittedSyscall blockedReview SystemCallFilter
Permission deniedInsufficient capabilitiesAdjust CapabilityBoundingSet
Step 3: Modify settings
Edit /etc/systemd/system/SERVICIO.service.d/seccomp.conf:
CODE
[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

Step 4: Recharge and restart

CODE
systemctl daemon-reload
systemctl restart SERVICIO

Practical Examples

MySQL/MariaDB

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

Typical exceptions:

  • /var/lib/mysql - Data
  • /var/log/mysql – Logs
  • /var/run/mysqld –Socket
  • /tmp – Temporary

Additional Capability:

CODE
CapabilityBoundingSet=CAP_IPC_LOCK  # Para bloquear memoria con mlock

PostgreSQL

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

Redis

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

Exceptions:

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

Function Verification

BASH
# 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"
BASH
grep -E "CONFIG_IMA|CONFIG_IMA_APPRAISE|CONFIG_IMA_KEYRINGS_PERMIT_SIGNED_BY_BUILTIN_OR_SECONDARY" /boot/config-$(uname -r)

5. Integrity Audit: AIDE (Advanced Intrusion Detection Environment)

AIDE is an intrusion detection system that creates a file integrity database and periodically checks whether unauthorized changes have occurred. Unlike IMA, AIDE operates in user space, providing an additional layer of post-compromise detection without modifying the kernel or requiring real-time cryptographic signatures.

Root of Trust Requirements

For AIDE to be effective in a professional environment, it must be anchored to external controls:
  • Secure storage: AIDE database should be saved on read-only media or immutable remote file system
  • Kernel hardening: KSPP protections prevent AIDE modification at runtime
  • Monitoring: Integration with SIEM for real-time alerts of critical modifications

Support Verification and Installation

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

# Verificar instalación
aide --version

AIDE Configuration

Archive: /etc/aide/aide.conf
CODE
# === 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

Database Initialization

 
BASH
# 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/

Verification and Manual Checks

 
BASH
# 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

Automation with Cron

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

SQL
# 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

Integration with Systemd for Real-Time Alerts

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

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

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

[Timer]
OnCalendar=hourly
Persistent=true

[Install]
WantedBy=timers.target

Activate timer:

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

GRUB Configuration with AIDE Support

Since AIDE operates in user space, it does not require special kernel parameters. However, we maintain the KSPP hardening:

CODE
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"
Update and restart:
 
BASH
sudo update-grub
sudo reboot

Function Verification

 
BASH
# 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

Automated Configuration Script for Web Servers

Archive: aide-setup-webserver.sh

BASH
#!/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 "$@"

Supplementary file: aide-emergency-fix.sh

BASH
#!/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

Quick Use Instructions

BASH
# 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. Entropy Analysis and Management

A cryptographically secure system depends on the quality of its random number generator (RNG). In virtualized environments, entropy is frequently insufficient because VMs lack sources of hardware noise (disk interrupts, thermal variations, etc.).

Entropy diagnosis

Check the current status:

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

Advanced settings

Archive: /etc/default/haveged

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

Post-implementation verification

CODE
# 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

Alternative: VirtIO-RNG (virtualized environments)

If your hypervisor supports it (KVM/QEMU), use the host entropy generator:

BASH
# 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

Impact on hardening

Low entropy compromises:

  • SSH/TLS key generation (predictable keys)
  • Effective ASLR (predictable memory addresses)
  • Crypto nonces (replay attacks)

With haveged or virtio-rng, we guarantee that the system has enough randomness to maintain the effectiveness of all previous mitigations.


Defense in Depth Architecture

This manual has implemented structural hardening that operates on multiple layers:Table

LayerMechanismProtection
BootKSPP kernel parametersSecurity invariants before user space
MemoryRandomization, isolationPrevention of corruption and exploitation
GridSysctl hardeningStrict filtering and information hiding
ProcessSeccomp + CapabilitiesReduction of syscalls and attack surface
IntegrityAIDEDetection of unauthorized modifications
CryptographicGuaranteed entropySecure RNG Operations

The result is a system where:

  • Nginx buffer overflow exploit fails to execute shellcode (W^X, seccomp)
  • An attacker with root access leaves detectable traces (AIDE monitoring critical binaries)
  • A compromised process cannot escalate privileges (kptr_restrict, yama)
  • Arbitrary code execution is prevented by design, not just patches
  • Unauthorized modifications are detected and alerted (AIDE + centralized logging)

Key Differences: IMA vs AIDE

FeatureIMA (Integrity Measurement Architecture)AIDE (Advanced Intrusion Detection Environment)
Operation levelKernel spaceUser space
VerificationIn real time, blocks executionPeriodic, detects post-modification
Kernel requirementsCONFIG_IMA_APPRAISE, signatures in binariesNone special
Blockage riskKernel panic if signature is missingAlerts only, no blocking
ComplexityRegistration (MOK, signatures, initramfs)Average (rules settings)
Resource usageLow (built into kernel)Moderate (periodic scans)
Rootkit detectionLimited (signed binaries only)Complete (all files monitored)
Ideal forHigh security critical systemsWeb servers, intrusion detection
AIDE is best suited for environments where:
  • Flexibility needed in update management
  • You cannot risk system availability
  • Change detection is required in configurations, not just binaries
  • Security team needs post-incident forensic audit
CODE
:wq!

Comments