
CVE-2026-68398 Escalada de privilegios local por use-after-free en Ubuntu PPPoL2TP

Este repositorio contiene un exploit de escalada de privilegios local específico de una compilación para CVE-2026-68398, una condición de carrera de tipo use-after-free entre el procesamiento de recepción de PPPoL2TP y la destrucción de un canal PPP no asociado. Fue validado en QEMU contra el paquete oficial de Ubuntu 22.04 linux-image-5.15.0-187-generic (5.15.0-187.197).
La prueba final comienza como un usuario dedicado con UID 1001, sin grupos suplementarios, sin capacidades y sin acceso sudo, y después obtiene UID 0 en el espacio de nombres inicial. KASLR, SMEP, SMAP y AppArmor permanecen habilitados. El invitado no se inicia con nokaslr, nopti, nosmep ni nosmap.
Advertencia
Este código corrompe intencionalmente el estado del heap del kernel y está ligado a una compilación exacta del kernel de Ubuntu. Una condición de carrera fallida puede provocar un pánico del kernel o corromper el sistema. Ejecútalo solo en una máquina virtual aislada y desechable de tu propiedad.
pppol2tp_recv() se ejecuta en la ruta de recepción UDP de L2TP dentro de una sección crítica de lectura de RCU y finalmente llama a ppp_input(&po->chan). El socket PPPoX y su ppp_channel incorporado son seguros para RCU, pero la struct channel interna usada por ppp_input() es una asignación separada.
Para un canal vinculado con PPPIOCGCHAN pero que no está asociado a una unidad PPP ni puenteado, la ruta de cierre liberaba ese objeto interno inmediatamente:
RX: l2tp_udp_encap_recv -> pppol2tp_recv -> ppp_input(channel)
CLOSE: pppol2tp_release -> pppox_unbind_sock
-> ppp_unregister_channel -> ppp_release_channel -> kfree(channel)
En consecuencia, la ruta de recepción puede operar sobre la cola skb y la waitqueue del canal liberado. El parche añade una devolución de llamada (callback) de RCU a struct channel y difiere el vaciado de la cola y la liberación hasta que haya transcurrido un período de gracia de RCU.
La vulnerabilidad fue descubierta y corregida upstream por Norbert Szetei, de Doyensec. La corrección en mainline es ec4215683e47424c9c4762fd3c60f552a3119142.
El registro CNA de Linux identifica el linaje vulnerable como comenzando con Linux 4.15. Los kernels de los proveedores pueden incluir la corrección con un número de versión diferente, por lo que la fuente exacta o el changelog del paquete tienen prioridad sobre esta tabla.
Las líneas de kernel de proveedores más antiguas requieren un backport. A fecha de 2026-08-12, el rastreador de CVE de Ubuntu marca el paquete linux de Jammy como needs-triage; no se identificó ningún paquete corregido de Ubuntu Jammy. La fuente probada 5.15.0-187.197 todavía llama a kfree(pch) directamente y es vulnerable.
El kernel no fue recompilado. La imagen mínima de nube carecía de linux-modules-extra-5.15.0-187-generic, por lo que se instaló ese paquete oficial de Ubuntu para proporcionar l2tp_ppp. Una instalación normal de Jammy que use el metapaquete linux-generic ya depende del paquete modules-extra correspondiente. El módulo del protocolo se carga automáticamente cuando el exploit crea su socket PPPoL2TP.
El detector automático de KASLR usa un canal lateral de temporización por prefetch x86 y requiere RDTSCP con KPTI inactivo. La CPU del host probado expone rdtscp, smep y smap y no está afectada por Meltdown, por lo que Ubuntu deja KPTI inactivo sin ninguna anulación en el arranque. En una CPU donde /proc/cpuinfo reporte el flag pti, el detector se niega a ejecutarse. Esa es una condición de hardware específica del exploit: la CVE subyacente sigue siendo alcanzable, pero esta versión no afirma un bypass de KASLR en un sistema con KPTI activo. Existe un slide suministrado manualmente únicamente para diagnósticos controlados.
struct channel liberada. La ruta RX aún en ejecución trata los bytes controlados de la clave como su cola skb y su waitqueue.core_pattern como espacio auxiliar de revelación y expone un puntero de asignación de clave.override_creds() con la credencial forjada. Los campos UID/GID, las capacidades y los punteros necesarios de usuario, espacio de nombres, ucount y grupo coinciden con la compilación exacta de Ubuntu./proc/self/exe a un archivo único en /tmp, lo cambia a propiedad de root con modo 4755 y verifica esos atributos./usr/bin/id.El último puente es necesario porque override_creds() cambia las credenciales subjetivas de la tarea activa del kernel; instalar y ejecutar la copia SUID verificada convierte esa primitiva de corta duración en credenciales normales de proceso.
El Makefile enlaza el exploit estáticamente. El objeto prefetch sensible a la temporización se compila deliberadamente con -O0; el exploit en sí usa -O2.
make
Comandos equivalentes:
gcc -O0 -Wall -Wextra -Werror -c -o build/kaslr_prefetch.o kaslr_prefetch.c
gcc -O2 -static -pthread -Wall -Wextra -Werror \
-o build/CVE-2026-68398 exploit.c build/kaslr_prefetch.o
Desde la cuenta de usuario ordinaria, en el kernel validado exacto:
id
grep '^Cap' /proc/self/status
./CVE-2026-68398 auto 60
El código fuente comprueba uname() y rechaza cualquier versión distinta de 5.15.0-187-generic. La condición de carrera es probabilística; reinicia una instantánea desechable antes de reintentar después de un fallo o un crash.
Una ejecución con éxito termina con:
[KASLR] image_base=0xffffffffb9200000 slide=0x38200000
CVE-2026-68398 Ubuntu local privilege-escalation exploit
uid=1001 euid=1001 slide=0x38200000
...
[9/9] invoking override_creds and installing the SUID transition...
override callback: uid=0 euid=0 gid=0 egid=0
installed root-owned mode 4755 helper: /tmp/.cve-2026-68398-root-948
SUID helper ready; executing it from the original unprivileged task...
SUID transition: uid=0 euid=0 gid=0 egid=0
uid=0(root) gid=0(root) groups=0(root),1001(poc)
La transcripción concisa completa de esa ejecución real en QEMU está en docs/example-output.txt.
La cadena se completó en tres arranques de Ubuntu nuevos y normalmente aleatorizados. Las bases de imagen recuperadas automáticamente fueron 0xffffffff90800000, 0xffffffffa5a00000 y 0xffffffffb9200000. La ejecución final usó la cuenta dedicada no administrativa con UID 1001 descrita anteriormente y verificó que el archivo SUID temporal se eliminara después.
La misma condición de carrera final también se ejecutó durante 60 segundos con el commit exacto de la corrección upstream, con KASAN habilitado y la misma topología de cuatro vCPU. Completó 5,969 ciclos de canal/clave, informó stage 1: no controlled reclaim y no produjo ningún informe de KASAN ni transición de etapa del exploit.
Comprobado el 2026-08-12 antes de que se creara este repositorio privado. SearchSploit/Exploit-DB no devolvió ningún exploit; Packet Storm no devolvió ningún archivo coincidente; la búsqueda de código exacto en GitHub devolvió 22 espejos de CVE/avisos y ningún PoC; y las búsquedas web exactas solo encontraron la corrección upstream y los metadatos. Este es un resultado puntual, no una garantía de que otro PoC no aparezca más adelante.
kaslr_prefetch.cEl exploit fue escrito por A. Ramos <[email protected]> (Twitter: @aramosf). El descubrimiento de la vulnerabilidad y la corrección upstream se atribuyen a Norbert Szetei (Doyensec).
exploit.c está bajo licencia GPL-2.0-only. kaslr_prefetch.c y kaslr_prefetch.h tienen licencia MIT y conservan la atribución a KASLD y el aviso de permiso completo en los archivos fuente.
| Línea del kernel | Primera versión corregida | Commit de corrección |
|---|
| 6.6.y | 6.6.148 | 4bb84e964ff0 |
| 6.12.y | 6.12.101 | 3ab32218d718 |
| 6.18.y | 6.18.42 | c9574b8a8ede |
| 7.1.y | 7.1.6 | 06213c85d8c0 |
| Mainline | 7.2-rc4 | ec4215683e47 |
| Propiedad | Valor |
|---|
| Distribución | Ubuntu 22.04.5 LTS (Jammy) |
| Paquete del kernel | linux-image-5.15.0-187-generic / 5.15.0-187.197 |
| Versión del kernel | 5.15.0-187-generic #197-Ubuntu |
| Arquitectura | x86-64 |
| VM | QEMU/KVM, -cpu host, cuatro vCPUs, 5 GiB de RAM |
| Identidad inicial | uid=1001(poc) gid=1001(poc) groups=1001(poc) |
| Capacidades iniciales | heredables, permitidas, efectivas y ambientales, todas a cero |
| Identidad final | uid=0(root) gid=0(root) en los espacios de nombres iniciales |
| Cambios de arranque | Ninguno; línea de comandos estándar, KASLR habilitado |
| Requisito | Estado en Ubuntu 5.15.0-187 | Uso en el exploit |
|---|
| PPP | CONFIG_PPP=y | Integrado |
| L2TP / PPPoL2TP | CONFIG_L2TP=m, CONFIG_PPPOL2TP=m | Módulo oficial de linux-modules-extra |
| Claves de usuario | CONFIG_KEYS=y | Recupera el canal liberado de kmalloc-256 |
| AppArmor | CONFIG_SECURITY_APPARMOR=y | Permanece activo; la credencial falsa incluye una etiqueta unconfined válida |
| KASLR | CONFIG_RANDOMIZE_BASE=y | Permanece activo; el slide se recupera en tiempo de ejecución |
| SMAP | CONFIG_X86_SMAP=y | Permanece activo |
| Espacios de nombres de usuario/red | Habilitados por Ubuntu, pero no utilizados | No se requiere configuración de espacios de nombres ni obtención de capacidades |
/dev/ppp | No es necesario | El canal está vinculado pero nunca se conecta a una unidad PPP |