
Marco de defensa en tiempo de ejecución del kernel para vulnerabilidades AF_ALG, con rastreo de sockets eBPF, endurecimiento Ansible y un auditor criptográfico para la detección de desviaciones.
Un marco de defensa en tiempo de ejecución del kernel para el subsistema AF_ALG (Address Family Algorithm, familia 38) de Linux. Diseñado para Centros de Operaciones de Seguridad que gestionan flotas empresariales de Linux donde Zero Trust debe extenderse hacia el kernel, no detenerse en el borde de la red.
AF_ALG expone la API criptográfica del kernel al espacio de usuario a través de una interfaz de socket (socket(AF_ALG, SOCK_SEQPACKET, 0)). Fue añadido originalmente para sistemas embebidos sin /dev/crypto y desde entonces ha acumulado una proporción desproporcionada de CVEs del kernel porque presenta código criptográfico en modo kernel a llamadores sin privilegios — un desajuste clásico de superficie de ataque.
En una implementación empresarial típica:
connect(), bind() o DNS no ven nada — el tráfico AF_ALG nunca sale del kernel.Este marco trata cada creación de socket AF_ALG como un evento de alta señal y reduce la superficie que hace explotables esos eventos.
| Principio Zero Trust | Control en este marco |
|---|---|
| Nunca confiar, siempre verificar | Rastreador eBPF registra cada intento de creación de socket AF_ALG con pid/uid/comm |
| Asumir brecha | Auditor criptográfico compara el estado del kernel contra una línea base firmada |
| Privilegio mínimo | systemd RestrictAddressFamilies + limitación de capacidades en unidades gestionadas |
| Microsegmentación (lado kernel) | unprivileged_userns_clone=0 elimina el pivote userns usado por exploits |
| Validación continua | CI valida informes de auditoría contra un esquema versionado en cada cambio |
.
├── ebpf/ Observabilidad en tiempo de ejecución (rastreador BCC + lista de permitidos)
├── ansible/ Configuración como Código (sysctl + drop-ins de systemd)
├── systemd/ Drop-in independiente de systemd para hosts sin Ansible
├── auditor/ Auditor de estado del kernel (Python)
├── schemas/ JSON Schema para la ingesta de informes de auditoría
├── scripts/ Scripts shell auxiliares (verificados por CI)
├── tests/ Pruebas unitarias + fixtures de informes
└── .github/workflows/ CI: shellcheck + validación de esquema JSON + lint
ebpf/af_alg_tracer.py adjunta un kprobe a security_socket_create. La sonda filtra en family == 38 a nivel del programa BPF para que el verificador elimine creaciones de sockets no relacionadas y la sobrecarga por evento se mantenga en nanosegundos. Emite un registro JSON por intento:
{
"@timestamp": "2026-05-02T09:14:11.412041+00:00",
"event": {"category": "kernel", "action": "af_alg_socket_create", "severity": "high"},
"process": {"pid": 1394, "tgid": 1394, "comm": "suspicious_bin"},
"user": {"uid": 1000, "gid": 1000},
"socket": {"family": 38, "family_name": "AF_ALG", "type": 5, "protocol": 0},
"host": {"name": "web-prod-04"}
}
Dirija la salida estándar a Vector, Fluent Bit o journald (vía systemd-cat). Una lista de permitidos por nombre de comm (/etc/af-alg-defense/allow.list) suprime consumidores conocidos y legítimos sin perder la capacidad de detectar desviaciones.
El objetivo del kprobe es el hook LSM, por lo que los eventos se disparan por intención — incluso los intentos que serían denegados por seccomp o RestrictAddressFamilies aún producen un registro. Eso es exactamente lo que un SOC quiere para la línea base de comportamiento.
ansible/roles/af_alg_hardening/ aplica dos capas de endurecimiento:
Drop-in de sysctl (/etc/sysctl.d/90-af-alg-defense.conf):
kernel.unprivileged_userns_clone=0 — elimina el pivote userns usado por la mayoría de las cadenas de escalada AF_ALG.user.max_user_namespaces=0 — defensa en profundidad portable entre distribuciones.Drop-in de systemd (/etc/systemd/system/<unit>.d/50-af-alg-restrict.conf):
Usa RestrictAddressFamilies como lista de permitidos (no lista de denegados). A la unidad se le permiten AF_UNIX AF_INET AF_INET6 AF_NETLINK; cualquier otra familia — AF_ALG incluida — falla con EAFNOSUPPORT porque systemd lo aplica mediante BPF adjunto a cgroups que la aplicación no puede desactivar. El drop-in también elimina CAP_SYS_ADMIN y aplica ProtectKernel* para cerrar las rutas de escalada más comunes.
Aplicar con:
ansible-playbook -i inventory ansible/site.yml --check --diff # vista previa
ansible-playbook -i inventory ansible/site.yml # aplicar
Para hosts sin Ansible, coloque el archivo independiente en su lugar:
sudo ./scripts/deploy_dropin.sh nginx.service
auditor/crypto_auditor.py produce un informe JSON de postura de seguridad inspeccionando:
/proc/crypto — cada cipher / hash / aead registrado, con banderas FIPS y estado de autoprueba./sys/module/ — módulos cargados en el subárbol criptográfico, con banderas de taint y capturas de parámetros./proc/sys/kernel/, /proc/sys/user/ — sysctls que controlan las rutas de ataque AF_ALG./sys/kernel/security/lockdown — modo de bloqueo del kernel.El informe está indexado por IDs de hallazgos estables (FND-001 a FND-005 actualmente) para que las reglas SIEM puedan suprimir hallazgos individuales sin descartar todo el documento. La detección de deriva compara la postura contra una línea base:
sudo ./auditor/crypto_auditor.py --output /var/log/af-alg-defense/today.json
sudo ./auditor/crypto_auditor.py \
--baseline /var/log/af-alg-defense/baseline.json \
--fail-on-drift
El esquema vive en schemas/audit_report.schema.json (Draft 2020-12) y se valida en CI en cada push.
.github/workflows/ci.yml ejecuta cuatro trabajos en cada push y PR:
*.sh y script con shebang.audit_report.schema.json, luego ejecuta el auditor en vivo en el kernel del runner de GH y valida el informe resultante. Los fixtures en tests/fixtures/ también se verifican.ruff check .).Una verificación de esquema fallida bloquea las fusiones, lo que evita que los analizadores SIEM posteriores se rompan por un campo renombrado silenciosamente.
af_alg_socket_create de un comm no incluido en la lista de permitidos — paginar en la primera ocurrencia, no agregar.crypto_modules entre ejecuciones consecutivas del auditor en un host donde la carga de módulos debería estar congelada.hardened=false después de una ejecución del playbook de endurecimiento — indica manipulación manual o deriva de un sistema de configuración paralelo.lockdown transiciona de integrity/confidentiality a none — fuerte indicador de manipulación del estado del kernel.allow.list para consumidores conocidos y legítimos (cryptsetup en el arranque es el habitual).baseline.json firmado.af_alg_systemd_services configurado a una unidad de bajo riesgo. Vigilar errores EAFNOSUPPORT en journald.systemd-analyze security <unit> debería mostrar que la restricción está aplicada.--fail-on-drift y enrutar las salidas no cero a la cola de guardia.af_alg si ya está en uso. La descarga de módulos está fuera de alcance porque los consumidores legítimos en el arranque pueden seguir ejecutándose. Use modprobe.blacklist=af_alg en la línea de comandos del kernel si ha confirmado que nada en el host lo necesita.security_socket_create).uname -r.CAP_BPF (o root) para cargar el rastreador; acceso de lectura a /proc/crypto para el auditor (no se requieren privilegios para leerlo).Apache-2.0. Ver LICENSE.