
Mitigación basada en Seccomp para CVE-2026-31431, un LPE del kernel de Linux. Bloquea el socket AF_ALG mediante un módulo PAM y un envoltorio independiente, con detección automática de kernels parcheados.
Una mitigación ligera y reversible basada en seccomp para CVE-2026-31431, una vulnerabilidad de escalada de privilegios local en el subsistema criptográfico algif_aead / authencesn del kernel de Linux.
Tipo: Escalada de privilegios local (LPE)
Componente afectado: crypto/algif_aead.c del kernel de Linux - operación AEAD in-place
Primitiva de ataque: Una escritura controlable de 4 bytes en la caché de páginas de cualquier archivo legible a través de la ruta de escritura temporal del algoritmo AEAD authencesn. Al apuntar a /etc/passwd, un atacante puede cambiar su UID a 0 (root) y obtener una shell root mediante su.
Kernels afectados: Confirmado en kernels 6.12+, 6.17+, 6.18+, y también reproducido en kernels RHEL/CentOS 4.18/5.14.
Entornos verificados: Rocky Linux 8 (kernel 4.18) y Rocky Linux 9 (kernel 5.14) - exploit completamente bloqueado, eliminación segura confirmada.
Causa raíz: El commit 72548b093ee3 introdujo la operación AEAD in-place. Cuando las páginas de caché empalmadas se usan como scatterlist de destino, el campo AAD seqno_lo se escribe incorrectamente de vuelta en la caché de páginas durante el descifrado AEAD.
Corrección upstream: Revertir a la operación AEAD out-of-place.
Esta solución tiene dos componentes:
Módulo PAM (pam_block_afalg.so) - La defensa principal. Cargado por PAM durante la apertura de sesión (pam_sm_open_session), aplica un filtro BPF seccomp que bloquea socket(AF_ALG, ...) antes de que se ejecute cualquier código de usuario. Esto cubre TODAS las sesiones autenticadas por PAM: su -c, su -, SSH, inicio de sesión TTY, etc.
Binario independiente (block_afalg) - Opcional. Puede envolver programas específicos para escenarios sin PAM (por ejemplo, trabajos cron, servicios systemd, invocación manual).
El filtro seccomp:
socket(AF_ALG, ...) (devuelve EACCES)setuid, su, sudo)Apertura de sesión PAM (su, ssh, login, etc.)
|
v
pam_block_afalg.so (pam_sm_open_session)
|
+-- Verificar: ¿es vulnerable el kernel? (probar socket(AF_ALG))
| |
| +-- No --> devolver PAM_SUCCESS (no-op)
| |
| +-- Sí --> prctl(PR_SET_SECCOMP, filtro BPF)
| |
| +-- filtro seccomp activo en el proceso hijo de sshd
| +-- heredado por la shell del usuario y TODOS los procesos hijos
| +-- socket(AF_ALG, ...) devuelve EACCES
v
La shell / comando del usuario se ejecuta con protección seccomp
|
+-- su, sudo y todas las demás llamadas al sistema funcionan normalmente
+-- Solo se bloquea el socket AF_ALG
| Archivo | Propósito |
|---|---|
pam_block_afalg.c | Código fuente del módulo PAM. Aplica el filtro seccomp en la apertura de sesión. |
pam_minimal.h | Definiciones mínimas de tipos PAM (compila sin pam-devel). |
block_afalg.c | Binario independiente de envoltura seccomp. Para uso sin PAM. |
deploy.sh | Script de despliegue. Compila, instala y gestiona el módulo PAM. |
gcc (para compilación)libpam (en tiempo de ejecución, normalmente preinstalado)# 1. Compilar el módulo PAM
gcc -Wall -O2 -fPIC -shared -o pam_block_afalg.so pam_block_afalg.c \
/usr/lib64/libpam.so.0
# 2. Instalar (añade automáticamente configuraciones PAM a su, sshd, login)
sudo ./deploy.sh install
# 3. Verificar (debe ser una sesión NUEVA)
cat /proc/self/status | grep Seccomp
# Debe mostrar: Seccomp: 2
python3 -c "
import socket
try:
s = socket.socket(38,2,0); s.close()
print('VULNERABLE')
except OSError:
print('BLOQUEADO')
"
# Debe mostrar: BLOQUEADO
# 4. Desinstalar
sudo ./deploy.sh remove
| Comando | Descripción |
|---|---|
deploy.sh install | Compilar el módulo PAM, instalar en /lib64/security/, añadir configuraciones PAM automáticamente |
deploy.sh remove | Desinstalación completa: eliminar módulo, limpiar configuraciones PAM, borrar archivos |
deploy.sh status | Mostrar estado de instalación, configuraciones PAM, estado del kernel |
Para escenarios sin PAM, use block_afalg directamente:
# Compilar
gcc -Wall -O2 -o block_afalg block_afalg.c
# Ejecutar un comando con AF_ALG bloqueado
./block_afalg python3 your_script.py
./block_afalg bash
python3 -c "
import socket
try:
s = socket.socket(38, socket.SOCK_SEQPACKET, 0)
s.close()
print('VULNERABLE: socket AF_ALG disponible')
except:
print('SEGURO: socket AF_ALG bloqueado o no disponible')
"
# Verificar estado de seccomp
cat /proc/self/status | grep Seccomp
# Seccomp: 0 = no protegido
# Seccomp: 2 = protegido
# Probar socket AF_ALG
python3 -c "
import socket
try:
s = socket.socket(38,2,0)
s.close()
print('AF_ALG disponible - NO protegido')
except OSError:
print('AF_ALG bloqueado - PROTEGIDO')
"
# Verificar registros PAM
grep pam_block_afalg /var/log/secure
# Debe mostrar: filtro seccomp aplicado, AF_ALG bloqueado
__NR_socket en x86_64). Otras arquitecturas necesitan actualizar el número de llamada al sistema.exec() directas sin PAM no están cubiertas (use block_afalg para esas).remove.yum update kernel y luego elimine el módulo.Esta herramienta se proporciona únicamente para pruebas de seguridad autorizadas y fines defensivos. Úsela solo en sistemas que posea o para los que tenga autorización explícita de evaluación.