
Framework de défense au niveau du noyau pour les vulnérabilités AF_ALG, doté d'un traçage de sockets eBPF, d'un durcissement Ansible et d'un auditeur cryptographique pour la détection de dérives.
Un framework de défense au niveau du noyau pour le sous-système AF_ALG (Address Family Algorithm, famille 38) de Linux. Conçu pour les centres d'opérations de sécurité (SOC) gérant des parcs Linux d'entreprise où le Zero Trust doit s'étendre dans le noyau, et non s'arrêter à la périphérie du réseau.
AF_ALG expose l'API crypto du noyau à l'espace utilisateur via une interface socket (socket(AF_ALG, SOCK_SEQPACKET, 0)). Il a été initialement ajouté pour les systèmes embarqués sans /dev/crypto et a depuis accumulé une part disproportionnée de CVE du noyau, car il présente du code crypto en mode noyau à des appelants non privilégiés — un déséquilibre classique de surface d'attaque.
Dans une configuration d'entreprise typique :
connect(), bind() ou le DNS ne voient rien — le trafic AF_ALG ne quitte jamais le noyau.Ce framework traite chaque création de socket AF_ALG comme un événement à forte valeur de signal et réduit la surface qui rend ces événements exploitables.
| Principe Zero Trust | Contrôle dans ce framework |
|---|---|
| Ne jamais faire confiance, toujours vérifier | Traceur eBPF journalise chaque tentative de création de socket AF_ALG avec pid/uid/comm |
| Présumer la compromission | Auditeur crypto compare l'état du noyau à une référence signée |
| Moindre privilège | RestrictAddressFamilies systemd + plafonnement des capacités sur les unités gérées |
| Microsegmentation (côté noyau) | unprivileged_userns_clone=0 supprime le pivot userns utilisé par les exploits |
| Validation continue | CI valide les rapports d'audit par rapport à un schéma versionné à chaque modification |
.
├── ebpf/ Observabilité runtime (traceur BCC + liste d'autorisation)
├── ansible/ Configuration en tant que code (sysctl + drop-ins systemd)
├── systemd/ Drop-in systemd autonome pour les hôtes sans Ansible
├── auditor/ Auditeur d'état du noyau (Python)
├── schemas/ Schémas JSON pour l'ingestion des rapports d'audit
├── scripts/ Scripts shell d'assistance (vérifiés par CI)
├── tests/ Tests unitaires + fixtures de rapports
└── .github/workflows/ CI : shellcheck + validation de schéma JSON + lint
ebpf/af_alg_tracer.py attache un kprobe à security_socket_create. La sonde filtre sur family == 38 au niveau du programme BPF afin que le vérificateur élague les créations de sockets non liées et que la surcharge par événement reste de l'ordre de la nanoseconde. Elle émet un enregistrement JSON par tentative :
{
"@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"}
}
Redirigez la sortie standard vers Vector, Fluent Bit ou journald (via systemd-cat). Une liste d'autorisation de noms de commandes (/etc/af-alg-defense/allow.list) supprime les consommateurs connus et légitimes sans perdre la capacité de détecter les écarts.
La cible du kprobe est le hook LSM, donc les événements se déclenchent sur l'intention — même les tentatives qui seraient refusées par seccomp ou RestrictAddressFamilies produisent un enregistrement. C'est exactement ce qu'un SOC souhaite pour l'établissement de références comportementales.
ansible/roles/af_alg_hardening/ applique deux couches de durcissement :
Drop-in sysctl (/etc/sysctl.d/90-af-alg-defense.conf) :
kernel.unprivileged_userns_clone=0 — supprime le pivot userns utilisé par la plupart des chaînes d'escalade AF_ALG.user.max_user_namespaces=0 — défense en profondeur portable entre distributions.Drop-in systemd (/etc/systemd/system/<unit>.d/50-af-alg-restrict.conf) :
Utilise RestrictAddressFamilies comme liste d'autorisation (et non liste de refus). L'unité est autorisée pour AF_UNIX AF_INET AF_INET6 AF_NETLINK ; toute autre famille — AF_ALG inclus — échoue avec EAFNOSUPPORT car systemd l'applique via un BPF attaché au cgroup que l'application ne peut pas désactiver. Le drop-in retire également CAP_SYS_ADMIN et applique ProtectKernel* pour fermer les chemins d'escalade les plus courants.
Application :
ansible-playbook -i inventory ansible/site.yml --check --diff # aperçu
ansible-playbook -i inventory ansible/site.yml # application
Pour les hôtes sans Ansible, placez le fichier autonome directement :
sudo ./scripts/deploy_dropin.sh nginx.service
auditor/crypto_auditor.py produit un rapport JSON de posture de sécurité en inspectant :
/proc/crypto — chaque chiffrement / hachage / aead enregistré, avec les indicateurs FIPS et l'état d'auto-test./sys/module/ — modules chargés dans le sous-arbre crypto, avec indicateurs de taint et instantanés de paramètres./proc/sys/kernel/, /proc/sys/user/ — sysctls qui contrôlent les chemins d'attaque AF_ALG./sys/kernel/security/lockdown — mode de verrouillage du noyau.Le rapport est indexé par des identifiants de constatation stables (FND-001 à FND-005 actuellement) afin que les règles SIEM puissent supprimer des constatations individuelles sans abandonner l'intégralité du document. La détection de dérive compare la posture à une référence :
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
Le schéma se trouve dans schemas/audit_report.schema.json (Draft 2020-12) et est validé en CI à chaque push.
.github/workflows/ci.yml exécute quatre tâches à chaque push et PR :
*.sh et script avec shebang.audit_report.schema.json, puis exécute l'auditeur en direct sur le noyau du runner GH et valide le rapport résultant. Les fixtures dans tests/fixtures/ sont également vérifiées.ruff check .).Un échec de validation de schéma bloque les fusions, ce qui empêche les analyseurs SIEM en aval de se casser sur un champ renommé silencieusement.
af_alg_socket_create provenant d'une commande non autorisée — pagez dès la première occurrence, ne regroupez pas.crypto_modules entre deux exécutions consécutives de l'auditeur sur un hôte où le chargement de modules devrait être figé.hardened=false après une exécution du playbook de durcissement — indique une altération manuelle ou une dérive d'un système de configuration parallèle.lockdown qui passe de integrity/confidentiality à none — indicateur fort d'altération de l'état du noyau.allow.list avec les consommateurs connus et légitimes (cryptsetup au démarrage est le cas habituel).baseline.json signé.af_alg_systemd_services défini sur une unité à faible risque. Surveillez les erreurs EAFNOSUPPORT dans journald.systemd-analyze security <unit> doit montrer que la restriction est appliquée.--fail-on-drift et routez les sorties non nulles vers la file d'astreinte.af_alg s'il est déjà utilisé. Le déchargement de modules est hors périmètre car des consommateurs légitimes au démarrage peuvent encore être actifs. Utilisez modprobe.blacklist=af_alg sur la ligne de commande du noyau si vous avez confirmé que rien sur l'hôte n'en a besoin.security_socket_create).uname -r.CAP_BPF (ou root) pour charger le traceur ; accès en lecture à /proc/crypto pour l'auditeur (aucun privilège requis pour le lire).Apache-2.0. Voir LICENSE.