Curso MIT "Seguridad de sistemas informáticos". Lección 7: El sandbox del cliente nativo, parte 1

Instituto de Tecnología de Massachusetts. Conferencia Curso # 6.858. "Seguridad de los sistemas informáticos". Nikolai Zeldovich, James Mickens. Año 2014


Computer Systems Security es un curso sobre el desarrollo e implementación de sistemas informáticos seguros. Las conferencias cubren modelos de amenazas, ataques que comprometen la seguridad y técnicas de seguridad basadas en trabajos científicos recientes. Los temas incluyen seguridad del sistema operativo (SO), características, gestión del flujo de información, seguridad del idioma, protocolos de red, seguridad de hardware y seguridad de aplicaciones web.

Lección 1: "Introducción: modelos de amenaza" Parte 1 / Parte 2 / Parte 3
Lección 2: "Control de ataques de hackers" Parte 1 / Parte 2 / Parte 3
Lección 3: “Desbordamientos del búfer: exploits y protección” Parte 1 / Parte 2 / Parte 3
Lección 4: “Separación de privilegios” Parte 1 / Parte 2 / Parte 3
Lección 5: “¿De dónde vienen los sistemas de seguridad?” Parte 1 / Parte 2
Lección 6: “Oportunidades” Parte 1 / Parte 2 / Parte 3
Lección 7: “Sandbox de cliente nativo” Parte 1 / Parte 2 / Parte 3

Hoy hablaremos de un sistema llamado Native Client , que Google usa en el mundo real. Es una tecnología sandbox para ejecutar código en diferentes plataformas. Se utiliza en el navegador Chrome , lo que permite que las aplicaciones web ejecuten código de máquina arbitrario. Este es en realidad un sistema bastante bueno. También ilustra las capacidades de aislamiento y una peculiar caja de arena o técnica de separación de privilegios llamada aislamiento de falla de software, aislamiento de falla de software , sin usar el sistema operativo o la máquina virtual para crear la caja de arena.



En cambio, Native Client adopta un enfoque completamente diferente para mirar instrucciones específicas en un archivo binario para averiguar si es seguro ejecutarlo o no. Por lo tanto, antes de comenzar a estudiar los detalles técnicos del sistema, descubramos por qué estos tipos realmente quieren ejecutar código de máquina. Su interés específico es aplicar esta solución en un navegador web, donde ya puede ejecutar código JavaScript , Flash Player y algunos otros procesos. ¿Por qué estos chicos están tan entusiasmados con la capacidad de ejecutar código en la plataforma x86 ? Después de todo, parece que esto es un paso atrás.

Audiencia: quieren obtener cálculos muy rápidos.

Profesor: sí, esta es una gran ventaja del código de máquina. Incluso si puede ser inseguro a largo plazo, proporciona un alto rendimiento. Todo lo que no haría en JavaScript , por ejemplo, escribir un programa y compilarlo, realmente funcionará mucho más rápido. ¿Hay alguna otra razón?

Audiencia: ¿ Ejecutando código existente?

Profesor: cierto. Es importante que no todo se pueda escribir en JavaScript . Por lo tanto, si tiene una aplicación existente o, en la terminología de la industria, el código "heredado" que tiene la intención de ejecutar en Internet, esta parece ser una gran solución. Debido a que puede tomar una biblioteca existente, por ejemplo, algún tipo de "motor" gráfico complejo que sea sensible al rendimiento y a muchas otras cosas complejas que no desea volver a implementar, y esta será una buena solución.
Si solo está programando una nueva aplicación web, ¿debería usar su propio cliente si no está particularmente preocupado por la herencia o el rendimiento?

Público: entonces no necesita usar JavaScript .

Profesor: sí, esa es una buena razón. Si no te gusta JavaScript , entonces no necesitas usarlo, ¿verdad? Puede usar, por ejemplo, C , puede ejecutar código Python , escribirlo en Haskell , en cualquier lenguaje que considere más adecuado.

Por lo tanto, esta es una lista de motivación bastante convincente para ejecutar su propio código en un navegador, y es bastante difícil obtener derechos para tal acción. En solo un segundo, consideraremos los detalles técnicos, y ahora quiero mostrarle una demostración de capacitación simple que recibí del sitio web de Native Client .



Esto es bastante simple, porque puede tomar C ++ o un programa en C y ejecutarlo en un navegador. Puede consultar esta página web, que es un archivo HTML que contiene un montón de código JavaScript .



La razón de la existencia de este código JavaScript es que le permite interactuar con partes del Native Client . Con respecto al funcionamiento del navegador, el significado de dicha solución es que tiene algún tipo de página web que contiene código JavaScript . Y esta solución funciona con los privilegios de las páginas y le permite hacer varias cosas en la propia página web, por ejemplo, comunicarse con la red en algunas circunstancias.

Native Client le permite ejecutar su módulo dentro del navegador, por lo que el código JavaScript puede interactuar con él y recibir una respuesta. Esto muestra parte del código JavaScript que necesita Native Client para interactuar con el módulo NaCl específico que estamos a punto de ejecutar.



Y puede enviar mensajes a este módulo. ¿Cómo se hace esto? Toma el objeto de este módulo en JavaScript , lo llama postMessage y , por lo tanto, admite enviar este mensaje al módulo NaCl . Cuando el módulo NaCl responde, iniciará la función de mensaje en JavaScript . Y en este caso particular, aparece un cuadro de diálogo emergente en el navegador.



Entonces, en el lado de JavaScript , esta es una interfaz de página web bastante simple. Lo único que debe hacer adicionalmente es asignar el módulo NaCl de esta manera. Es decir, simplemente inserta un módulo con una ID específica aquí . Lo más interesante aquí es el código de saludo con la extensión nmf . Simplemente dice que hay un archivo ejecutable que debe descargar y comenzar a trabajar con él en un entorno NaCl .



Este código nativo es realmente como cualquier otro código C ++ que puedas escribir. La parte interesante es esta función de procesamiento de mensajes HandleMessage .



Esta es una clase de C ++ , y siempre que el código JavaScript envíe un mensaje al código nativo , realizará esta función. Realiza una comprobación if (mensaje = = 'hola') . Si es así, creará algún tipo de línea de respuesta y la enviará de vuelta. Esto es algo bastante simple. Pero para detalles, intentemos ejecutarlo y ver qué sucede.

Podemos construir y ejecutar un pequeño servidor web que servirá a esta página y al módulo Native Client . Aquí puedo ir a esta URL , y aquí vemos la página web de NaCl . El módulo recibió nuestro mensaje de bienvenida de JavaScript , respondió con una cadena en JavaScript y el código JavaScript activó un cuadro de diálogo emergente que contenía esta respuesta.



Entonces realmente funciona.

Intente averiguar si podemos causar que el Native Client se bloquee. Espero que no, pero podemos tomar este código y este búfer y escribir un montón de tonterías en él, por ejemplo, 65536 y ver qué pasa.



Espero que esto no haga que mi navegador se bloquee porque Native Client está tratando de proporcionar aislamiento. Pero veamos qué pasa.

Reinicie el servidor web. Vemos que la entrada al módulo todavía es exitosa, nuestro navegador no resultó dañado. Sin embargo, la mensajería con el cliente no se realizó, por lo que falta el cuadro de diálogo. Miremos la consola de JavaScript en la parte inferior de la página y veamos que el módulo Native Client nos informa de la falla del módulo NaCl .



Es posible que el argumento que ingresé provocó un desbordamiento del búfer o acceso a alguna dirección incorrecta, pero en cualquier caso, el módulo NaCl es realmente capaz de aislar la corrupción accidental de la memoria de tal manera que no afecte al navegador.

Esta es una demostración rápida de este sistema en la forma en que puede usarlo como usuario final o desarrollador. Veamos algunos ejemplos más. Por ejemplo, cómo funcionará Native Client , o por qué necesitamos esto, y no un diseño alternativo.

Por lo tanto, si su objetivo es aislar su propio código, existen varias alternativas con las que puede hacerlo. De hecho, las personas solían tener problemas para usar el código heredado y otros idiomas antes de que apareciera Native Client . Los resolvieron de varias maneras, lo que podría no haber sido tan seguro y conveniente como el Native Client , pero proporcionaba las mismas capacidades de aislamiento.

Entonces, ¿qué debe hacer si realmente desea ejecutar el código de la máquina en un navegador? Una opción es confiar en el desarrollador. Quizás una variante de este enfoque es que le preguntas al usuario si quiere ejecutar algún código en su navegador o no.

Entonces, todos entienden aproximadamente qué tipo de plan es este, ¿verdad? Por ejemplo, en lugar de toda esta estrategia de compilación de Native Client , podría crear un programa en C , ejecutarlo en un navegador, y él me preguntaría si quiero ejecutar este sitio o no. Y si hago clic en "sí", accidentalmente "cortando" en la memoria del navegador, se bloqueará. Entonces es posible, ¿verdad? Esto, por supuesto, resuelve todos estos problemas, pero ¿qué hay de malo en eso?

Creo que lo malo es que esta solución no es segura. Esta es una forma de sortear este sistema y muchos otros sistemas.

Microsoft tenía un sistema llamado ActiveX que básicamente implementó este plan. Puede enviar los archivos binarios a IE , el navegador de su computadora, y hasta que regresen con un certificado de un desarrollador específico firmado por, digamos, Microsoft u otra persona, el navegador no ejecutará su código. ¿Crees que este es un plan útil?

Audiencia: ¡Esto es una cuestión de confianza!

Profesor: sí, lo es. Realmente necesita confiar un poco en que el desarrollador solo firmará esos "binarios" que no harán nada malo. Pero a menudo es imposible determinar si esto es algo malo o no, por lo que simplemente escriben el código C y lo firman a ciegas sin hacer una gran cantidad de trabajo. En este caso, es posible que tenga ciertos problemas en el futuro.

Del mismo modo, la decisión de preguntar al usuario si realmente quiere ejecutar una cosa no garantiza la seguridad en absoluto. Incluso si el usuario quiere tener cuidado, ¿en realidad no está claro cómo debe decidir? Supongamos que realmente quiero entender si puedo dejar que este programa funcione. Me dicen que todo está bien, tal vez fue creado por desarrolladores acreditados de Google.com o Microsoft.com . Sin embargo, este es el archivo ejecutable foo.exe y no sé absolutamente qué hay dentro de él. Incluso si desmonto su código, será muy difícil decir si va a hacer algo malo o no. Por lo tanto, es realmente difícil para el usuario decidir si ejecutar el código es seguro para el sistema.



Por lo tanto, Native Client puede actuar como un mecanismo por el cual los usuarios pueden tener cierta confianza en si deben decir sí o no a algún programa.

Entonces, en la práctica, creo, debería haber una opción propuesta por nuestro profesor invitado Paul Yang la semana pasada. Aconsejó ejecutar el complemento " reproducir extensión " o "reproducir la extensión" en el navegador Chrome . Es decir, antes de comenzar cualquier extensión, incluido el Cliente nativo , debe hacer clic en esta cosa. En cierto modo, esto es lo mismo que preguntarle al usuario. Pero en este caso, incluso si el usuario decide responder "sí", el sistema seguirá siendo seguro, porque el Cliente nativo se incluirá en el trabajo. En este sentido, tenemos un doble mecanismo de seguridad: primero pregunte al usuario, y luego, con una respuesta positiva, inicie el cliente sandbox, que no permitirá que el navegador se bloquee.

Por lo tanto, otro enfoque que debe aplicarse es utilizar el entorno limitado, implementado mediante el sistema operativo o el hardware, o aislar procesos. Esto es lo que examinamos en las últimas 2 conferencias.

Quizás usaría mecanismos de aislamiento de Unix . Si tuviera algo más complejo, usaría FreeBSD o Capsicum . Es ideal para aislar un fragmento de código en el entorno limitado, ya que puede limitar sus capacidades. Linux tiene un mecanismo similar llamado Seccomp , que cubrimos brevemente en la última conferencia, también le permite hacer tales cosas.

Por lo tanto, ya existe un mecanismo para escribir código de forma aislada en su máquina. ¿Por qué están estos tipos en contra de usar esta solución existente? Parece que están "inventando la rueda" por alguna razón. Entonces, ¿qué está pasando?

Público: ¿ tal vez quieren minimizar los errores?

Profesor: sí, en cierto modo, no confían en el sistema operativo. Quizás estén realmente preocupados por los errores del sistema operativo. Es probable que el kernel de FreeBSD o el kernel de Linux contengan una gran cantidad de código C que no desean o no pueden verificar si son correctos, incluso si quisieran. Y en Capsicum o Seccomp, el trabajo se realiza sobre la base de un plan de aislamiento, por lo que es suficiente que el kernel tenga solo un pequeño y fiel fragmento de código, para que el sandbox mantenga y aplique el aislamiento.



Público: dado que obtienes muchas más formas de usar los navegadores, tienes que lidiar con varios sistemas operativos, como iOS y Android, y acceder ...

Profesor: sí, de hecho, otra consideración interesante es que generalmente muchos sistemas operativos tienen errores. Además, de hecho, los diferentes sistemas operativos son de alguna manera incompatibles entre sí. Esto significa que cada sistema operativo tiene su propio mecanismo, como se muestra aquí: Unix tiene Capsicum , Linux tiene Seccomp , pero estas son solo variaciones de Unix . Mac OS tiene Seatbelt , Windows tiene algo más y la lista continúa.

Entonces, al final, cada plataforma con la que trabaja tiene su propio mecanismo de aislamiento. Y lo que realmente no les molesta demasiado es que tendrán que escribir códigos diferentes para Mac , Windows y Linux . Pero más aún, afecta cómo escribes estas cosas para que funcionen dentro del sandbox. Porque en Native Client, en realidad escribe un fragmento de código que se ejecuta de la misma manera que el código del sistema operativo "nativo", de la misma manera que se ejecuta el código de Apple , el código de Windows o el código del sistema Linux .

Y si utiliza estos mecanismos de aislamiento, en realidad imponen diferentes restricciones al programa colocado en el sandbox. Por lo tanto, debe escribir un programa que se ejecute dentro del entorno limitado de Linux , otro programa que se ejecute dentro del entorno limitado de Windows , y así sucesivamente.

Eso es lo que es realmente inaceptable para ellos. No quieren lidiar con problemas de este tipo. ¿Qué otras consideraciones tienes?

Audiencia: presumiblemente el rendimiento del sistema. Porque si usa Capsicum , debe cuidar los recursos suficientes para garantizar que los procesos funcionen dentro del entorno limitado. Aquí pueden enfrentar el mismo problema.

Profesor: sí, eso es verdad. El plan de aislamiento de fallas de software es realmente muy intensivo en recursos, lo que a nivel del sistema operativo puede causar una falta de recursos para soportar el entorno limitado. Resulta que en su propio Native Client, en realidad usan tanto su sandbox como el sandbox del sistema operativo para proporcionar seguridad adicional. Por lo tanto, de hecho, no ganan en el desempeño de su implementación, aunque probablemente podrían hacerlo.

Público: quizás quieran controlarlo todo. Porque pueden controlar lo que sucede en el navegador, pero si lo enviaron a la computadora del cliente en el sistema operativo, no saben qué podría pasar allí.

Profesor: se puede decir que sí, el sistema operativo puede tener errores o no administrar la caja de arena lo suficientemente bien. O la interfaz es un poco diferente, por lo que no sabe lo que el sistema operativo está a punto de revelar.

Público: y esto no impedirá que el código haga algunas cosas malas. Hay muchas cosas que hace el código, por ejemplo, desea realizar un análisis estático, pero los bucles de código impiden que el programa actúe.

Profesor: de hecho, es muy difícil determinar si hay un proceso en bucle infinito o no, pero en principio, este enfoque le permite detectar algunos problemas de código. Creo que un ejemplo realmente interesante, que no conocía hasta que leí su artículo, muestra que estos tipos están preocupados por los errores de hardware y no solo por las vulnerabilidades del sistema operativo que el código puede ejecutar. Por ejemplo, el procesador en sí tiene algunas instrucciones que pueden hacer que se congele o reinicie la computadora. Básicamente, su equipo no debería tener ese error, porque el sistema operativo se basa en el hecho de que el hardware en cualquier caso lo ayudará a llegar al núcleo para eliminar las consecuencias de un error del usuario.

Pero resulta que los procesadores son tan complejos que tienen errores, y estos muchachos dicen que encontraron evidencia de esto. Si hay algunas instrucciones complejas que el procesador no esperaba recibir, se detendrá en lugar de procesar el núcleo del sistema. Esto es malo Creo que esto no es catastrófico si solo ejecuto algunas cosas útiles en mi computadora portátil, pero mucho peor si la computadora se congela cuando visito algún tipo de página web.

Por lo tanto, querían crear un mayor nivel de protección para los módulos de Native Client que el que proporciona aislamiento a nivel del sistema operativo, incluso sin errores de hardware. Entonces, con respecto a la seguridad, se comportan como paranoicos, incluido el problema de seguridad del hardware.

Veamos ahora cómo Native Client realmente aísla los procesos en el entorno limitado. Por lo tanto, Native Client adopta un enfoque diferente, que se puede llamar "aislar fallas de software".



El plan no es confiar en el hecho de que el sistema operativo o el equipo verificará las cosas mientras el programa se está ejecutando, sino confiar en que revisen las instrucciones con anticipación y decidan que pueden ejecutarse de manera completamente segura. Por lo tanto, de hecho, es suficiente mirar el archivo binario para verificar todas las instrucciones posibles y ver si serán seguras o inseguras. Una vez que haya decidido que todo estará seguro, simplemente puede comenzar el proceso porque sabe que se trata de cosas seguras y no habrá fallas.

Entonces, lo que van a hacer es mirar casi todas las instrucciones en el código binario que se envía al navegador y decidir si las instrucciones específicas son seguras o no.

? . ? , , .

- ALU , , . , . , , . , , , .



? , , . , , , . , «» , ? .

, , , - , . «» , - . , «» , . , , , , .
, ( ) . . , if , , . , , – .

, , , . . , , . , , , , «» .



. , , . , , .

, , , , - , . , , , , . Trusted Service Runtime , . . Google . , NaCl .

, , , , , — , — . , .

: , , NaCl ? , ?

: , , , NaCl . , malloc pthread_create , Trusted Service Runtime . - , Unix , - . , , JavaScript -. RPC JavaScript , .



, , NaCl Unix -, - , -.

. , Native Client . – Native Client ?

, Native Client . , , . , , x86 . , , «», .

, . , , 0 256 . , , , , .

? , ?

: , .

: , . , , . , , ? , ?

: .

: !

: -, , . .

: , . , . , , . , , , Trusted Service Runtime . , , Trusted Service Runtime , . , .

, , NaCl , . , 0. , NaCl . .

28:00

:

Curso MIT "Seguridad de sistemas informáticos". 7: « Native Client», 2


.

, . ¿Te gustan nuestros artículos? ¿Quieres ver más materiales interesantes? Apóyenos haciendo un pedido o recomendándolo a sus amigos, un descuento del 30% para los usuarios de Habr en un análogo único de servidores de nivel de entrada que inventamos para usted: toda la verdad sobre VPS (KVM) E5-2650 v4 (6 núcleos) 10GB DDR4 240GB SSD 1Gbps de $ 20 o cómo dividir el servidor? (las opciones están disponibles con RAID1 y RAID10, hasta 24 núcleos y hasta 40GB DDR4).

3 Dell R630 — 2 Intel Deca-Core Xeon E5-2630 v4 / 128GB DDR4 / 41TB HDD 2240GB SSD / 1Gbps 10 TB — $99,33 , , .

Dell R730xd 2 veces más barato? ¡Solo tenemos 2 x Intel Dodeca-Core Xeon E5-2650v4 128GB DDR4 6x480GB SSD 1Gbps 100 TV desde $ 249 en los Países Bajos y los Estados Unidos! Lea sobre Cómo construir un edificio de infraestructura. clase utilizando servidores Dell R730xd E5-2650 v4 que cuestan 9,000 euros por un centavo?

Source: https://habr.com/ru/post/es418223/


All Articles