
37 años escondido en el kernel: el bug de OpenBSD que terminó en shell de root
Hay semanas en que la seguridad te da lecciones gratis, y esta las regaló un bug de OpenBSD que tiene literalmente 37 años de antigüedad. El equipo de Calif publicó Big Fish: un exploit que consigue shell de root local combinando un desborde de enteros que viene desde las fuentes BSD originales con una condición de carrera y un write fuera de límites en el kernel. Y todo con KARL, SMAP y SMEP activos, sin necesitar un bug de fuga de información previo. Suena a exageración, pero está documentado paso a paso, erratas incluidas.
La raíz es casi poética: en las fuentes originales de BSD, el contador de adjuntos de memoria compartida SysV, shm_nattch, se definió como entero con signo de 16 bits. Máximo 32.767. Si haces fork en cadena con procesos que adjuntan memoria compartida, el contador da la vuelta y queda negativo. De ahí, ganándose una carrera con IPC_RMID mientras otro proceso adjunta un segmento con el tamaño trampa, se llega a un use-after-free. Después viene la parte fina: heap grooming con métricas de sysctl, sockets IP con IP_MULTICAST_TTL no estándar para clavar estructuras de 16 bytes en direcciones predecibles, y un TAILQ_REMOVE que produce el write fuera de límites. El resultado es un clásico write-what-where en el kernel, porque los allocadores de arranque de OpenBSD no randomizan sus bases. Root shell.
Lo interesante es la lección, no el exploit. OpenBSD es el sistema que inventó la mitad de las mitigaciones que damos por sentadas: W^X, ASLR agresivo, separación de privilegios, auditoría de código constante. Y aun así, un entero de 16 bits definido en los ochenta sobrevivió 37 años de escrutinio. KARL relinkea tu kernel y randomiza funciones y datos, pero si el allocador de arranque es determinista, los punteros a funciones tempranas caen siempre en el mismo lugar. La defensa en profundidad que no cubre el determinismo del allocador es media defensa.
En mi pega trabajo con sistemas que no se pueden reiniciar cada semana, y este tipo de detalle me deja pensando. Uno confía en que los componentes viejos y auditados son los más seguros, y es al revés: los componentes viejos simplemente tienen bugs que todavía no se publicaron. No es que no existan, es que nadie los encontró aún. Con la IA revisando código a escala, la ventana entre «nadie lo vio» y «hay exploit público con código en GitHub» se acorta cada mes. Calif mismo lo deja claro: los bugs que reportaron a FreeBSD los habría cazado el array bounds sanitizer en compilación.
Yo mantengo un par de VPS OpenBSD para cosas críticas, así que la reacción inmediata es simple: aplica las erratas del proyecto. Las que cierran este bug son la 026 (SysV IPC) y la 018 (shmat), ambas para el branch 7.9. Es escalada local a root, así que si tu threat model incluye usuarios locales o procesos que manipulan datos no confiables, parchar hoy es innegociable. Y si el equipo además expone servicios por red, el riesgo sube, porque el combo carrera + corrupción de memoria no es teórico.
La moraleja para los que administramos servidores sin ser dioses del kernel va en tres líneas: 1) los enteros de 16 bits con signo siguen vivos en tu stack y alguien va a desbordar uno más temprano que tarde; 2) el determinismo de los allocadores es una superficie de ataque en sí misma, no un detalle de rendimiento; 3) un proyecto con 37 años de auditoría no es un proyecto sin bugs, es un proyecto con 37 años de bugs que aún no se publican.
Nada de esto demerita a OpenBSD, ojo: sigue siendo de los pocos sistemas que publican erratas en horas y documentan los fixes con ese nivel de detalle. El punto es otro. La seguridad no es un estado, es un proceso que se paga todos los meses con actualizaciones, revisión de configuración y algo de paranoia saludable. Yo ya parché los míos, porque la alternativa a la paranoia es responder incidentes a la medianoche, y esa changa nadie la quiere.
Fuente: Big Fish: Exploiting a 37-Year-Old Kernel Bug in OpenBSD, investigación de Calif.
Fuente de inspiración: Big Fish: Exploiting a 37-Year-Old Kernel Bug in OpenBSD
