Last active
December 13, 2024 21:50
-
-
Save malacupa/0b7694f93dbaf5bf1b9d23ec55b0b648 to your computer and use it in GitHub Desktop.
Enumerate dynamic update settings for Active Directory Integrated DNS (ADIDNS) zones
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# see https://malacupa.com/2024/12/13/unsecure-dynamic-updates for a bit more info on dynamic update settings | |
function Parse-DnsProperty { | |
param ( | |
[Parameter(Mandatory=$true)] | |
$dnsPropertyValues | |
) | |
# see https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dnsp/445c7843-e4a1-4222-8c0f-630c230a4c80 for description | |
$parsedValues = @() | |
$dnsPropertyValues | %{ | |
$value = $_ | |
if ($value -is [byte[]]) { | |
$parsedValue = @{} | |
# Extract DataLength (4 bytes) | |
$dataLengthBytes = $value[0..3] | |
#[Array]::Reverse($dataLengthBytes) | |
$parsedValue.DataLength = [BitConverter]::ToUInt32($dataLengthBytes, 0) | |
# Extract NameLength (4 bytes) - Not Used | |
$nameLengthBytes = $value[4..7] | |
#[Array]::Reverse($nameLengthBytes) | |
$parsedValue.NameLength = [BitConverter]::ToUInt32($nameLengthBytes, 0) | |
# Extract Flag (4 bytes) - Reserved for future use | |
$flagBytes = $value[8..11] | |
#[Array]::Reverse($flagBytes) | |
$parsedValue.Flag = [BitConverter]::ToUInt32($flagBytes, 0) | |
# Extract Version (4 bytes) | |
$versionBytes = $value[12..15] | |
#[Array]::Reverse($versionBytes) | |
$parsedValue.Version = [BitConverter]::ToUInt32($versionBytes, 0) | |
# Extract Id (4 bytes) | |
$idBytes = $value[16..19] | |
#[Array]::Reverse($idBytes) | |
$parsedValue.Id = [BitConverter]::ToUInt32($idBytes, 0) | |
# Extract Data (variable length) | |
$dataBytes = $value[20..(19 + $parsedValue.DataLength)] | |
$parsedValue.Data = $dataBytes | |
# Extract Name (1 byte) - Not Used | |
$parsedValue.Name = $value[20 + $parsedValue.DataLength] | |
$parsedValues += $parsedValue | |
} | |
} | |
return $parsedValues | |
} | |
function Get-DynamicUpdateSupport { | |
param( | |
$zone | |
) | |
$values = Parse-DnsProperty $zone.properties.dnsproperty | ?{ $_.id -eq 2 } | |
if ($values.length -eq 1) { | |
switch ($values.Data) { | |
# see https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dnsp/e8651544-0fbb-4038-8232-375ff2d8a55e for details | |
0 { return 'ZONE_UPDATE_OFF' } | |
1 { return 'ZONE_UPDATE_UNSECURE'} | |
2 { return 'ZONE_UPDATE_SECURE' } | |
Default { return 'Invalid value' } | |
} | |
} | |
throw "dnsProperty structure is missing DSPROPERTY_ZONE_ALLOW_UPDATE property ID" | |
} | |
function Get-DynamicUpdateSupportInForest { | |
<# | |
.SYNOPSIS | |
Retrieves the dynamic update support status for all DNS zones in the forest. | |
.DESCRIPTION | |
The Get-DynamicUpdateSupportInForest function retrieves the dynamic update support status for all DNS zones in the forest. It queries each domain in the forest and checks the dynamic update status for each DNS zone. | |
.PARAMETER None | |
This function does not take any parameters. | |
.EXAMPLE | |
PS C:\> Get-DynamicUpdateSupportInForest -Verbose | |
This command retrieves the dynamic update support status for all DNS zones in the forest, shows status during processing and displays the results. | |
#> | |
[CmdletBinding()] | |
param() | |
$res = [System.Collections.ArrayList]@() | |
$ds =[ADSISearcher]'(objectClass=dnsZone)' | |
$ds.PropertiesToLoad.Add('dNSProperty') | Out-Null | |
$ds.PropertiesToLoad.Add('Name') | Out-Null | |
[System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain().Forest.Domains.Name | %{ | |
Write-Verbose "Processing $_ domain" | |
$domain = $_ | |
$domainDn = ('DC=' + ($_.split('.') -join ',DC=')) | |
$ds.searchroot = "LDAP://DC=DomainDnsZones,$domainDn" | |
$ds.FindAll() |%{ | |
$zone = $_ | |
$zoneName = $zone.properties.name | |
$dynamicUpdateSupport = (Get-DynamicUpdateSupport $zone) | |
Write-Verbose "Processing $_ domain's zone $zoneName" | |
$res.Add([PSCustomObject]@{ | |
Domain = $domain | |
Zone = $zoneName | |
DynamicUpdate = $dynamicUpdateSupport | |
}) | Out-Null | |
Write-Verbose "Doing $_ domain, zone $zoneName, dynamic update status = $dynamicUpdateSupport" | |
} | |
} | |
return $res | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment