Millones de binarios después. Cómo Linux se hizo más fuerte

Millones de binarios después. Cómo Linux se hizo más fuerteTL; DR. En este artículo, exploramos los esquemas de refuerzo que funcionan de forma inmediata en cinco distribuciones populares de Linux. Para cada uno, tomamos la configuración predeterminada del kernel, cargamos todos los paquetes y analizamos los esquemas de seguridad en los archivos binarios adjuntos. Las distribuciones consideradas son OpenSUSE 12.4, Debian 9, CentOS, RHEL 6.10 y 7, así como Ubuntu 14.04, 12.04 y 18.04 LTS.

Los resultados confirman que incluso los esquemas básicos como el apilamiento de canarios y el código independiente de la posición aún no son adoptados por todos. La situación es aún peor para los compiladores cuando se trata de protegerse contra vulnerabilidades como el choque de pilas, que saltó a la luz en enero después de su publicación. información sobre vulnerabilidades de systemd. Pero no todo es tan desesperado. Una cantidad significativa de binarios implementa métodos de protección básicos y su número crece de una versión a otra.

La revisión mostró que la mayor cantidad de métodos de protección se implementa en Ubuntu 18.04 a nivel de sistema operativo y aplicación, seguido de Debian 9. Por otro lado, OpenSUSE 12.4, CentOS 7 y RHEL 7 también implementan esquemas de protección básicos y protección contra colisiones de pila. se utiliza aún más ampliamente con un conjunto mucho más denso de paquetes predeterminados.

introducción

Es difícil garantizar un software de alta calidad. A pesar de la gran cantidad de herramientas avanzadas para el análisis de código estático y el análisis dinámico del tiempo de ejecución, así como de los importantes avances en el desarrollo de compiladores y lenguajes de programación, el software moderno todavía sufre de vulnerabilidades que los atacantes explotan constantemente. La situación es aún peor en ecosistemas que incluyen código heredado. En tales casos, no sólo nos enfrentamos al eterno problema de encontrar posibles errores explotables, sino que también estamos limitados por estrictos marcos de compatibilidad con versiones anteriores, que a menudo nos exigen preservar un código limitado, o peor aún, vulnerable o con errores.

Aquí es donde entran en juego los métodos para proteger o reforzar los programas. No podemos prevenir algunos tipos de errores, pero sí podemos hacerle la vida más difícil al atacante y solucionar parcialmente el problema previniendo o previniendo Operativo estos errores. Esta protección se utiliza en todos los sistemas operativos modernos, pero los métodos difieren mucho en complejidad, eficiencia y rendimiento: desde stack canaries y ASLR a la protección total CFI и ROP. En este artículo, veremos qué métodos de protección se utilizan en las distribuciones de Linux más populares en la configuración predeterminada y también examinaremos las propiedades de los archivos binarios que se distribuyen a través de los sistemas de administración de paquetes de cada distribución.

CVE y seguridad

Todos hemos visto artículos con títulos como "Las aplicaciones más vulnerables del año" o "Los sistemas operativos más vulnerables". Por lo general, proporcionan estadísticas sobre el número total de registros sobre vulnerabilidades como CVE (vulnerabilidades y exposiciones comunes), obtenido de Base de datos nacional de vulnerabilidad (NVD) de NIST y otras fuentes. Posteriormente, estas aplicaciones u SO se clasifican según el número de CVE. Desafortunadamente, si bien los CVE son muy útiles para rastrear problemas e informar a proveedores y usuarios, dicen poco sobre la seguridad real del software.

Como ejemplo, consideremos el número total de CVE en los últimos cuatro años para el kernel de Linux y las cinco distribuciones de servidores más populares, a saber, Ubuntu, Debian, Red Hat Enterprise Linux y OpenSUSE.

Millones de binarios después. Cómo Linux se hizo más fuerte
La figura. 1

¿Qué nos dice este gráfico? ¿Un mayor número de CVE significa que una distribución es más vulnerable que otra? Sin respuesta. Por ejemplo, en este artículo verá que Debian tiene mecanismos de seguridad más sólidos en comparación con, digamos, OpenSUSE o RedHat Linux y, sin embargo, Debian tiene más CVE. Sin embargo, no necesariamente significan una seguridad debilitada: incluso la presencia de un CVE no indica si una vulnerabilidad es explotado. Las puntuaciones de gravedad proporcionan una indicación de cómo probablemente explotación de una vulnerabilidad, pero en última instancia la explotabilidad depende en gran medida de las protecciones presentes en los sistemas afectados y de los recursos y capacidades de los atacantes. Además, la ausencia de informes CVE no dice nada sobre los demás. no registrado o desconocido vulnerabilidades. La diferencia en CVE puede deberse a factores distintos a la calidad del software, incluidos los recursos asignados a las pruebas o el tamaño de la base de usuarios. En nuestro ejemplo, el mayor número de CVE de Debian puede simplemente indicar que Debian incluye más paquetes de software.

Por supuesto, el sistema CVE proporciona información útil que le permite crear protecciones adecuadas. Cuanto mejor comprendamos las razones del fracaso del programa, más fácil será identificar posibles métodos de explotación y desarrollar mecanismos apropiados. detección y respuesta. En la Fig. 2 muestra las categorías de vulnerabilidades para todas las distribuciones durante los últimos cuatro años (fuente). Queda inmediatamente claro que la mayoría de los CVE se clasifican en las siguientes categorías: denegación de servicio (DoS), ejecución de código, desbordamiento, corrupción de memoria, fuga de información (exfiltración) y escalada de privilegios. Aunque muchos CVE se cuentan varias veces en diferentes categorías, en general los mismos problemas persisten año tras año. En la siguiente parte del artículo, evaluaremos el uso de varios esquemas de protección para evitar la explotación de estas vulnerabilidades.

Millones de binarios después. Cómo Linux se hizo más fuerte
La figura. 2

Tareas

En este artículo pretendemos responder a las siguientes preguntas:

  • ¿Cuál es la seguridad de las diferentes distribuciones de Linux? ¿Qué mecanismos de protección existen en las aplicaciones del kernel y del espacio de usuario?
  • ¿Cómo ha cambiado la adopción de mecanismos de seguridad a lo largo del tiempo en todas las distribuciones?
  • ¿Cuáles son las dependencias promedio de paquetes y bibliotecas para cada distribución?
  • ¿Qué protecciones se implementan para cada binario?

Selección de distribuciones

Resulta que es difícil encontrar estadísticas precisas sobre las instalaciones de distribución, ya que en la mayoría de los casos el número de descargas no indica el número de instalaciones reales. Sin embargo, las variantes de Unix constituyen la mayoría de los sistemas de servidores (en servidores web el 69,2%, en comparación con estadísticas W3techs y otras fuentes), y su participación crece constantemente. Por lo tanto, para nuestra investigación nos centramos en las distribuciones disponibles listas para usar en la plataforma. Google Cloud. En particular, seleccionamos el siguiente sistema operativo:

Distribución/versión
núcleo
Construir

OpenSUSE 12.4
4.12.14-95.3-predeterminado
#1 SMP miércoles 5 de diciembre 06:00:48 UTC 2018 (63a8d29)

Debian 9 (estiramiento)
4.9.0-8-amd64
#1 SMP Debian 4.9.130-2 (2018-10-27)

6.10 CentOS
2.6.32-754.10.1.el6.x86_64
#1 SMP Martes 15 de enero 17:07:28 UTC 2019

7 CentOS
3.10.0-957.5.1.el7.x86_64
#1 SMP Viernes 1 de febrero 14:54:57 UTC 2019

Servidor Red Hat Enterprise Linux 6.10 (Santiago)
2.6.32-754.9.1.el6.x86_64
#1 SMP miércoles 21 de noviembre 15:08:21 EST 2018

Servidor Red Hat Enterprise Linux 7.6 (Maipo)
3.10.0-957.1.3.el7.x86_64
#1 SMP Jueves 15 de noviembre 17:36:42 UTC 2018

Ubuntu 14.04 (Trusty Tahr)
4.4.0–140-genérico

#166~14.04.1-Ubuntu SMP sábado 17 de noviembre 01:52:43 UTC 20…

Ubuntu 16.04 (Xenial Xerus)
4.15.0–1026-gcp
#27~16.04.1-Ubuntu SMP viernes 7 de diciembre 09:59:47 UTC 2018

Ubuntu 18.04 (Castor biónico)
4.15.0–1026-gcp
#27-Ubuntu SMP jueves 6 de diciembre 18:27:01 UTC 2018

Tabla 1

análisis de

Estudiemos la configuración predeterminada del kernel, así como las propiedades de los paquetes disponibles a través del administrador de paquetes de cada distribución listo para usar. Por lo tanto, solo consideramos paquetes de las réplicas predeterminadas de cada distribución, ignorando los paquetes de repositorios inestables (como las réplicas de 'prueba' de Debian) y los paquetes de terceros (como los paquetes de Nvidia de las réplicas estándar). Además, no consideramos compilaciones de kernel personalizadas ni configuraciones reforzadas con seguridad.

Análisis de configuración del kernel

Se aplicó un guión de análisis basado en comprobador kconfig gratuito. Veamos los parámetros de protección listos para usar de las distribuciones nombradas y compárelos con la lista de Proyecto central de autodefensa (KSPP). Para cada opción de configuración, la Tabla 2 describe la configuración deseada: la casilla de verificación es para distribuciones que cumplen con las recomendaciones de KSSP (consulte lo siguiente para obtener una explicación de los términos). aquí; En futuros artículos explicaremos cuántos de estos métodos de seguridad surgieron y cómo hackear un sistema en su ausencia).

Millones de binarios después. Cómo Linux se hizo más fuerte

Millones de binarios después. Cómo Linux se hizo más fuerte

En general, los nuevos núcleos tienen configuraciones más estrictas listas para usar. Por ejemplo, CentOS 6.10 y RHEL 6.10 en el kernel 2.6.32 carecen de la mayoría de las características críticas implementadas en kernels más nuevos, como SMAP, estrictos permisos RWX, aleatorización de direcciones o protección copy2usr. Cabe señalar que muchas de las opciones de configuración de la tabla no están disponibles en versiones anteriores del kernel y no son aplicables en la realidad; esto todavía se indica en la tabla como una falta de protección adecuada. Del mismo modo, si una opción de configuración no está presente en una versión determinada y la seguridad requiere que esa opción esté deshabilitada, esto se considera una configuración razonable.

Otro punto a considerar al interpretar los resultados: algunas configuraciones del kernel que aumentan la superficie de ataque también se pueden utilizar por motivos de seguridad. Dichos ejemplos incluyen uprobes y kprobes, módulos del kernel y BPF/eBPF. Nuestra recomendación es utilizar los mecanismos anteriores para brindar una protección real, ya que su uso no es trivial y su explotación supone que los actores maliciosos ya se han establecido en el sistema. Pero si estas opciones están habilitadas, el administrador del sistema debe monitorear activamente el abuso.

Si analizamos más a fondo las entradas de la Tabla 2, vemos que los núcleos modernos ofrecen varias opciones para protegerse contra la explotación de vulnerabilidades como la fuga de información y los desbordamientos de pila/montón. Sin embargo, notamos que incluso las distribuciones populares más recientes aún no han implementado una protección más compleja (por ejemplo, con parches seguridad) o protección moderna contra ataques de reutilización de código (p. ej. combinación de aleatorización con esquemas como R^X para código). Para empeorar las cosas, incluso estas defensas más avanzadas no protegen contra toda la gama de ataques. Por lo tanto, es fundamental que los administradores de sistemas complementen las configuraciones inteligentes con soluciones que ofrezcan detección y prevención de exploits en tiempo de ejecución.

Análisis de aplicaciones

No es sorprendente que diferentes distribuciones tengan diferentes características de paquete, opciones de compilación, dependencias de biblioteca, etc. Existen diferencias incluso para relacionado distribuciones y paquetes con una pequeña cantidad de dependencias (por ejemplo, coreutils en Ubuntu o Debian). Para evaluar las diferencias, descargamos todos los paquetes disponibles, extrajimos su contenido y analizamos los binarios y las dependencias. Para cada paquete, realizamos un seguimiento de los otros paquetes de los que depende y, para cada binario, realizamos un seguimiento de sus dependencias. En esta sección resumimos brevemente las conclusiones.

Distribuciones

En total, descargamos 361 paquetes para todas las distribuciones, extrayendo solo paquetes de las réplicas predeterminadas. Ignoramos los paquetes sin ejecutables ELF, como fuentes, fuentes, etc. Después del filtrado, quedaron 556 paquetes, que contenían un total de 129 binarios. La distribución de paquetes y archivos entre distribuciones se muestra en la Fig. 569.

Millones de binarios después. Cómo Linux se hizo más fuerte
La figura. 3

Podrás notar que cuanto más moderna es la distribución, más paquetes y binarios contiene, lo cual es lógico. Sin embargo, los paquetes de Ubuntu y Debian incluyen muchos más binarios (tanto ejecutables como módulos y bibliotecas dinámicas) que CentOS, SUSE y RHEL, lo que potencialmente afecta la superficie de ataque de Ubuntu y Debian (cabe señalar que los números reflejan todos los binarios de todas las versiones). paquete, es decir, algunos archivos se analizan varias veces). Esto es especialmente importante cuando consideras las dependencias entre paquetes. Por tanto, una vulnerabilidad en un único paquete binario puede afectar a muchas partes del ecosistema, del mismo modo que una biblioteca vulnerable puede afectar a todos los binarios que la importan. Como punto de partida, veamos la distribución del número de dependencias entre paquetes en diferentes sistemas operativos:

Millones de binarios después. Cómo Linux se hizo más fuerte
La figura. 4

En casi todas las distribuciones, el 60% de los paquetes tienen al menos 10 dependencias. Además, algunos paquetes tienen un número significativamente mayor de dependencias (más de 100). Lo mismo se aplica a las dependencias inversas de paquetes: como era de esperar, algunos paquetes son utilizados por muchos otros paquetes en la distribución, por lo que las vulnerabilidades en esos pocos seleccionados son de alto riesgo. A modo de ejemplo, la siguiente tabla enumera los 20 paquetes con el número máximo de dependencias inversas en SLES, Centos 7, Debian 9 y Ubuntu 18.04 (cada celda indica el paquete y el número de dependencias inversas).

Millones de binarios después. Cómo Linux se hizo más fuerte
Tabla 3

Dato interesante. Aunque todos los sistemas operativos analizados están diseñados para la arquitectura x86_64 y la mayoría de los paquetes tienen la arquitectura definida como x86_64 y x86, los paquetes a menudo contienen archivos binarios para otras arquitecturas, como se muestra en la Figura 5. XNUMX.

Millones de binarios después. Cómo Linux se hizo más fuerte
La figura. 5

En el siguiente apartado profundizaremos en las características de los binarios analizados.

Estadísticas de protección de archivos binarios

Como mínimo absoluto, necesita explorar un conjunto básico de opciones de seguridad para sus archivos binarios existentes. Varias distribuciones de Linux vienen con scripts que realizan dichas comprobaciones. Por ejemplo, Debian/Ubuntu tiene un script de este tipo. Aquí un ejemplo de su trabajo:

$ hardening-check $(which docker)
/usr/bin/docker:
 Position Independent Executable: yes
 Stack protected: yes
 Fortify Source functions: no, only unprotected functions found!
 Read-only relocations: yes
 Immediate binding: yes

El guión marca cinco funciones de protección:

  • Ejecutable independiente de posición (PIE): indica si la sección de texto de un programa se puede mover en la memoria para lograr la aleatorización si ASLR está habilitado en el kernel.
  • Pila protegida: si los canarios de pila están habilitados para proteger contra ataques de colisión de pila.
  • Fortificar fuente: si las funciones no seguras (por ejemplo, strcpy) se reemplazan con sus contrapartes más seguras y las llamadas verificadas en tiempo de ejecución se reemplazan con sus contrapartes no verificadas (por ejemplo, memcpy en lugar de __memcpy_chk).
  • Reubicaciones de solo lectura (RELRO): si las entradas de la tabla de reubicación se marcan como de solo lectura si se activan antes de que comience la ejecución.
  • Enlace inmediato: si el vinculador en tiempo de ejecución permite todos los movimientos antes de que comience la ejecución del programa (esto es equivalente a un RELRO completo).

¿Son suficientes los mecanismos anteriores? Lamentablemente no. Hay formas conocidas de eludir todas las defensas anteriores, pero cuanto más dura sea la defensa, más alto será el listón para el atacante. Por ejemplo, Métodos de derivación de RELRO más difícil de aplicar si están en vigor el PIE y la vinculación inmediata. Del mismo modo, el ASLR completo requiere trabajo adicional para crear un exploit que funcione. Sin embargo, los atacantes sofisticados ya están preparados para cumplir con dichas protecciones: su ausencia esencialmente acelerará el ataque. Por tanto, es fundamental que estas medidas se consideren necesarias. mínimo.

Queríamos estudiar cuántos archivos binarios de las distribuciones en cuestión están protegidos por estos y otros tres métodos:

  • Bit no ejecutable (NX) impide la ejecución en cualquier región que no debería ser ejecutable, como el montón de pila, etc.
  • RUTA/RUTA DE EJECUCIÓN denota la ruta de ejecución utilizada por el cargador dinámico para encontrar bibliotecas coincidentes. El primero es obligatorio para cualquier sistema moderno: su ausencia permite a los atacantes escribir arbitrariamente la carga útil en la memoria y ejecutarla tal cual. Para el segundo, las configuraciones incorrectas de la ruta de ejecución ayudan a introducir código no confiable que puede provocar una serie de problemas (p. ej. escalada de privilegiosy otros problemas).
  • La protección contra colisiones de pila proporciona protección contra ataques que hacen que la pila se superponga a otras áreas de la memoria (como el montón). Dados los recientes abusos vulnerabilidades de colisión del montón de systemd, sentimos que era apropiado incluir este mecanismo en nuestro conjunto de datos.

Entonces, sin más preámbulos, vayamos a los números. Las tablas 4 y 5 contienen un resumen del análisis de archivos ejecutables y bibliotecas de varias distribuciones, respectivamente.

  • Como puede ver, la protección NX se implementa en todas partes, con raras excepciones. En particular, se puede observar su uso ligeramente menor en distribuciones Ubuntu y Debian en comparación con CentOS, RHEL y OpenSUSE.
  • Los canarios de pila faltan en muchos lugares, especialmente en distribuciones con núcleos más antiguos. Se están viendo algunos avances en las últimas distribuciones de Centos, RHEL, Debian y Ubuntu.
  • Con la excepción de Debian y Ubuntu 18.04, la mayoría de las distribuciones tienen un soporte PIE deficiente.
  • La protección contra colisiones de pila es débil en OpenSUSE, Centos 7 y RHEL 7, y prácticamente inexistente en otros.
  • Todas las distribuciones con kernels modernos tienen cierto soporte para RELRO, con Ubuntu 18.04 a la cabeza y Debian en segundo lugar.

Como ya se mencionó, las métricas de esta tabla son el promedio de todas las versiones del archivo binario. Si observa solo las últimas versiones de los archivos, los números serán diferentes (por ejemplo, consulte Progreso de Debian con la implementación de PIE). Además, la mayoría de las distribuciones normalmente solo prueban la seguridad de unas pocas funciones en el binario al calcular estadísticas, pero nuestro análisis muestra el porcentaje real de funciones que están reforzadas. Por lo tanto, si 5 de 50 funciones están protegidas en un binario, le daremos una puntuación de 0,1, que corresponde al 10% de las funciones que se están fortaleciendo.

Millones de binarios después. Cómo Linux se hizo más fuerte
Tabla 4. Características de seguridad de los archivos ejecutables que se muestran en la Fig. 3 (implementación de funciones relevantes como porcentaje del número total de archivos ejecutables)

Millones de binarios después. Cómo Linux se hizo más fuerte
Tabla 5. Características de seguridad de las bibliotecas que se muestran en la Fig. 3 (implementación de funciones relevantes como porcentaje del número total de bibliotecas)

Entonces ¿hay progreso? Definitivamente lo hay: esto se puede ver en las estadísticas de distribuciones individuales (por ejemplo, Debian), así como de las tablas anteriores. Como ejemplo en la Fig. La Figura 6 muestra la implementación de mecanismos de protección en tres distribuciones sucesivas de Ubuntu LTS 5 (hemos omitido las estadísticas de protección contra colisiones de pila). Notamos que, de una versión a otra, cada vez más archivos admiten pilas canarias y también se envían cada vez más archivos binarios con protección RELRO completa.

Millones de binarios después. Cómo Linux se hizo más fuerte
La figura. 6

Desafortunadamente, varios archivos ejecutables en diferentes distribuciones todavía no tienen ninguna de las protecciones anteriores. Por ejemplo, si observa Ubuntu 18.04, notará el binario ngetty (un reemplazo de getty), así como los shells mksh y lksh, el intérprete picolisp, los paquetes nvidia-cuda-toolkit (un paquete popular para aplicaciones aceleradas por GPU). como marcos de aprendizaje automático) y klibc -utils. Del mismo modo, el binario mandos-client (una herramienta administrativa que le permite reiniciar automáticamente máquinas con sistemas de archivos cifrados) así como rsh-redone-client (una reimplementación de rsh y rlogin) se entregan sin protección NX, aunque tienen derechos SUID: (. Además, varios binarios suid carecen de protección básica, como los canarios de pila (por ejemplo, el binario Xorg.wrap del paquete Xorg).

Resumen y observaciones finales

En este artículo, hemos destacado varias características de seguridad de las distribuciones modernas de Linux. El análisis mostró que la última distribución Ubuntu LTS (18.04) implementa, en promedio, la protección más fuerte a nivel de sistema operativo y aplicaciones entre las distribuciones con kernels relativamente nuevos, como Ubuntu 14.04, 12.04 y Debian 9. Sin embargo, las distribuciones examinadas CentOS, RHEL y OpenSUSE en nuestro conjunto produce de forma predeterminada un conjunto de paquetes más denso, y en las últimas versiones (CentOS y RHEL) tienen un mayor porcentaje de protección contra colisiones de pila en comparación con los competidores basados ​​​​en Debian (Debian y Ubuntu). Al comparar las versiones de CentOS y RedHat, notamos grandes mejoras en la implementación de stack canaries y RELRO de las versiones 6 a 7, pero en promedio CentOS tiene más funciones implementadas que RHEL. En general, todas las distribuciones deberían prestar especial atención a la protección PIE, que, con excepción de Debian 9 y Ubuntu 18.04, está implementada en menos del 10% de los archivos binarios de nuestro conjunto de datos.

Finalmente, cabe señalar que, aunque realizamos la investigación manualmente, hay muchas herramientas de seguridad disponibles (p. ej. Lynis, Tigre, Hubble), que realizan análisis y ayudan a evitar configuraciones inseguras. Desafortunadamente, incluso una protección sólida en configuraciones razonables no garantiza la ausencia de exploits. Por eso creemos firmemente que es vital garantizar Monitoreo confiable y prevención de ataques en tiempo real., centrándose en los patrones de explotación y previniéndolos.

Fuente: habr.com

Añadir un comentario