
Mitigation basée sur Seccomp pour CVE-2026-31431, une LPE du noyau Linux. Bloque la socket AF_ALG via un module PAM et un wrapper autonome, avec détection automatique des noyaux corrigés.
Une atténuation légère et réversible basée sur seccomp pour CVE-2026-31431, une vulnérabilité d'élévation de privilèges locale dans le sous-système crypto algif_aead / authencesn du noyau Linux.
Type : Élévation de privilèges locale (LPE)
Composant affecté : crypto/algif_aead.c du noyau Linux - opération AEAD en place
Primitive d'attaque : Une écriture contrôlable de 4 octets dans le cache de pages de tout fichier lisible via le chemin d'écriture scratch de l'algorithme AEAD authencesn. En ciblant /etc/passwd, un attaquant peut modifier son UID en 0 (root) et obtenir un shell root via su.
Confirmé sur les noyaux 6.12+, 6.17+, 6.18+, et également reproduit sur les noyaux RHEL/CentOS 4.18/5.14.
Environnements vérifiés : Rocky Linux 8 (noyau 4.18) et Rocky Linux 9 (noyau 5.14) - exploit entièrement bloqué, suppression sûre confirmée.
Cause racine : Le commit 72548b093ee3 a introduit l'opération AEAD en place. Lorsque des pages du cache de pages épissées sont utilisées comme liste de scatter-gather de destination, le champ AAD seqno_lo est incorrectement réécrit dans le cache de pages lors du déchiffrement AEAD.
Correctif en amont : Revenir à l'opération AEAD hors place.
Cette solution comporte deux composants :
Module PAM (pam_block_afalg.so) - La défense principale. Chargé par PAM lors de l'ouverture de session (pam_sm_open_session), il applique un filtre BPF seccomp qui bloque socket(AF_ALG, ...) avant que tout code utilisateur ne s'exécute. Cela couvre TOUTES les sessions authentifiées par PAM : su -c, su -, SSH, connexion TTY, etc.
Binaire autonome (block_afalg) - Optionnel. Peut encapsuler des programmes spécifiques pour les scénarios non-PAM (par exemple, tâches cron, services systemd, invocation manuelle).
Le filtre seccomp :
socket(AF_ALG, ...) (retourne EACCES)setuid, su, sudo)Ouverture de session PAM (su, ssh, login, etc.)
|
v
pam_block_afalg.so (pam_sm_open_session)
|
+-- Vérification : le noyau est-il vulnérable ? (essayer socket(AF_ALG))
| |
| +-- Non --> retourner PAM_SUCCESS (sans effet)
| |
| +-- Oui --> prctl(PR_SET_SECCOMP, filtre BPF)
| |
| +-- filtre seccomp actif sur le processus enfant sshd
| +-- hérité par le shell de l'utilisateur et TOUS les processus enfants
| +-- socket(AF_ALG, ...) retourne EACCES
v
Le shell / la commande de l'utilisateur s'exécute avec la protection seccomp
|
+-- su, sudo et tous les autres appels système fonctionnent normalement
+-- Seul le socket AF_ALG est bloqué
| Fichier | Objectif |
|---|---|
pam_block_afalg.c | Source du module PAM. Applique le filtre seccomp à l'ouverture de session. |
pam_minimal.h | Définitions minimales des types PAM (compilation sans pam-devel). |
block_afalg.c | Binaire autonome d'encapsulation seccomp. Pour une utilisation non-PAM. |
deploy.sh | Script de déploiement. Compile, installe et gère le module PAM. |
gcc (pour la compilation)libpam (exécution, généralement préinstallé)# 1. Compiler le module PAM
gcc -Wall -O2 -fPIC -shared -o pam_block_afalg.so pam_block_afalg.c \
/usr/lib64/libpam.so.0
# 2. Installer (ajoute automatiquement les configurations PAM à su, sshd, login)
sudo ./deploy.sh install
# 3. Vérifier (doit être une NOUVELLE session)
cat /proc/self/status | grep Seccomp
# Devrait afficher : Seccomp: 2
python3 -c "
import socket
try:
s = socket.socket(38,2,0); s.close()
print('VULNERABLE')
except OSError:
print('BLOQUÉ')
"
# Devrait afficher : BLOQUÉ
# 4. Désinstaller
sudo ./deploy.sh remove
| Commande | Description |
|---|---|
deploy.sh install | Compiler le module PAM, l'installer dans /lib64/security/, ajouter automatiquement les configurations PAM |
deploy.sh remove | Désinstallation complète : supprimer le module, nettoyer les configurations PAM, supprimer les fichiers |
deploy.sh status | Afficher l'état de l'installation, les configurations PAM, l'état du noyau |
Pour les scénarios non-PAM, utilisez block_afalg directement :
# Compiler
gcc -Wall -O2 -o block_afalg block_afalg.c
# Exécuter une commande avec AF_ALG bloqué
./block_afalg python3 votre_script.py
./block_afalg bash
python3 -c "
import socket
try:
s = socket.socket(38, socket.SOCK_SEQPACKET, 0)
s.close()
print('VULNÉRABLE : socket AF_ALG disponible')
except:
print('SÛR : socket AF_ALG bloqué ou indisponible')
"
# Vérifier l'état seccomp
cat /proc/self/status | grep Seccomp
# Seccomp: 0 = non protégé
# Seccomp: 2 = protégé
# Tester le socket AF_ALG
python3 -c "
import socket
try:
s = socket.socket(38,2,0)
s.close()
print('AF_ALG disponible - NON protégé')
except OSError:
print('AF_ALG bloqué - PROTÉGÉ')
"
# Vérifier les journaux PAM
grep pam_block_afalg /var/log/secure
# Devrait afficher : filtre seccomp appliqué, AF_ALG bloqué
__NR_socket sur x86_64). Les autres architectures nécessitent une mise à jour du numéro d'appel système.exec() directs sans PAM ne sont pas couverts (utilisez block_afalg pour ceux-ci).remove.yum update kernel puis supprimez le module.Cet outil est fourni uniquement à des fins de tests de sécurité autorisés et de défense. Utilisez-le uniquement sur des systèmes que vous possédez ou que vous êtes explicitement autorisé à évaluer.