
Una implementación en Go de dirtyfrag (CVE-2026-43284 / CVE-2026-43500)
Dos bugs. Una shell. Sin escrituras en disco.
Puerto en Go de dirtyfrag (CVE-2026-43284 / CVE-2026-43500).
La clase de bug está en el subsistema XFRM del kernel de Linux. Cuando una página de archivo se pasa con splice() a un pipe y luego a un socket cifrado con ESP, el kernel descifra la carga útil de ESP en el lugar, directamente en la página de page-cache del archivo de origen. El archivo es de solo lectura. El page-cache no lo es.
dirtyfrag encadena dos bugs independientes que explotan esta primitiva:
CVE-2026-43284 - ruta ESP/XFRM
Instala 48 SA XFRM en modo transporte mediante NETLINK_XFRM. Cada SA codifica 4 bytes de la carga útil del shellcode en el campo seq_hi de su estado de replay ESN. Una cadena vmsplice + splice activa el descifrado de ESP en el lugar para cada SA, escribiendo esos 4 bytes en la entrada de page-cache de /usr/bin/su. 48 activaciones, 192 bytes escritos, sin condición de carrera.
CVE-2026-43500 - ruta RxRPC/rxkad
Obtiene mediante fuerza bruta 3 claves de sesión PCBC(fcrypt) fuera de línea que producen las secuencias de bytes objetivo al ser descifradas. Activa un disparador de socket AF_RXRPC para cada clave con el fin de parchear la entrada root en /etc/passwd a root::0:0 (nullok). su - acepta entonces una contraseña vacía.
Ambas rutas se ejecutan en un namespace de usuario + red (CLONE_NEWUSER | CLONE_NEWNET) para evitar requerir CAP_NET_ADMIN en el host.
go build -o dirtyfrag-go .
./dirtyfrag-go
# Force a specific path
./dirtyfrag-go --force-esp
./dirtyfrag-go --force-rxrpc
# Verbose output
./dirtyfrag-go -v
El binario intenta primero la ruta ESP. Si /usr/bin/su no queda parcheado después, recurre a la ruta RxRPC (hasta 3 reintentos). En caso de éxito, accede a una shell root mediante una PTY nueva.
El exploit solo toca el page-cache. Los binarios en disco y /etc/passwd no se modifican. Un reinicio lo restaura todo. Para vaciarlo inmediatamente sin reiniciar:
echo 1 | tee /proc/sys/vm/drop_caches
esp4, esp6 (ruta ESP) y/o rxrpc (ruta RxRPC)Todos los kernels anteriores a los parches:
rmmod esp4 esp6 rxrpc
printf 'install esp4 /bin/false\ninstall esp6 /bin/false\ninstall rxrpc /bin/false\n' \
> /etc/modprobe.d/dirtyfrag.conf
El runtime de Go es multi-hilo desde el inicio, por lo que unshare(CLONE_NEWUSER) no está permitido. El puerto en Go se re-ejecuta a sí mismo como un proceso hijo con SysProcAttr.Cloneflags configurado, lo que llama a clone() antes de que se inicialice el runtime de Go.
| C (original) | Go |
|---|
| Dependencias externas | no | no |
| Archivo único | no | no |
| Binario estático | sí | sí |
| Ruta RxRPC | sí | sí |
| Ruta ESP | sí | sí |
| Aislamiento de namespace | unshare() | re-ejecución con Cloneflags |