Hardening granular con fapolicyd
Qué es fapolicyd
fapolicyd (File Access Policy Daemon) es un framework de seguridad para Linux diseñado para controlar la ejecución de aplicaciones basándose en una "lista de confianza".
A diferencia de los antivirus tradicionales que buscan firmas de malware conocido, fapolicyd opera bajo un modelo de Zero Trust: si un binario o script no está explícitamente permitido en la base de datos de confianza, el kernel bloquea su ejecución.
Utiliza el subsistema fanotify del kernel para interceptar llamadas al sistema relacionadas con la apertura y ejecución de archivos.
Funcionamiento Técnico
El demonio actúa como un guardián entre el espacio de usuario y el kernel.
El flujo de proceso y decisión sigue los siguientes pasos:
- Intercepción: Cuando un proceso intenta ejecutar un archivo (vía
execve) o abrirlo para lectura (si es un script), el kernel envía un evento a través de fanotify afapolicyd. - Identificación: fapolicyd obtiene los metadatos del archivo: ruta, UID, GID y, lo más importante, el hash (SHA-256) del contenido.
- Evaluación de Reglas: Compara estos metadatos contra sus bases de datos de confianza (generalmente la base de datos de RedHat (RPM) y de Debian (DEB) del sistema y los archivos de configuración locales.
- Decisión:
- Allow: Envía una señal al kernel para permitir la operación.
- Deny: Envía una señal de bloqueo y el usuario recibe un error de "Permiso denegado".
Configuración y Políticas
El archivo fapolicyd.conf
Un parámetro técnico vital es el integrity.
En él se define cómo de estricta es la validación:
- none: Solo verifica la ruta del archivo.
- size: Verifica ruta y tamaño.
- sha256: Verifica que el hash del archivo coincida con el registrado (máxima seguridad).
Gestión de Reglas (fapolicyd.rules)
- Las reglas se leen en orden secuencial.
- Si una regla coincide, se detiene la búsqueda.
- Formato de las reglas es:
decisión objeto sujeto : filtro de objeto
Configuración en Debian versus RedHat
Configurar fapolicyd en Debian es un proceso similar al de RHEL, pero con matices técnicos importantes, ya que Debian usa dpkg en lugar de rpm.
El demonio tiene que estar configurado para confiar en la base de datos de paquetes de Debian para no bloquear el sistema operativo base.
Vemos a nivel técnico que hay que ajustar para que fapolicyd funcione en servidores Debian.
1. Instalación y Preparación en Debian
A partir de la versión 11 de Debian el paquete apareció ya disponible en los repositorios oficiales.
sudo apt update
sudo apt -y install fapolicyd
Configuración del origen de confianza (Trust Source)
Hay que asegurarse de que fapolicyd reconozca los paquetes instalados vía apt.
Editaremos el archivo /etc/fapolicyd/fapolicyd.conf, buscaremos la línea de trust y nos aseguramos que incluya debian:
...
trust = debian, file
...
Que indicamos con esto:
- debian: Lee la base de datos de
/var/lib/dpkg/status - file: Permite añadir archivos manuales a
/etc/fapolicyd/fapolicyd.trust
2. Configuración de las Reglas (.rules)
En Debian, las reglas se gestionan en /etc/fapolicyd/rules.d/.
El orden de los archivos (01-..., 10-..., 95-...) determina la prioridad.
Ejemplo: Bloquear la ejecución en las rutas /home y /tmp
Esta es una de las configuraciones más comunes para endurecer (hardening) un servidor.
Creamos el fichero /etc/fapolicyd/rules.d/20-block-user-paths.rules:
# Bloquear ejecución en las carpetas de los usuarios
deny_audit perm=execute all : dir=/home/
deny_audit perm=execute all : dir=/tmp/
deny_audit perm=execute all : dir=/var/tmp/
Ejemplo: Permitir ejecutar un script específico de Python
Si tenemos un script en /opt/scripts/backup.py, fapolicyd podría bloquear el intérprete de Python al intentar leerlo.
Para permitirlo creamos una regla en /etc/fapolicyd/rules.d/30-python-scripts.rules:
# Permitir que python3 ejecute solo este script (hardening por Hash)
allow perm=any all : path=/usr/bin/python3.13 trust=1
allow perm=open all : path=/opt/scripts/backup.py ftype=text/x-python sha256hash=e3b0c442...
3. Gestionar la Lista de Confianza (Método Manual)
Si descargamos un binario (por ejemplo, terraform o kubectl) que no viene de un .deb, tendremos que marcarlo como "de confianza" de forma manual.
Paso 1: Agregar el archivo
# Registrar manualmente un binario específico
sudo fapolicyd-cli --file add /usr/local/bin/mi-binario --trust-domain local-admin
Paso 2: Actualizar y Reiniciar
A diferencia de otras distros, en Debian es una buena práctica forzar la regeneración de la base de datos de fapolicyd:
sudo fapolicyd-cli --update
sudo systemctl restart fapolicyd
4. Comandos para Diagnóstico y Auditorías
Si algo no funciona en tu servidor Debian después de activar fapolicyd, puedes revisar lo que sucede con los siguientes comandos:
Averiguar qué regla bloqueó un proceso
# Localizar eventos en tiempo real (usando modo Debug)
sudo fapolicyd --debug --nodetach 2>&1 | grep "rule="
Revisar el log de Auditoría (Essential)
Recuerda que Debian usa auditd.
Si no lo tienes hay que instálalo mediante: sudo apt -y install auditd
Despues ya podemos localizar las denegaciones que se pueden estar realizando (denegaciones de fanotify):
sudo ausearch -m FANOTIFY -ts today
Comprobar la integridad de la base de datos
# Comprobar si hay algun tipo de discrepancia entre los ficheros y al base de datos de fapolicyd
sudo fapolicyd-cli --check-config
sudo fapolicyd-cli --check-db
5. Tabla Resumen de un Flujo de Decisiones de fapolicyd
Un ejemplo en formato tabla de lo que sucede con las acciones de un usuario, cuando usamos fapolicyd:
| Acción del Usuario | Estado en DPKG | Regla Local | Resultado |
apt install vim | Sí | N/A | Permitido (Vía trust=debian) |
./malware.sh | No | No | Bloqueado (Default deny) |
python3 script.py | Intérprete Sí | Script No | Bloqueado (Si ftype está activo) |
/opt/app/bin | No | allow...path=/opt/app | Permitido (Regla personalizada) |
Explicación detallada sobre el formato de las reglas
El formato de las reglas en fapolicyd es una expresión lineal que define quién, cómo y sobre qué se aplica una política.
Estas reglas se almacenan en archivos .rules dentro de /etc/fapolicyd/rules.d/ y se compilan en un único conjunto de reglas siguiendo el orden numérico de los nombres de los archivos.
La estructura general de una regla es: decisión permiso sujeto : objeto
Explicación de cada parte de la regla
A. Decisión (decision)
Define qué hacer cuando se encuentra una coincidencia:
- allow: Permite el acceso y detiene la evaluación de más reglas.
- deny: Deniega el acceso y detiene la evaluación. El usuario recibe "Permission Denied".
- allow_audit: Permite el acceso y genera un evento en el log de auditoría (
auditd). - deny_audit: Deniega el acceso y genera un evento en el log de auditoría (Recomendado para debugging).
- allow_syslog: Permite y escribe en syslog.
- deny_syslog: Deniega y escribe en syslog.
B. Permiso (perm)
Define la operación que se intenta realizar:
- open: Abrir un archivo (común para scripts o librerías).
- execute: Ejecutar un archivo binario.
- any: Cualquier operación (open o execute).
C. Sujeto (subject)
Define quién realiza la acción. Se puede filtrar por:
- all: Cualquier proceso en el sistema.
- auid: ID de usuario de auditoría (el usuario original que inició sesión).
- uid: ID de usuario efectivo.
- gid: ID de grupo.
- sessionid: ID de la sesión de login.
- comm: Nombre del comando/ejecutable del proceso.
D. Objeto (object)
Define sobre qué se actúa.
Se separa del sujeto por dos puntos (:).
- all: Cualquier archivo.
- path: Ruta absoluta al archivo (ej.
/usr/bin/ls). - dir: Directorio completo (ej.
/tmp/). - device: Identificador de dispositivo (major/minor).
- ftype: Tipo MIME del archivo (ej.
application/x-sharedlib). - trust: Nivel de confianza.
1significa que está en la base de datos de confianza (DPKG en Debian),0que no. - sha256hash: El hash específico del archivo para validación de integridad.