Curso MIT "Seguridad de sistemas informáticos". Lección 6: "Oportunidades", parte 3

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

Público: si este UID proporciona acceso de solo lectura a este archivo, y también tiene un descriptor de archivo, entonces, si pierde el UID , ¿puede obtener permiso para leer este archivo?

Profesor: sí, ya que aparecerá en los catálogos. Porque tan pronto como agregue la función al archivo, eso es todo. Está abierto para usted con privilegios especiales, etc. Pero el problema es que tienen este diseño híbrido.

Es decir, dicen: realmente puede agregar características a los directorios y puede abrir un nuevo archivo, mientras trabaja en paralelo. Puede ser que agregue la función a un directorio, como / etc , pero no tiene acceso obligatorio a todos los archivos en el directorio / etc. Pero tan pronto como ingrese al modo de funciones, puede intentar abrir estos archivos, sabiendo que tiene acceso al directorio / etc. Después de todo, ya está abierto, así que ¿por qué no me das un archivo llamado "contraseña" ubicado en este directorio?



Y luego, el núcleo debe decidir si le permite abrir el archivo en este directorio en modo de lectura o escritura, o lo que tiene. Así que creo que este es el único lugar donde todavía necesita este privilegio externo, porque intentaron crear un diseño compatible, donde utilizaron una semántica no demasiado natural para describir el funcionamiento de los directorios. Este parece ser el único lugar donde permanecen los principios para configurar un sistema de archivos Unix .

Público: ¿hay otros lugares similares?

Profesor: buena pregunta. Creo que tendré que obtener su código fuente anterior para averiguar qué está sucediendo, pero la mayoría de las otras situaciones realmente no requieren verificación de UID . Porque, por ejemplo, no se usa para redes. Estas son probablemente las operaciones habituales del sistema de archivos: si tiene un segmento de memoria compartida, simplemente ábralo y listo.

Público: ¿podría explicar nuevamente cuál es exactamente la ID de usuario, si tiene la función de capacidad ?

Profesor: esto es importante cuando tienes la oportunidad de catalogar. La pregunta es, ¿qué le presenta esta oportunidad? Considere una interpretación, por ejemplo, el estado de las capacidades de un sistema limpio, no Capsicum . Si en dicho sistema tiene la oportunidad de un directorio, entonces tiene acceso incondicional a todos los archivos en este directorio.

En Unix, este no suele ser el caso. Puede abrir el directorio como / etc , pero tiene muchos archivos del sistema en los que se puede almacenar información confidencial, por ejemplo, la clave privada del servidor. Y el hecho de que pueda abrir y desplazarse por este directorio no significa que no pueda abrir archivos en este directorio. Es decir, al tener acceso al directorio, tiene acceso a los archivos.

En Capsicum , si abre el directorio / etc y luego ingresa al modo de función, sucede lo siguiente. Usted dice: “No sé qué es este directorio. Solo le agrego un descriptor de archivo ". Hay un archivo llamado "clave". ¿Por qué no abres este archivo "clave" ? Solo porque en ese momento, probablemente no desee que este proceso basado en características abra este archivo, porque no lo necesita. Aunque esto le permite omitir los permisos de Unix para el archivo.

Por lo tanto, creo que los autores de este artículo abordaron cuidadosamente el desarrollo de un sistema que no violaría los mecanismos de seguridad existentes.

Público: es decir, ¿dice que en algunos casos puede usar una combinación de estos dos factores de seguridad? Es decir, aunque el usuario puede cambiar el archivo en el directorio, ¿a qué archivos accede depende de su ID de usuario?

Profesor: sí, exactamente. En la práctica, en Capsicum , antes de pasar al modo de funciones, debe adivinar qué archivos puede necesitar más adelante. Es posible que necesite bibliotecas compartidas, archivos de texto, plantillas, conexiones de red, etc. Por lo tanto, abres todo esto por adelantado. Y no siempre es necesario saber qué archivo necesita. Entonces, estos tipos lo hicieron para que simplemente pueda abrir el descriptor de archivo del directorio y ver los archivos que necesita más adelante. Sin embargo, puede ser que estos archivos no tengan los mismos permisos que usted tiene. Es precisamente por esta razón que se utiliza una combinación de dos factores de seguridad: verificar las capacidades y el usuario uid . Entonces esto es parte del mecanismo del núcleo.



¿Por qué necesitan una biblioteca como libcapsicum ? Creo que hay dos cosas principales que admiten en esta biblioteca.

Una de ellas es que implementan una función llamada lch_start , que debe usar en lugar de la función cap_enter . Otra función que proporciona libcapsicum es el concepto de listas fd, que se utiliza para pasar descriptores de archivo por números. El propósito de esta lista de archivos es fácil de explicar. Esto es básicamente una generalización de cómo Unix administra y pasa descriptores de archivo entre procesos. En Unix y Linux tradicionales, que usa hoy, se le pasan algunos descriptores de archivos cuando comienza el proceso. Simplemente abra algunos descriptores de archivo con valores enteros de esta tabla e inicie el proceso secundario que necesita. O ejecuta un binario específico y hereda todos estos espacios abiertos en la tabla fd . Sin embargo, no hay otra buena manera de nombrar estas cosas que usar números como nombres.

Considere un ejemplo en el que la ranura 0 se utilizará para la entrada, la ranura 1 para la salida, la ranura 2 para imprimir mensajes de error. Así es como funciona en Unix . Y funciona bien si solo transfiere estos tres archivos o tres flujos de datos al proceso.



Pero en Capsicum, sucede que "revisas" muchos más descriptores de archivos en tu camino. Entonces, cuando pasa un descriptor de archivo para algunos archivos, pasa por un descriptor de archivo para una conexión de red, un descriptor para una biblioteca compartida que tiene, y así sucesivamente. Gestionar todos estos números es bastante tedioso. Por lo tanto, de hecho, libcapsicum proporciona la capacidad de abstraer del nombre de estos descriptores de archivos pasados ​​entre procesos usando un nombre jerárquico que se usa en lugar de estos enteros oscuros.
Esta es una de las cosas simples que proporcionan en su biblioteca. Entonces puedo pasar el descriptor de archivo al proceso y darle un nombre, no importa qué número se indique. Este método es mucho más simple.

Todavía tienen otro mecanismo de lanzamiento de caja de arena más complejo. Esta es lch , la API de host de sandbox que se usa en lugar de simplemente ingresar al modo de características de Capability . ¿Por qué necesitaban algo más que una simple entrada en un modo de oportunidad? ¿Qué es lo que generalmente te molesta al crear un sandbox?

Público: probablemente, lch borra todas las cosas heredadas para garantizar un inicio "limpio" del sistema.

Profesor: si. Creo que les preocupa tratar de tener en cuenta todo a lo que tiene acceso el sandbox. La cuestión es que, si solo llama a cap_enter , técnicamente, al nivel del mecanismo del núcleo, funcionará. Derecho? Simplemente evita que descubras nuevas oportunidades.

Pero el problema es que puede haber muchas cosas existentes a las que el proceso ya tiene acceso.

Por lo tanto, creo que el ejemplo más simple es la presencia de descriptores de archivos abiertos que olvidó, y este proceso simplemente los heredará.



Por ejemplo, consideraron tcpdump . Primero, cambiaron tcpdump simplemente llamando a cap_enter incluso antes de que estuvieran a punto de analizar todas las conexiones de red entrantes. En cierto modo, esto funciona bien porque no puede obtener más funciones de capacidad . Pero luego, mirando el descriptor de archivo abierto, se dieron cuenta de que tiene acceso completo al terminal de usuario, porque tiene un descriptor de archivo abierto para él. Para que pueda interceptar todas las pulsaciones de teclas que realiza el usuario, y similares. Por lo tanto, este probablemente no sea un buen plan para tcpdump . Porque no quieres que alguien intercepte tu actividad de teclado.

Por lo tanto, en el caso de tcpdump, cambiaron manualmente los descriptores de archivo y agregaron algunos bits de características para limitar los tipos de operaciones que puede realizar. Si recuerda, en Capsicum, la función también tiene estos bits adicionales que indican la clase de operaciones que se pueden realizar para un descriptor de archivo dado. Por lo tanto, básicamente suponen que el descriptor de archivo es 0. Apunta al terminal de usuario tty. Inicialmente, era solo un puntero directo a la estructura tty en el núcleo. Para limitar el tipo de operaciones que se pueden realizar para este descriptor, introdujeron una estructura beta intermedia de capacidades en el medio. Por lo tanto, el descriptor de archivo apunta a esta estructura de capacidad, y ya apunta al archivo real al que está intentando acceder. Y esta estructura de capacidad contiene algunos bits o permisos restrictivos para un objeto descriptor de archivo que se puede implementar.

Por lo tanto, con la entrada de datos estándar en tcpdump, no puede hacer nada con ella. Puedes ver que existe, y eso es todo. Para el descriptor del archivo de salida, proporcionaron una oportunidad cuando puede escribir algo en él, pero no puede cambiar el registro, es decir, no puede cancelar los cambios realizados.



Entonces, ¿qué más podría preocuparse por lanzar el sandbox ? Pienso en el estado del descriptor de archivo. ¿Algo más importa? Creo que en Unix estos son descriptores de archivos y memoria.

Otra cosa es que estos tipos están preocupados de que en su espacio de direcciones pueda haber datos confidenciales asignados anteriormente. Y el proceso que va a aislar en el sandbox puede leer toda la memoria disponible. Entonces, si hay algún tipo de contraseña que verificó anteriormente, cuando el usuario inicia sesión y aún no ha borrado la memoria, entonces este proceso podrá leerla y hacer algo "interesante".

Resolvieron este problema de esta manera: en lch_start tienes que ejecutar un programa "nuevo". Usted toma el programa y empaqueta todos los argumentos en él, todos los descriptores de archivo que desea proporcionarle. Luego inicia un nuevo proceso o inicia la operación de reinicialización de todo el espacio de memoria virtual. Y luego no hay duda de que este proceso no recibirá ningún privilegio adicional para afectar el conjunto de datos confidenciales. Esto es exactamente lo que pasó a la función lch_start , en términos de nombres binarios, argumentos y capacidades del programa.

Audiencia: ¿qué sucede si el proceso que inicia contiene setuid binario = 0 ?

Profesor: Creo que estos tipos no usan "binarios" setuid en el modo de función para evitar algunas interacciones extrañas que puedan aparecer. Implementan esta regla: puede tener un programa setuid que obtenga sus privilegios del binario setuid , y luego puede llamar a cap_enter o lch_start . Pero una vez que ingresa al modo de funciones, no puede restaurar preferencias adicionales.

En principio, esto podría funcionar, pero sería muy extraño. Porque, si recuerdas, lo único en lo que importa el UID cuando estás en modo de función es abrir archivos dentro de un directorio. Por lo tanto, no está claro si este es realmente un gran plan para privilegios adicionales o si tiene fallas.

Público: Anteriormente, hablamos sobre por qué la biblioteca no admite realmente una separación estricta entre los dos factores de seguridad. Pero no tenemos que usar lch_start ?

Profesor: eso es correcto. Suponga que tiene algo como tcpdump , o gzip : esta es otra cosa con la que trabajan. Asume que la aplicación probablemente no está comprometida, y que hay alguna función básica de la aplicación, y le importa cómo se comporta en el entorno limitado. En el caso de tcpdump, se trata de un análisis de paquetes que provienen de la red, en el caso de gzip se trata de descomprimir archivos. Y hasta cierto punto, asumes que el proceso está haciendo todo bien y que no habrá vulnerabilidades. Por lo tanto, confía en él para ejecutar lch_start y cree que creará correctamente la imagen, configurará correctamente todas las funciones y luego se limitará a sí mismo de cualquier otra llamada al sistema fuera del modo de capacidades.

Y luego lanzas cosas peligrosas. Pero para entonces la instalación era correcta y no tienes forma de salir de este entorno limitado. Por lo tanto, creo que necesita ver cómo puede usar el modo de función para las aplicaciones de sandbox.

Así que hablamos un poco sobre tcpdump . ¿Cómo aislar este proceso? Otro ejemplo interesante es el programa gzip , que comprime y descomprime archivos. Entonces, ¿por qué están preocupados por la caja de arena? Creo que les preocupa que el código de descompresión pueda tener errores, o que pueda haber errores en la administración de la memoria, la administración del búfer durante la descompresión, etc.



Otra pregunta interesante es ¿por qué los cambios para gzip parecen mucho más complicados que para tcpdump ? Creo que esto se debe a cómo la aplicación está estructurada internamente, ¿verdad? Por lo tanto, si tiene una aplicación que simplemente comprimió un archivo o descomprimió un archivo, entonces es normal simplemente iniciarlo sin cambiarlo en el modo de funciones. Simplemente le da un nuevo estándar para desempacar algo, y el estándar proporciona datos desempaquetados en la salida, y esto funcionará bien.

El problema, como casi siempre ocurre con tales métodos de sandbox, es que la aplicación en realidad tiene una lógica de proceso mucho más compleja. Por ejemplo, gzip puede comprimir varios archivos a la vez, y así sucesivamente. Y en este caso, tiene algún tipo de proceso líder al frente de la aplicación, que en realidad tiene derechos adicionales para abrir varios archivos, empaquetarlos, etc. Y la lógica central a menudo necesita ser otro proceso de apoyo. En el caso de gzip, la aplicación no estaba estructurada de modo que la compresión y la descompresión actuaran como procesos separados. Por lo tanto, tuvieron que cambiar la implementación del kernel gzip y alguna estructura de la aplicación en sí misma para que, además de pasar los datos a la función de descompresión, se enviaran a través de una llamada RPC o realmente se escribieran en algún tipo de descriptor de casi archivo. Esto fue para evitar que ocurran problemas de terceros y desempaquetar prácticamente sin privilegios. Lo único que gzip podía hacer al mismo tiempo era devolver los datos descomprimidos o comprimidos al proceso que lo llamó.

Otra tarea es cómo usar Capsicum en OKWS . ¿Qué opinas de esto? ¿Sería útil? ¿ Los chicos de OKWS estarían felices de actualizar a FreeBSD porque es mucho más fácil de usar? ¿Cómo usarías Capsicum en FreeBSD ?

Público: se podrían eliminar algunas restricciones estrictas.

Profesor: sí, lo podríamos reemplazar por completo con la presencia de un directorio de descriptores de archivos y capacidades. No necesitaría configurar un chroot confuso. En lugar de usar chroot con muchas cosas pequeñas, puedes establecer los permisos con cuidado. Simplemente puede abrir los archivos exactos que necesita. Así que esto parece una gran ventaja.

A continuación, en OKWS , tiene el servicio de inicio OK , que debe iniciar todos los procesos principales. Tan pronto como mueren, la señal regresa a okld para reiniciar el proceso "muerto". Y esto tendría que ejecutar root , porque tenía que aislar los procesos en el sandbox. Pero hay varias cosas en OKWS que podrían mejorarse con Capsicum .

Por ejemplo, podría proporcionar okld con muchos menos privilegios. Porque, por ejemplo, para obtener el puerto 80, necesita privilegios de root. Pero después de eso, puede poner todo lo demás de forma segura en el entorno limitado, porque los derechos de root ya no son necesarios. Entonces es genial. Quizás incluso pueda delegar al proceso el derecho de responder a las solicitudes de otra persona, por ejemplo, un proceso de monitoreo del sistema que solo tiene este descriptor de proceso o descriptor de proceso para el proceso secundario y cada vez que dicho proceso falla, comienza uno nuevo. Por lo tanto, creo que la capacidad de crear un sandbox sin privilegios de root es muy útil.

Público: puede proporcionar a cada proceso un descriptor de archivo que le permita agregar solo entradas al registro.

Profesor: sí, y eso es genial. Como dijimos la última vez, oklogd puede "estropear" el archivo de registro. Y quién sabe qué le permitirá hacer el núcleo cuando tenga el descriptor del archivo de registro. Sin embargo, podemos determinar con mayor precisión las capacidades del descriptor de archivo dándole un archivo de registro e indicando que solo puede escribir pero no buscar nada. , append-only, «» . . , , Unix .

Capsicum ?

: , , , . , , , .

: , . Capsicum , , . .

: , , okld . , .

: , . . , , Capability , . , , , , , .
, OKWS . . , , , . .

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

: , FreeBSD . , - , . FreeBSD Casper , , Capability . , «».

- , , , - , , Casper .



, «» . . , , , Casper - .

, , - . , Unix FD . , . , , .

, FreeBSD , DNS . DNS -, «». , tcpdump . tcpdump , IP-. , , DNS -.

, , DNS- DNS-, . Casper , DNS-.

, , , Capsicum? ? ? , , . Capsicum , ?

tcpdump GZIP , , . ?



: , , , . , Capability .

: , . Capsicum , , . , , . , , , , Capsicum , .

, «». , TCP — helper , , , , . , , , .

: , .

: , . . , . lth_start , . , , , - .

, , Capsicum . , , , . Unix - , .

, . , . , , . , .

, Chrome . , , , Unix, -, Unix .

, ?

: .

: . . , . , , , , .

Unix , . , . , . . , .

. Linux , setcall , , . , Capsicum , , Capsicum , . Linux setcall , . , , Linux .

, — , , , , . , - , «//», . Capsicum donde puede iniciar el proceso para un archivo específico y no para todo el directorio de inicio.


La versión completa del curso está disponible aquí .

Gracias por quedarte con nosotros. ¿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 meses gratis al pagar un nuevo Dell R630 por un período de seis meses - 2 x Intel Deca-Core Xeon E5-2630 v4 / 128GB DDR4 / 4x1TB HDD o 2x240GB SSD / 1Gbps 10 TB - desde $ 99.33 al mes , solo hasta fines de agosto, ordene es posible aquí .

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/es418221/


All Articles