Security Compliance checking with PowerShell: DNS

I guess most of you will agree that DNS is a critical component in a Windows infrastructure. It's not only the basis for a good working AD, but also the first target for anybody who wants to attack your systems and communication-channels, using Man-in-the-Middle techniques.  E.g., suppose an (internal) hacker could advertise a compromised system as your company portal or proxy server by changing the A-records? Or inserting false A-records?

If your DNS configuration is not secure, these types of attacks are easy to perform. E.g. if you allow un-authenticated and un-authorized updates in a DNS zone, an attacker could insert e.g. an A-record for the "" (wpad = Web Proxy Autodiscovery Protocol) which points to a malicious proxy that could intercept all internet traffic for those clients whose internet proxy settings are not explicitly configured ("automatically detect settings" is enabled in the browser). And when an attacker succeeds in bringing down your DNS servers, Active Directory will stop functioning too ...

Security configuration settings for the DNS role in Windows Server 2008 R2 can be found in 2 areas. First, there is the server configuration itself for which you can configure for example the setting "Configure DNS to Configure DNS to ignore non-authoritative resource records" (a.k.a. cache poisoning).

This setting is enabled by default, but you do want to ensure that it stays enabled. The setting can be found under the "advanced" tab of the DNS server properties:


To validate if this setting is set correctly using powershell, you can use the "SecureResponses" property of the DNS-server WMI object. The script below can be used to check on the local host.

$DNSServer = Get-WmiObject -Namespace "root\MicrosoftDNS" -Class "MicrosoftDNS_Server"

if ($DNSServer.SecureResponses) {

   $result = "DNS Option *Secure Cache Against Pollution* is enabled on server."




  $result = "DNS Option *Secure Cache Against Pollution* is not enabled on server."












(run this script using a PowerShell prompt that runs with elevated privileges; see also at the end of this post).

As you can see, I use the WMI interface to query the DNS configuration, since DNS role in Windows Server 2008 R2 doesn't have a direct interface for PowerShell. DNS has however very good and simple WMI support, so the scripts are straightforward to implement.

(note: the SCM Document also make recommendations about 2 other server configuration settings: "Enable recursion to only the appropriate DNS servers" and "Configure root hints for the internal DNS namespace"; these are not handled in this post).

Next, you have the security configuration settings for each DNS zone; following the best-practices in SCM documentation, following should be checked for each zone:

  • Preferably use AD-integrated DNS zone replication. This won't be possible in all environments, e.g. when you have a combination of Windows DNS and BIND.
  • DNS-zones must be configured to only allow secure dynamic updates or no dynamic updates; under no circumstances, insecure (=un-authenticated and/or not-authorized) updates should be allowed.
  • Restrict Zone Transfers to Specific Computers Running DNS

Some other recommendations will be handled in a next post in this blog. Specifically checks about role-combinations and use of Windows Server CORE amongst other server security recommendations that apply to multiple server roles. Specifically for DNS, we can already identify:

  • Combine DNS with DC: only a DNS that runs on a DC, supports secure dynamic updates and the zone replications relies on the secure AD-replication mechanisms.
  • Run DNS on Windows Server CORE.

The code for the DNS security compliancy check as described above looks as follows:

# The function New-CompliancyResult is used to create an array of ps-objects that store the compliancy-checks information

Function New-CompliancyResult{ Param( [string]$Category, [string]$SubCategory, [string]$setting, [boolean]$IsCompliant ) # create a new object and set the noteproperties using a hash-table $x = New-Object PSObject -Property @{ computer = (Get-WmiObject -Class Win32_ComputerSystem).name Category = $Category SubCategory = $SubCategory Setting = $setting IsCompliant = $IsCompliant } return $x}

function CheckSecCompl-DNS { $CompliancyResList = @() #array of compliancy-checks results

 $DNSServer = Get-WmiObject -Namespace "root\MicrosoftDNS" -Class "MicrosoftDNS_Server"

 # check if the server is protected against DNS cache pollution using the property: SecureResponses

 $CompliancyResList += New-CompliancyResult "DNS" "Server Configuration" "Secure Cache Against Pollution" $DNSServer.SecureResponses

 $DNSZones = Get-WmiObject -Namespace "root\MicrosoftDNS" -Class "MicrosoftDNS_Zone" foreach ($DNSzone in $DNSZones) { $SubCategory = "DNS Zone: " + $DNSzone.Name # To check if a DNS zone only accepts secure dynamic updates, use the property: AllowUpdate # AllowUpdate can have following values: # 0: no dynamic updates allowed # 1: secure and insecure dynamic updates allowed --> not secure # 2: only secure dynamic updates allowed $CompliancyResList += New-CompliancyResult "DNS" $SubCategory "Secure or no dynamic updates" ($DNSzone.AllowUpdate -eq 1) # To check if a DNS zone is Active-Directory-integrated, use the property: DsIntegrated $CompliancyResList += New-CompliancyResult "DNS" $SubCategory "Zone is AD integrated" $DNSZone.DsIntegrated # To check if a DNS zone doesn't allow zone transfers to any computer, use the property: SecureSecondaries # SecureSecondaries can have following values: # 0: Allow zone transfers to any server --> not secure # 1: Allow zone transfers only to specific servers (listed in the name-servers tab) # 2: Allow zone transfers only to specific servers (listed in the zone-transfers tab) # 3: Do not allow Zone Transfers $CompliancyResList += New-CompliancyResult "DNS" $SubCategory "Zone transfers only to known secondaries" ($DNSZone.SecureSecondaries -ne 0) } return $CompliancyResList}

CheckSecCompl-DNS | Out-GridView


The result will appear in a PowerShell GridView.

Copy the script above to a powershell script file (e.g. SecCompl_DNS.ps1) and run using a Powershell-prompt under elevated privileges (All Programs --> Accessories --> Windows Powershell --> Windows PowerShell --> right-click and select:"run as administrator"). Be aware: I've only tested these scripts on Windows Server 2008 R2, not earlier versions. But feel free to try on other versions...

Was this post useful for you? Let me know through the feedback!