
Un write up sobre la sala Source de TryHackMe y un script de Python para explotar la vulnerabilidad
Un write-up sobre la sala Source de TryHackMe y un script de python para explotar la vulnerabilidad
No me atribuyo ningún crédito por el descubrimiento de esta vulnerabilidad. Gracias a las siguientes personas por proporcionar los recursos para que personas como yo puedan aprender.
Descubrimiento de la vulnerabilidad:
Özkan Mustafa Akkuş
Módulo de MSF:
https://github.com/rapid7/metasploit-framework/blob/master/modules/exploits/linux/http/webmin_backdoor.rb
https://www.rapid7.com/db/modules/exploit/linux/http/webmin_backdoor/
Autor del módulo de MSF:
wvu
Sala de TryHackMe:
https://tryhackme.com/room/source
Autor de THM:
https://tryhackme.com/p/DarkStar7471
Recursos:
https://www.webmin.com/exploit.html
https://github.com/webmin/webmin/issues/947
https://www.perlmonks.org/?node_id=301355
No soy, ni mucho menos, un profesional de la seguridad con experiencia. Esto significa que puedo proporcionar información incorrecta. Si eres un profesional con experiencia o un investigador experimentado y ves algo que es incorrecto, por favor infórmame para poder volver, estudiar lo que hice mal y proporcionar la información correcta. Esto es beneficioso tanto para mí como para otros investigadores novatos que puedan toparse con este write-up. Si encuentras información incorrecta que he escrito, por favor contáctame en [email protected] para poder corregirla. ¡Gracias!
1. Historia
Webmin es una herramienta basada en web para la administración de sistemas tipo Unix. En algún momento del primer trimestre de 2018, Webmin fue víctima de un ataque a la cadena de suministro en el que un atacante desconocido logró insertar código malicioso en el archivo password_change.cgi, creando una vulnerabilidad que permitía abrir una puerta trasera en cualquier sistema que estuviera ejecutando esa versión de Webmin (1.890) con la configuración predeterminada. Llamo a esto un ataque a la cadena de suministro porque los desarrolladores/distribuidores del software vieron comprometido el código fuente de sus productos. Cuando el proveedor publicó el producto comprometido, todos los que actualizaron su software quedaron ejecutando el código vulnerable, dando así al atacante la capacidad de comprometer cualquier sistema que estuviera ejecutando el código ahora vulnerable. Ese mismo año, los desarrolladores de Webmin se dieron cuenta de lo que había sucedido y revirtieron el archivo a su estado original; sin embargo, el atacante pudo insertar el código nuevamente. Esta vez, el código solo sería vulnerable si la opción de cambiar contraseñas caducadas estaba habilitada. Esta vulnerabilidad no se descubriría hasta agosto de 2019. La vulnerabilidad se parcheó en la versión 1.930 de Webmin.
2. El código
Después de buscar un poco, pude encontrar la línea de código que hacía vulnerable a la versión 1.890 de Webmin a la inyección de comandos. Me costaba encontrar la información correcta porque en realidad hay dos CVE diferentes asociados con este problema (CVE-2019-15231/CVE-2019-15107). CVE-2019-15231 se relaciona con la vulnerabilidad de la configuración predeterminada en la versión 1.890, y CVE-2019-15107 se relaciona con la vulnerabilidad que requiere que la opción de cambiar contraseñas caducadas esté habilitada en versiones hasta la 1.920. Echemos un vistazo al código de la versión 1.890. En la línea 12 de password_change.cgi, tenemos la siguiente línea de código:
$in{'expired'} eq '' || die $text{'password_expired'},qx/$in{'expired'}/;
Al momento de escribir esto, nunca he escrito nada en perl. Vamos a diseccionar esta línea de código usando motores de búsqueda para entender mejor qué hace el código y por qué es vulnerable a la explotación. La primera parte del código a la izquierda del operador || parece ser una variable ($in) que toma un parámetro (expired) y comprueba si es igual (eq) a una cadena vacía ''. En el medio, tenemos el operador ||. El || es otra forma de usar el operador lógico or en perl. Cuando se usa || en perl, si el lado izquierdo del operador es verdadero, la mitad derecha no se evaluará. Si la mitad izquierda es falsa, entonces se evaluará la mitad derecha. En la primera mitad del código a la derecha del operador , podemos ver . En perl, es una función que mata el proceso del script y muestra un mensaje de error. El mensaje sería presumiblemente la variable diciendo que la contraseña ha caducado. La última parte del código es donde se pone interesante. Vemos que tenemos una coma seguida de y un punto y coma que termina la línea de código. La coma actúa como separador del código: la mitad izquierda se evaluará primero y luego se evaluará la segunda mitad. En perl, es una función que permite ejecutar comandos del sistema en el host. Las son delimitadores utilizados para identificar el parámetro. En este caso, tenemos , que ejecutará el parámetro como un comando del sistema. Creo que la variable podría ser algo similar a en php por la siguiente razón. En el script de exploit que escribí, tenemos un parámetro llamado que almacena el payload antes de ser enviado al servidor mediante una petición post. Así es como se ve ese código: . La variable debe estar haciendo algo para recuperar el valor que establecimos en para que el payload pueda ser ejecutado por la función . Para resumir esta sección, la línea de código vulnerable detecta que nuestro parámetro en la petición post no es igual a una cadena vacía, por lo que el operador ahora evaluará la mitad derecha del código y ejecutará nuestro payload almacenado en el parámetro . Pasemos al write-up de la sala Source de TryHackMe.com.
Comencemos con un escaneo de puertos. Usaremos rustscan para obtener una visión general amplia porque nmap puede ser dolorosamente lento.

Parece que tenemos 2 puertos abiertos: 22 y 10000. Ahora usaremos nmap para averiguar qué servicios se están ejecutando en cada puerto.

Así que tenemos SSH ejecutándose en su puerto estándar y un servicio HTTP ejecutándose en el puerto 10000. Naveguemos a la página que se ejecuta en el puerto 10000 y veamos qué hay allí.

Necesitarás usar HTTPS y omitir la advertencia del certificado SSL para acceder a esta página. Parece que tenemos una página de inicio de sesión para el servicio Webmin. Cuando hice originalmente esta máquina, probé algunos intentos de fuerza bruta de directorios, pero no apareció nada interesante. Veamos si hay una vulnerabilidad para la versión de webmin que obtuvimos del escaneo de nmap mediante searchsploit.

Parece que tenemos algunas opciones diferentes aquí, sin embargo, ninguna es igual a nuestra versión. Abramos MSF y veamos con qué tenemos que trabajar.

Tenemos algunas opciones diferentes para elegir aquí. Busquemos la versión de webmin que obtuvimos de nmap y veamos si aparecen algunos CVE que nos ayuden a reducir esto.

En el resumen de la vulnerabilidad, vemos que menciona algo sobre el archivo password_change.cgi. Usemos el número 5 de nuestra búsqueda en MSF, ya que también menciona el archivo password_change.cgi, así como la misma fecha de divulgación.

¡Lol, en realidad no vamos a usar MSF! MSF es bueno, pero no es tan divertido como descubrir cómo explotar algo con tu propio código. Usé el código fuente de ruby como referencia para este exploit para crear mi propio código de exploit en python. ¡Usemos eso en su lugar!

¡Bada-bing, bada-boom! Conseguimos una shell de root en la sala. No voy a revelar las flags. ¡Estoy seguro de que puedes encontrarlas! Gracias por leer y que tengas un buen día.
||die $text{'password_expired'}die$text,qx/$in{'expired'}/;qx//qx/$in{'expired'}/$in{'expired'}$in$_GETexpireddata = {'expired':payload,}$inexpiredqxexpired||expired