Yesterday, I read this awesome post by Shay Ber here which details a feature abuse in Windows Active Directory (AD) environment. I rely heavily on feature abuse during my red team engagements and always recommend them over memory corruption exploits during my training as well. Feature abuses are as lethal as exploits and are almost always ignored.
The post details a feature abuse in AD where a user who is member of the DNSAdmins group or have write privileges to a DNS server object can load an arbitrary DLL with SYSTEM privileges on the DNS server. Since, many enterprise setups use the Domain Controller (DC) as a DNS server as well, this is a very interesting find. Let's try to see the practical usage of this feature.
This is the lab setup. We have initial access as a normal domain user (labuser) on one of the boxes in our lab AD.
Let's first enumerate users who are part of the DNSAdmins group using PowerView.
In a real red team or pentest, the next step would be to target the buildadmin user. We can find a box where token of buildadmin is available using Invoke-UserHunter from PowerView.
To keep the discussion on the topic at hand, let's assume that we found a box where a ticket of buildadmin is available and our current user (labuser) has local admin access as well (derivative admin). So, we have privileges of the user who is a member of the DNSAdmins group.
Now, there could be two scenarios - one where the DC is the DNS server as well and second, where a separate server acts as the DNS server.
For the first scenario, where the DNS Server service is running on the DC we can simply use dnscmd as mentioned in the post by Shay to load a dll. There is also a PowerShell module - dnsserver - for this but it is not well documented.
UPDATE: Benjamin confirmed that it is possible to load the DLL from UNC path. The 'C$' in my UNC path was the problem!
We can use the below command to load the DLL. The path \\ops-build\dll should be readable by the DC:
For debugging (admin rights required on the target), below command can be used to check if DLL was added successfully on the target
Now, since our user is a part of the DNSAdmins, we can restart the DNS service. While, this is NOT the default configuration, it makes sense for such a user to have the rights to restart the DNS service. But, the service restart must be done from the local box, that is, DC in the current scenario. We need administrator rights to do it remotely - the attack gets more typical and hard to execute :(
So what do we get after successfully executing the above commands? Benjamin quickly updated mimilib to be used with this attack. The updated version of mimilib when used in this attack logs all DNS queries to C:\Windows\system32\kiwidns.log
We can make changes to kdns.c to include capability of command execution. I included a simple line of code to execute a reverse PowerShell shell encoded using Invoke-Encode from Nishang. The payload gets executed for each query to the DNS service and the kiwidns.log will still be created and populated.
Neat! SYSTEM on the domain controller. We own this domain and possibly the entire forest :D
For our second scenario, if DNS service was not running on the DC we can still get SYSTEM access on the box with 'only' the privileges of DNSAdmins and restarting the DNS service.
How to detect the attack?
To prevent the attack, audit ACL for write privilege to DNS server object and membership of DNSAdmins group.
Obvious indicators like DNS service restart and couple of log entries:
DNS Server Log Event ID 150 for failure and 770 for success
Hope you liked the post. Please leave feedback and comments.