Ya no habrá más «viernes azules»
(brendangregg.com)- La caída global de Windows del 19 de julio de 2024 fue un caso en el que una actualización de un controlador de kernel de un producto de seguridad provocó una lectura incorrecta de memoria, causando pantallas azules y bucles de arranque
- eBPF se ejecuta dentro del kernel, pero usa un verificador y sandboxing para rechazar código riesgoso, por lo que está diseñado para impedir que un solo programa haga colapsar todo el sistema
- Linux ya incluye eBPF, y cuando eBPF for Windows de Microsoft esté listo para producción, el software de seguridad de Windows también podrá migrarse de la misma manera
- Grandes empresas tecnológicas como Google, Meta y Cisco, junto con startups de seguridad basadas en eBPF, están ampliando productos de seguridad y sistemas de detección aprovechando su velocidad, visibilidad profunda y garantías de seguridad
- Las empresas que compran software comercial que incluye controladores de kernel o módulos de kernel pueden convertir el soporte para eBPF en un requisito para proveedores: ahora en Linux y pronto en Windows
Los riesgos del código de kernel que dejó al descubierto la caída de Windows del 19 de julio
- La interrupción del 19 de julio de 2024 fue un caso sin precedentes que mostró los riesgos inherentes de la programación en kernel
- Computadoras con Windows en todo el mundo sufrieron la pantalla azul (blue screen of death) y bucles de arranque, afectando a hospitales, aerolíneas, bancos, supermercados y medios de comunicación
- La causa fue una actualización de configuración (config update) de un producto de seguridad de uso extendido, que incluía un controlador de kernel para sistemas Windows
- Después de la actualización, el controlador de kernel intentó leer memoria incorrecta, y este tipo de error puede hacer colapsar el kernel
Los fallos que eBPF puede evitar
- eBPF ya no es solo una sigla, sino un entorno seguro de ejecución en el kernel similar al runtime seguro de JavaScript integrado en un navegador web
- Es muy probable que los usuarios de Linux ya tengan eBPF en sus sistemas, ya que fue incorporado al kernel de Linux hace algunos años
- Los programas eBPF están restringidos para que no puedan hacer colapsar todo el sistema
- Un verificador (verifier) de software revisa su seguridad
- El programa se ejecuta, en la práctica, dentro de un sandbox
- Si el verificador detecta código inseguro, el programa se rechaza y no se ejecuta
- El verificador de la implementación de Linux está compuesto por más de 20 mil líneas de código, con contribuciones de la industria como Meta, Isovalent y Google, y del ámbito académico como Rutgers University y University of Washington
- La seguridad reforzada, el bajo uso de recursos y la prevención de fallos son ventajas clave de eBPF
Posibilidades de adopción en Linux y Windows
- La empresa de seguridad responsable de esta caída ya estaba en proceso de adoptar eBPF en sistemas Linux
- Cuando eBPF support for Windows de Microsoft esté listo para producción, el software de seguridad de Windows también podrá portarse a eBPF
- Un agente de seguridad de Windows migrado a eBPF quedaría en una forma que no podría provocar fallos del kernel de Windows
Adopción en la industria de seguridad y entre grandes tecnológicas
- Startups de seguridad basadas en eBPF como Oligo y Uptycs han destacado, a raíz de la reciente caída, las ventajas de migrar a eBPF
- Las grandes empresas tecnológicas también están adoptando eBPF para seguridad
- Cisco adquirió la startup de eBPF Isovalent y presentó Cisco Hypershield, un tejido para aplicación de seguridad y monitoreo
- Google y Meta detectan y bloquean actividad maliciosa en entornos a gran escala aprovechando la velocidad, visibilidad profunda y garantías de seguridad de eBPF
- Además de seguridad, eBPF también se usa para redes y observabilidad (observability)
Límites de eBPF y medidas operativas complementarias
- Lo peor que puede hacer un programa eBPF es consumir más recursos de lo deseable, como ciclos de CPU o memoria
- No impide el código ineficiente o derrochador, pero sí bloquea problemas graves que terminarían en una caída del sistema
- eBPF también es una tecnología nueva, por lo que ha habido bugs en el código de gestión, e incluso hubo un caso reciente de kernel panic en Linux descubierto por la misma empresa de seguridad mencionada en las noticias
- Si esos bugs se corrigen en eBPF, la corrección puede aplicarse a todos los proveedores que usan eBPF, mejorando más rápido la seguridad general
- El riesgo de despliegue no termina con eBPF, y todavía quedan prácticas operativas que pueden usarse junto con él
- Pruebas canary
- Despliegue gradual
- Ingeniería general de resiliencia
Cambios que los compradores pueden exigir
- Lo importante del enfoque de eBPF es que se trata de una solución de software que vendrá incluida de forma nativa tanto en el kernel de Linux como en el de Windows, y que ya ha sido adoptada para este caso de uso
- Si una empresa paga por software comercial que incluye controladores de kernel o módulos de kernel, puede convertir eBPF en un requisito
- En Linux eso ya es posible hoy, y en Windows lo será pronto
- Algunos proveedores ya adoptaron eBPF de manera proactiva, pero otros podrían necesitar que los clientes que pagan se lo exijan
1 comentarios
Opiniones en Hacker News
Al ver la lista de “hooks” que ofrece eBPF para Windows, parece bastante alejada de la realidad. Por ahora se limita más o menos a paquetes entrantes y operaciones de sockets, así que parece que Microsoft espera que Berkeley Packet Filter se use literalmente para filtrado de paquetes.
No es lo mismo que el filtrado de I/O, la creación/uso de objetos, ni la gran cantidad de puntos donde drivers como los de CrowdStrike se enganchan al kernel NT.
Además, para vigilar otra basura de terceros que corre en el espacio del kernel, el antimalware también tiene que estar dentro del kernel. ELAM (early-launch anti-malware) carga primero el driver antimalware para que supervise el comportamiento de otros drivers, y es muy dudoso que algo así sea posible con eBPF.
A Microsoft le queda un camino muy largo si quiere reemplazar los drivers antimalware en espacio de kernel con eBPF.
https://microsoft.github.io/ebpf-for-windows/ebpf__structs_8...
Como analogía, sería como si la gente hiciera operaciones bancarias en sitios web con JavaScript en Google Chrome, pero en Microsoft Edge les dijeran: “no soportamos JavaScript, así que descargue y ejecute este .EXE”. La pregunta no es tanto “si” Microsoft va a soportar JavaScript o eBPF, sino “cuándo” lo va a soportar.
No quiero discutir con alguien como Brendan Gregg, pero me gustaría que los proveedores de este sector investigaran toda la cadena de fallas de manera más integral. Cuando tres días después de una falla aparece una propuesta que dice “x resuelve el problema ocurrido en la fecha y”, me pongo cauteloso.
Puede ser correcta, pero si no se hace el análisis pueden quedar puntos ciegos, y también puede haber muchas alternativas que deban revisarse y luego descartarse adecuadamente.
En particular, me cuesta estar de acuerdo con la parte de que “el peor resultado negativo es solo desperdiciar CPU”. Para ciertas clases de bugs puede ser así, pero hay muchos modos de falla en los que un conjunto de reglas incorrecto puede dejar un sistema muy inutilizable y difícil de recuperar.
No quiero decir que un módulo de seguridad basado en eBPF no pueda ser la opción correcta para muchos proveedores; lo que digo es que conviene entender qué riesgos evita, cuáles no, y qué parte de la cadena de fallas aborda.
https://opensource.microsoft.com/blog/2021/05/10/making-ebpf...
https://lwn.net/Articles/857215/
Si de verdad hay preocupaciones, también existen canales de discusión donde se pueden plantear, y están organizados en GitHub.
https://github.com/microsoft/ebpf-for-windows
Puede que ya haya respuestas; si no, se pueden tratar ahí.
Eso no es correcto. Si la estructura es tal que el sistema necesita cierto fragmento de código para ejecutarse, cuando ese código se rompe el sistema directamente no debería ejecutarse. Es raro ignorar la falla.
Por ejemplo, si el código del controlador de algún dispositivo médico garantiza un bloqueo de seguridad para que no queme a una persona, preferiría que todo se detuviera antes que funcionara como si nada con la seguridad desactivada.
Al final, aunque bajemos de nivel, sigue siendo el mismo problema.
No sé cómo lo hace Linux en la práctica, pero se puede imaginar un mundo en el que el comportamiento ante entradas incorrectas sea configurable.
Además, esa afirmación no siempre es cierta. En el caso general estoy de acuerdo, pero en ciertos contextos el sistema debe seguir funcionando. El ejemplo que me viene enseguida a la mente es la computadora de guiado de un módulo automático de aterrizaje en Marte. La latencia de ida y vuelta con la Tierra es demasiado larga como para delegar la responsabilidad.
Si se apaga, se estrella; pero si hace lo mejor posible en un estado dañado, probablemente solo se estrelle, así que esa opción podría ser mejor.
Si todo el sistema operativo queda convertido en un ladrillo, es un problema mucho mayor porque un técnico de IT tiene que arreglarlo en persona. De lo contrario, habría bastado con actualizar solo el controlador defectuoso.
Un auto tampoco se niega a arrancar porque no tenga líquido limpiaparabrisas.
La mayoría de las organizaciones afectadas el viernes habrían preferido un ligero aumento durante 24 horas del riesgo de ataques de malware o uso no autorizado antes que el colapso total de IT que realmente sufrieron.
Además, ese bug no tenía por qué causar necesariamente una pantalla azul. El sistema también podría haber seguido funcionando en un estado indefinido y con consecuencias ilimitadas.
Con eBPF, al menos se pueden detectar algunos de los errores posibles y tomar decisiones de gestión de riesgo según el resultado.
Para actualizar, el llamador debe invocar otra función, de modo que la responsabilidad queda en el llamador y no en alguien que pueda tocar el kernel por vías laterales.
Si no existe una función correspondiente al hash indicado, no se puede llamar; y aunque exista, no se la puede invocar de una forma distinta a la prevista, con lo que se obtiene la propiedad deseada de “funcionar perfectamente o no funcionar en absoluto”.
Además, la respuesta ante un estado incorrecto no tiene por qué ser necesariamente “ignorar”. También podría desactivar inicios de sesión limitados de usuarios o apagar la pantalla.
Si la preocupación es que el malware pueda abusar de esto, me pregunto si es buena idea confiar en que el propio sistema pueda manejarlo cuando el malware ya está en una situación en la que puede modificar los archivos en disco del antivirus.
Puede ser más seguro reportarlo a una capa superior de seguridad y hacer que un sistema externo tome medidas como desactivar o restringir el acceso a la red. Más aún, como esas medidas solo requieren permiso de observación y no autoridad para intervenir en el sistema, también se reduce la posibilidad de que el propio sistema antivirus se convierta en una ruta para el malware o en la causa de bugs como este.
eBPF es excelente y puede usarse para muchos fines, mejorando muchas cosas, pero decir que “la computadora no se va a crashear por una mala actualización de software” me parece una exageración.
Incluso suponiendo que BPF en sí no tenga bugs, el alcance de los hooks del kernel es bastante amplio; esos hooks llaman código eBPF, y ese código a su vez puede llamar al kernel.
https://www.man7.org/linux/man-pages/man7/bpf-helpers.7.html
En particular, bpf_probe_read_kernel() se usa muchísimo, pero no es seguro. Hace un esfuerzo considerable por evitar OOPS o crasheos, pero de ninguna manera es perfecto.
En el resto de la lista también hay muchas cosas que pueden arruinar fácilmente el sistema aunque en la práctica no provoquen un oops o un panic.
Y si se trata de una herramienta que detecta y bloquea “comportamiento malicioso” en espacio de usuario, también podría empezar a considerar todo como malicioso y dejar la computadora inutilizable.
Por otro lado, eBPF no tiene un verdadero modelo de seguridad del lado del espacio de usuario. La vinculación real de programas eBPF se realiza mediante la llamada al sistema bpf(), no como una operación razonable de permisos sobre el objeto del kernel al que se adjunta, y no existe ningún mecanismo para confinar dentro de un contenedor el eBPF usado por ese contenedor. bpf_probe_read_kernel() esencialmente puede leer toda la memoria del kernel.
Así que la ventaja de eBPF frente al código C común del kernel está en que se parece a escribir código en un lenguaje seguro con una superficie limitada de API unsafe. Para este tipo de trabajo es una gran mejora, pero de ninguna manera es perfecto.
También se dice que el verificador es estricto y que la implementación de Linux supera las 20 mil líneas, pero el verificador es ridículamente complejo. Preferiría ver una base de métodos formales antes que 20 mil líneas de lógica escrita a mano.
Me genera dudas eso de que “los programas eBPF pasan controles de seguridad mediante un verificador de software y se ejecutan prácticamente en un sandbox, por lo que no pueden hacer que todo el sistema crashee”
¿No es uno de los objetivos de un sistema operativo supervisar el software? Entiendo que este es un problema relacionado con el propio sistema operativo, pero si agregamos una capa para supervisar al supervisor, ¿no terminamos teniendo que supervisar también esa capa?
¿No podríamos optar por reducir la complejidad, en lugar de creer ingenuamente que una nueva complejidad será mejor a largo plazo?
El enfoque anterior era cargar drivers del kernel, engancharse a un montón de llamadas del sistema y rezar para no romper nada. Si sale mal, puede haber un panic, aunque Linux es bastante robusto
El enfoque con eBPF se parece más a pedir la información que quieres mediante instrucciones específicas de eBPF
Aquí hay un resumen de cómo funciona: https://ebpf.io/what-is-ebpf/
Suena como una tecnología genial, pero el problema realmente serio está en la parte que dice que “también se pueden usar métodos de mitigación de riesgos en el despliegue de software, como pruebas canary, despliegues graduales e ingeniería de resiliencia”
No hace falta una tecnología nueva para implementar control de calidad básico estándar de la industria
Tal vez deberíamos empezar a tomarnos libres los viernes para conmemorar este incidente. Es posible que el daño hubiera sido menor si la gente trabajara con menos presión y tuviera más tiempo para detenerse a pensar cómo evolucionan las situaciones y qué influencia puede tener sobre ese rumbo
La explicación de que el verificador de la implementación de Linux tiene más de 20 mil líneas y recibió contribuciones de la industria y la academia, en realidad, no me tranquiliza. La superficie de ataque adicional ya es un problema, pero ¿quién puede garantizar una base de código tan grande?
Tengo la impresión de que el verificador de WebAssembly es mucho más simple
Si el filtro se carga al arrancar y se engancha a todo, un solo bug puede bloquear el sistema hasta el punto de que no se pueda ni operar ni parchear. Por ejemplo, si se carga una lista de permitidos vacía; al final, eso podría convertir un bucle de arranque en otra forma de denegación de servicio
Si Microsoft incluyera los elementos esenciales para la recuperación en una lista de permitidos hardcodeada, sería más fácil corregir bugs de este tipo de herramientas, pero hasta que se distribuya la corrección podría haber un downtime real en el que el sistema esté encendido, pero inutilizable
La publicación del blog dice que “eBPF es inmune a este tipo de crashes”
Busqué, pero no encontré nada concluyente, y todavía parece que podría romper algo. Me gustaría que algún experto en eBPF explicara esta afirmación. Lo mejor que encontré es esto: https://stackoverflow.com/questions/70403212/why-is-ebpf-sai...