Vulnerabilidad Root en el núcleo de Linux y denegación de servicio en systemd

Investigadores de seguridad de la empresa Qualys han revelado los detalles de dos vulnerabilidades que afectan al núcleo de Linux y al gestor de sistemas systemd. La vulnerabilidad en el núcleo (CVE-2021-33909) permite a un usuario local ejecutar código con privilegios de root a través de manipulaciones en directorios con un alto nivel de anidamiento.

El peligro de la vulnerabilidad se agrava por el hecho de que los investigadores han conseguido preparar exploits funcionales que funcionan en Ubuntu 20.04/20.10/21.04, Debian 11 y Fedora 34 en la configuración por defecto. Se señala que otras distribuciones no han sido verificadas, pero teóricamente también podrían estar afectadas y ser atacadas. Se promete publicar el código completo de los exploits después de que se resuelva el problema de manera generalizada, mientras que solo está disponible un prototipo limitado en funcionalidad que provoca el colapso del sistema. El problema ha estado presente desde julio de 2014 y afecta a las versiones del núcleo a partir de la 3.16. La corrección de la vulnerabilidad fue coordinada con la comunidad y aceptada en el núcleo el 19 de julio. Las principales distribuciones ya han creado actualizaciones de paquetes con el núcleo (Debian, Ubuntu, Fedora, RHEL, SUSE, Arch).

La vulnerabilidad es causada por la falta de verificación del resultado de la conversión de tipo size_t a int antes de realizar operaciones en el código seq_file, que se encarga de crear archivos a partir de secuencias de registros. La ausencia de esta verificación puede resultar en la escritura fuera de los límites del búfer al crear, montar y eliminar estructuras de directorios con un alto nivel de anidamiento (tamaño de ruta superior a 1 GB). Como resultado, el atacante puede lograr escribir una cadena de 10 bytes «//deleted» con un desplazamiento de «-2 GB - 10 bytes», apuntando a un área inmediatamente anterior al búfer asignado.

El exploit preparado requiere 5 GB de memoria y 1 millón de inodes libres. La operación del exploit se reduce a crear, mediante la llamada mkdir(), una jerarquía de alrededor de un millón de directorios anidados para alcanzar un tamaño de ruta de archivo que supere 1 GB. Este directorio se monta a través de bind-mount en un espacio de nombres separado de identificadores de usuarios (user namespace), tras lo cual se inicia la función rmdir() para su eliminación. Paralelamente, se crea un hilo que carga un pequeño programa eBPF, que se bloquea en la etapa posterior a la verificación del pseudocódigo eBPF, pero antes de su JIT-compilación.

En el espacio de nombres no privilegiado de los identificadores de usuario, se abre el archivo /proc/self/mountinfo y comienza la lectura de la larga ruta del directorio montado mediante bind-mount, lo que lleva a grabar la cadena «//deleted» en el área antes del inicio del búfer. La posición para grabar la cadena se elige de tal manera que sobrescriba una instrucción en un programa eBPF ya verificado pero aún no compilado.

A continuación, a nivel del programa eBPF, una grabación fuera del búfer no controlada se transforma en una capacidad gestionada de lectura y escritura en otras estructuras del núcleo a través de la manipulación de las estructuras btf y map_push_elem. Como resultado, el exploit determina la ubicación del búfer modprobe_path[] en la memoria del núcleo y sobrescribe en él la ruta «/sbin/modprobe», lo que permite iniciar la ejecución de cualquier archivo ejecutable con privilegios de root en caso de que se realice la llamada request_module(), que se ejecuta, por ejemplo, al crear un socket netlink.

Los investigadores presentan varios métodos de elusión de protección que son efectivos solo para este exploit específico, pero no eliminan el problema en sí. Se recomienda establecer el parámetro «/proc/sys/kernel/unprivileged_userns_clone» en 0 para prohibir el montaje de directorios en un espacio de nombres de identificadores de usuarios separado, así como «/proc/sys/kernel/unprivileged_bpf_disabled» en 1 para prohibir la carga de programas eBPF en el núcleo.

Es notable que al explorar una alternativa de ataque relacionada con el uso del mecanismo FUSE en lugar de bind-mount para montar un gran directorio, los investigadores se encontraron con otra vulnerabilidad (CVE-2021-33910) que afecta al gestor de sistemas systemd. Resultó que al intentar montar a través de FUSE un directorio con un tamaño de ruta que supera los 8 MB, el proceso de inicialización de control (PID1) experimenta un agotamiento de la memoria de pila, provocando un fallo que lleva al sistema a un estado de «panic».

El problema está relacionado con el hecho de que systemd rastrea y analiza el contenido de /proc/self/mountinfo, y procesa cada punto de montaje en la función unit_name_path_escape(), donde se realiza la operación strdupa(), que coloca los datos en la pila, y no en memoria asignada dinámicamente. Dado que el tamaño máximo de la pila está limitado a través de RLIMIT_STACK, procesar una ruta de punto de montaje demasiado larga provoca el fallo del proceso PID1 y la detención del sistema. Para el ataque, se puede utilizar un módulo FUSE básico junto con un directorio con un alto nivel de anidamiento como punto de montaje, cuya ruta supera los 8 MB.

El problema se manifiesta desde systemd 220 (abril de 2015), ya ha sido solucionado en el repositorio principal de systemd y corregido en las distribuciones (Debian, Ubuntu, Fedora, RHEL, SUSE, Arch). Es notable que en la versión 248 de systemd el exploit no funciona debido a un error en el código de systemd que provoca fallos al procesar /proc/self/mountinfo. También es interesante que en 2018 surgió una situación similar y al intentar escribir un exploit para la vulnerabilidad CVE-2018-14634 en el núcleo de Linux, los investigadores de Qualys encontraron tres vulnerabilidades críticas en systemd.

Fuente: opennet.ru

Compra un hosting fiable para sitios web con protección contra DDoS, servidores VPS VDS 🔥 Compra un hosting fiable para sitios web con protección contra DDoS, servidores VPS VDS | ProHoster