Vulnerabilidad de raíz en el kernel de Linux y denegación de servicio en systemd

Los investigadores de seguridad de Qualys han revelado detalles de dos vulnerabilidades que afectan al kernel de Linux y al administrador del sistema systemd. Una vulnerabilidad en el kernel (CVE-2021-33909) permite a un usuario local lograr la ejecución de código con derechos de root mediante la manipulación de directorios altamente anidados.

El peligro de la vulnerabilidad se ve agravado por el hecho de que los investigadores pudieron preparar exploits que funcionan en Ubuntu 20.04/20.10/21.04, Debian 11 y Fedora 34 en la configuración predeterminada. Cabe señalar que no se han probado otras distribuciones, pero en teoría también son susceptibles al problema y pueden ser atacadas. Se promete publicar el código completo de los exploits una vez que se elimine el problema en todas partes, pero por ahora sólo está disponible un prototipo de funcionalidad limitada, lo que provoca que el sistema falle. El problema ha estado presente desde julio de 2014 y afecta a las versiones del kernel a partir de la 3.16. La corrección de la vulnerabilidad se coordinó con la comunidad y se aceptó en el kernel el 19 de julio. Las principales distribuciones ya han generado actualizaciones de sus paquetes de kernel (Debian, Ubuntu, Fedora, RHEL, SUSE, Arch).

La vulnerabilidad se debe a que no se verifica el resultado de una conversión de size_t a int antes de realizar operaciones en el código seq_file, que crea archivos a partir de una secuencia de registros. Si no se realiza la verificación, se pueden producir escrituras fuera de los límites en el búfer al crear, montar y eliminar una estructura de directorios muy anidada (tamaño de ruta superior a 1 GB). Como resultado, un atacante puede lograr una cadena de 10 bytes "//eliminada" escrita en un desplazamiento de "-2 GB - 10 bytes" que apunte al área inmediatamente anterior al búfer asignado.

El exploit preparado requiere 5 GB de memoria y 1 millón de inodos libres para funcionar. El exploit funciona llamando a mkdir() para crear una jerarquía de aproximadamente un millón de subdirectorios para lograr un tamaño de ruta de archivo superior a 1 GB. Este directorio se monta mediante bind-mount en un espacio de nombres de usuario separado, después de lo cual se ejecuta la función rmdir() para eliminarlo. Paralelamente, se crea un hilo que carga un pequeño programa eBPF, que se bloquea en la etapa después de verificar el pseudocódigo de eBPF, pero antes de su compilación JIT.

En el espacio de nombres de ID de usuario sin privilegios, se abre el archivo /proc/self/mountinfo y se lee la ruta larga del directorio montado en el enlace, lo que da como resultado que la cadena "//deleted" se escriba en el área antes del inicio del búfer. La posición para escribir la línea se elige de modo que sobrescriba la instrucción en el programa eBPF ya probado pero aún no compilado.

A continuación, en el nivel del programa eBPF, la escritura incontrolada fuera del búfer se transforma en una capacidad controlada para leer y escribir en otras estructuras del núcleo mediante la manipulación de las estructuras btf y map_push_elem. Como resultado, el exploit determina la ubicación del buffer modprobe_path[] en la memoria del kernel y sobrescribe la ruta “/sbin/modprobe” en él, lo que le permite iniciar el lanzamiento de cualquier archivo ejecutable con derechos de root en caso de un llamada request_module(), que se ejecuta, por ejemplo, al crear el socket netlink.

Los investigadores ofrecen varias soluciones que son efectivas sólo para un exploit específico, pero que no eliminan el problema en sí. Se recomienda configurar "/proc/sys/kernel/unprivileged_userns_clone" en 0 para deshabilitar los directorios de montaje en un espacio de nombres de ID de usuario separado, y "/proc/sys/kernel/unprivileged_bpf_disabled" en 1 para deshabilitar la carga de programas eBPF en el kernel.

Cabe destacar que mientras analizaban un ataque alternativo que implicaba el uso del mecanismo FUSE en lugar de bind-mound para montar un directorio grande, los investigadores encontraron otra vulnerabilidad (CVE-2021-33910) que afectaba al administrador del sistema systemd. Resultó que al intentar montar un directorio con un tamaño de ruta superior a 8 MB a través de FUSE, el proceso de inicialización de control (PID1) se queda sin memoria de pila y falla, lo que pone al sistema en un estado de "pánico".

El problema es 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(), que realiza una operación strdupa() que coloca los datos en la pila en lugar de en la memoria asignada dinámicamente. . Dado que el tamaño máximo de pila está limitado mediante RLIMIT_STACK, procesar una ruta demasiado grande hasta el punto de montaje provoca que el proceso PID1 falle y detenga el sistema. Para un ataque, puede utilizar el módulo FUSE más simple en combinación con el uso de un directorio altamente anidado como punto de montaje, cuyo tamaño de ruta exceda los 8 MB.

El problema viene apareciendo desde systemd 220 (abril de 2015), ya ha sido solucionado en el repositorio principal de systemd y solucionado en distribuciones (Debian, Ubuntu, Fedora, RHEL, SUSE, Arch). En particular, en la versión 248 de systemd el exploit no funciona debido a un error en el código de systemd que hace que falle el procesamiento de /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 kernel de Linux, los investigadores de Qualys encontraron tres vulnerabilidades críticas en systemd.

Fuente: opennet.ru

Añadir un comentario