Collectors/Get-EscDomainMapping.ps1
|
function Get-EscDomainMapping { <# .SYNOPSIS Reads certificate-mapping registry settings from domain controllers. .DESCRIPTION For each domain controller, remotely reads (read-only) two REG_DWORD values that govern certificate-to-account mapping strength: - HKLM\SYSTEM\CurrentControlSet\Services\Kdc\ StrongCertificateBindingEnforcement - HKLM\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\ CertificateMappingMethods and maps them to DcMapping: DomainController, StrongCertificateBindingEnforcement(int), CertificateMappingMethods(int), WeakSchannelMapping(bool), Reachable(bool) WeakSchannelMapping = (CertificateMappingMethods -band 0x4) -ne 0 (0x4 = UPN mapping, considered weak for ESC10). If remote registry is unreachable, Reachable=$false and the int values are left null. Offline mode: pass -InputObject with the field values. .PARAMETER DomainController Optional list of DC host names. Auto-discovered from the current domain when omitted. .PARAMETER InputObject Optional array of offline records. .OUTPUTS [pscustomobject] DcMapping[]. .EXAMPLE Get-EscDomainMapping -Verbose #> [CmdletBinding()] param( [Parameter(Mandatory = $false)] [string[]] $DomainController, [Parameter(Mandatory = $false)] [object[]] $InputObject ) $build = { param($dc, $strong, $methods, $reachable) $weak = $null if ($null -ne $methods) { $weak = ((([int]$methods) -band 0x4) -ne 0) } $strongOut = $null if ($null -ne $strong) { $strongOut = [int] $strong } $methodsOut = $null if ($null -ne $methods) { $methodsOut = [int] $methods } return [pscustomobject]@{ DomainController = $dc StrongCertificateBindingEnforcement = $strongOut CertificateMappingMethods = $methodsOut WeakSchannelMapping = $weak Reachable = $reachable } } if ($PSBoundParameters.ContainsKey('InputObject') -and $null -ne $InputObject) { Write-EscLog -Component 'DomainMapping' -Message ("Offline mode: transforming {0} fixture record(s)." -f @($InputObject).Count) $out = @() foreach ($rec in $InputObject) { $reachable = $true if ($null -ne $rec.Reachable) { $reachable = [bool] $rec.Reachable } $out += (& $build ([string]$rec.DomainController) $rec.StrongCertificateBindingEnforcement $rec.CertificateMappingMethods $reachable) } return @($out) } $dcs = @($DomainController) if (@($dcs).Count -eq 0) { try { $domain = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain() foreach ($dc in $domain.DomainControllers) { $dcs += $dc.Name } } catch { Write-EscLog -Component 'DomainMapping' -Level Warning -Message ("Could not enumerate domain controllers: {0}" -f $_.Exception.Message) } } $dcs = @($dcs | Where-Object { -not [string]::IsNullOrWhiteSpace($_) } | Select-Object -Unique) $localShort = [string] $env:COMPUTERNAME $localFqdn = $localShort try { $localFqdn = [System.Net.Dns]::GetHostEntry($localShort).HostName } catch { } $out = @() foreach ($dc in $dcs) { $strong = $null $methods = $null $reachable = $false $base = $null try { $dcShort = ($dc -split '\.')[0] $isLocal = ($dc -ieq 'localhost' -or $dc -ieq '.' -or $dc -ieq $localShort -or $dc -ieq $localFqdn -or $dcShort -ieq $localShort) if ($isLocal) { $base = [Microsoft.Win32.RegistryKey]::OpenBaseKey([Microsoft.Win32.RegistryHive]::LocalMachine, [Microsoft.Win32.RegistryView]::Default) } else { $base = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey([Microsoft.Win32.RegistryHive]::LocalMachine, $dc) } $reachable = $true $kdc = $base.OpenSubKey('SYSTEM\CurrentControlSet\Services\Kdc') if ($null -ne $kdc) { $v = $kdc.GetValue('StrongCertificateBindingEnforcement') if ($null -ne $v) { $strong = [int] $v } $kdc.Close() } $schannel = $base.OpenSubKey('SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL') if ($null -ne $schannel) { $v = $schannel.GetValue('CertificateMappingMethods') if ($null -ne $v) { $methods = [int] $v } $schannel.Close() } } catch { $reachable = $false Write-EscLog -Component 'DomainMapping' -Level Warning -Message ("Remote registry read failed for '{0}': {1}" -f $dc, $_.Exception.Message) } finally { if ($null -ne $base) { try { $base.Close() } catch { } } } $out += (& $build $dc $strong $methods $reachable) } Write-EscLog -Component 'DomainMapping' -Message ("Collected mapping settings for {0} DC(s)." -f @($out).Count) return @($out) } |