Created
August 24, 2023 17:02
-
-
Save laymanstake/9c9cc965a6712cea6851b305a02d06f2 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
Function Start-SecurityCheck { | |
[CmdletBinding()] | |
Param( | |
[Parameter(ValueFromPipeline = $true, mandatory = $true)]$DomainName, | |
[Parameter(ValueFromPipeline = $true, mandatory = $true)][pscredential]$Credential | |
) | |
$SecuritySettings = @() | |
$DCs = (Get-ADDomainController -Filter * -Server $DomainName -Credential $Credential).hostname | |
$PDC = (Test-Connection -Computername (Get-ADDomainController -Filter * -Server $DomainName -Credential $Credential).Hostname -count 1 -AsJob | Get-Job | Receive-Job -Wait | Where-Object { $null -ne $_.Responsetime } | sort-object Responsetime | select-Object Address -first 1).Address | |
$null = Get-Job | Remove-Job | |
ForEach ($DC in $DCs) { | |
if (Test-Connection -ComputerName $Dc -Count 4 -Quiet) { | |
try { | |
$remotereg = ([Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine', $DC)) | |
$results = ( | |
$remotereg.OpenSubKey('System\CurrentControlSet\Control\Lsa').GetValue('LmCompatibilityLevel'), | |
$remotereg.OpenSubKey('System\CurrentControlSet\Control\Lsa').GetValue('NoLMHash'), | |
$remotereg.OpenSubKey('System\CurrentControlSet\Control\Lsa').GetValue('RestrictAnonymous'), | |
$remotereg.OpenSubKey('System\CurrentControlSet\Services\NTDS\Parameters').GetValue('LDAPServerIntegrity'), | |
$remotereg.OpenSubKey('SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System').GetValue('InactivityTimeoutSecs'), | |
$remotereg.OpenSubKey('SOFTWARE\Microsoft\Windows\NetworkProvider\HardenedPaths').GetValueNames() | |
) | |
$null = $remotereg.Close() | |
} | |
catch { | |
Write-Log -logtext "Could not check for security related registry keys on domain controller $dc : $($_.Exception.Message)" -logpath $logpath | |
$results = ("", "", "", "", "", "") | |
} | |
if ($results) { | |
$NTLM = switch ($results[0]) { | |
5 { "Send NTLMv2 response only. Refuse LM & NTLM" } | |
4 { "Send NTLMv2 response only. Refuse LM" } | |
3 { "Send NTLMv2 response only" } | |
2 { "Send NTLM response only" } | |
1 { "Send LM & NTLM - use NTLMv2 session security if negotiated" } | |
0 { "Send LM & NTLM responses" } | |
Default { | |
switch ((Get-ADCOmputer ($dc).split(".")[0] -Properties operatingsystem -Server $PDC).operatingsystem ) { | |
{ $_ -like "*2022*" -OR $_ -like "*2019*" -OR $_ -like "*2016*" -OR $_ -like "*2012 R2*" } { "Send NTLMv2 response only. Refuse LM & NTLM" } | |
Default { "Not configured, OS default assumed" } | |
} | |
} | |
} | |
$LMHash = switch ($results[1]) { | |
1 { "Enabled" } | |
0 { "Disabled" } | |
Default { "Not configured" } | |
} | |
$RestrictAnnon = switch ($results[2]) { | |
0 { "Disabled" } | |
1 { "Enabled" } | |
Default { "Not configured" } | |
} | |
$LDAPIntegrity = switch ($results[3]) { | |
0 { "Does not requires signing" } | |
1 { "Requires signing" } | |
Default { "Not configured" } | |
} | |
$InactivityTimeout = switch ( $results[4] ) { | |
{ $_ -le 900 -AND $_ -ne 0 -AND $_ -ne $null } { "900 or fewer second(s), but not 0: $($_)" } | |
{ $_ -eq 0 } { "0 second" } | |
{ $_ -gt 900 } { "More than 900 seconds: $($_) seconds" } | |
Default { | |
switch ((Get-ADCOmputer ($dc).split(".")[0] -Properties operatingsystem -Server $PDC).operatingsystem ) { | |
{ $_ -like "*2022*" -OR $_ -like "*2019*" -OR $_ -like "*2016*" -OR $_ -like "*2012*" } { "OS default: 900 second" } | |
Default { "Unlimited" } | |
} | |
} | |
} | |
$SYSVOLHardened = switch (($results[5] -like "*SYSVOL*") -like "*") { | |
$true { "True" } | |
$false { "False" } | |
Default { "False" } | |
} | |
$NetlogonHardened = switch (($results[5] -like "*Netlogon*") -like "*") { | |
$true { "True" } | |
$false { "False" } | |
Default { "False" } | |
} | |
$settings = ($NTLM, $LMHash, $RestrictAnnon, $LDAPIntegrity, $InactivityTimeout, $SYSVOLHardened, $NetlogonHardened) | |
} | |
else { | |
$settings = ("Access denied", "Access denied", "Access denied", "Access denied", "Access denied", "Access denied", "Access denied") | |
Write-Log -logtext "Could not check for security related security settings on domain controller $dc as regisitry not accessible : $($_.exception.message)" -logpath $logpath | |
} | |
if (Test-WSMan -ComputerName $DC -ErrorAction SilentlyContinue) { | |
try { | |
$settings += invoke-command -ComputerName $DC -Credential $Credential -ScriptBlock { | |
$null = secedit.exe /export /areas USER_RIGHTS /cfg "$env:TEMP\secedit.cfg" | |
$seceditContent = Get-Content "$env:TEMP\secedit.cfg" | |
$LocalLogonSIDs = ((($seceditContent | Select-String "SeInteractiveLogonRight") -split "=")[1] -replace "\*", "" -replace " ", "") -split "," | |
try { | |
$LocalLogonUsers = $LocalLogonSIDs | Where-Object { $_ -ne "" } | ForEach-Object { | |
if ($_ -like "S-1*") { | |
$SID = New-Object System.Security.Principal.SecurityIdentifier($_) | |
$User = $SID.Translate([System.Security.Principal.NTAccount]) | |
$User.Value | |
} | |
else { $_ } } | |
} | |
catch {} | |
$LocalLogonUsers -join "`n" | |
$RemoteLogonSIDs = ((($seceditContent | Select-String "SeRemoteInteractiveLogonRight") -split "=")[1] -replace "\*", "" -replace " ", "") -split "," | |
try { | |
$RemoteLogonUsers = $RemoteLogonSIDs | Where-Object { $_ -ne "" } | ForEach-Object { | |
if ($_ -like "S-1*") { | |
$SID = New-Object System.Security.Principal.SecurityIdentifier($_) | |
$User = $SID.Translate([System.Security.Principal.NTAccount]) | |
$User.Value | |
} | |
else { $_ } } | |
} | |
catch {} | |
$RemoteLogonUsers -join "`n" | |
$DenyNetworkLogonSIDs = ((($seceditContent | Select-String "SeDenyNetworkLogonRight") -split "=")[1] -replace "\*", "" -replace " ", "") -split "," | |
try { | |
$DenyNetworkLogonUsers = $DenyNetworkLogonSIDs | Where-Object { $_ -ne "" } | ForEach-Object { | |
if ($_ -like "S-1*") { | |
$SID = New-Object System.Security.Principal.SecurityIdentifier($_) | |
$User = $SID.Translate([System.Security.Principal.NTAccount]) | |
$User.Value | |
} | |
else { $_ } } | |
} | |
catch {} | |
$DenyNetworkLogonUsers -join "`n" | |
$DenyServiceLogonSIDs = ((($seceditContent | Select-String "SeDenyServiceLogonRight") -split "=")[1] -replace "\*", "" -replace " ", "") -split "," | |
try { | |
$DenyServiceLogonUsers = $DenyServiceLogonSIDs | Where-Object { $_ -ne "" } | ForEach-Object { | |
if ($_ -like "S-1*") { | |
$SID = New-Object System.Security.Principal.SecurityIdentifier($_) | |
$User = $SID.Translate([System.Security.Principal.NTAccount]) | |
$User.Value | |
} | |
else { $_ } } | |
} | |
catch {} | |
$DenyServiceLogonUsers -join "`n" | |
$DenyBatchLogonSIDs = ((($seceditContent | Select-String "SeDenyBatchLogonRight") -split "=")[1] -replace "\*", "" -replace " ", "") -split "," | |
try { | |
$DenyBatchLogonUsers = $DenyBatchLogonSIDs | Where-Object { $_ -ne "" } | ForEach-Object { | |
if ($_ -like "S-1*") { | |
$SID = New-Object System.Security.Principal.SecurityIdentifier($_) | |
$User = $SID.Translate([System.Security.Principal.NTAccount]) | |
$User.Value | |
} | |
else { $_ } } | |
} | |
catch {} | |
$DenyBatchLogonUsers -join "`n" | |
$DenyInteractiveLogonSIDs = ((($seceditContent | Select-String "SeDenyInteractiveLogonRight") -split "=")[1] -replace "\*", "" -replace " ", "") -split "," | |
try { | |
$DenyInteractiveLogonUsers = $DenyInteractiveLogonSIDs | Where-Object { $_ -ne "" } | ForEach-Object { | |
if ($_ -like "S-1*") { | |
$SID = New-Object System.Security.Principal.SecurityIdentifier($_) | |
$User = $SID.Translate([System.Security.Principal.NTAccount]) | |
$User.Value | |
} | |
else { $_ } } | |
} | |
catch {} | |
$DenyInteractiveLogonUsers -join "`n" | |
$null = Remove-Item "$env:TEMP\secedit.cfg" | |
} | |
} | |
catch { | |
$settings += ("Access denied", "Access denied", "Access denied", "Access denied", "Access denied", "Access denied") | |
Write-Log -logtext "Could not check for secedit related security settings on domain controller $dc : $($_.Exception.Message)" -logpath $logpath | |
} | |
} | |
else { | |
$settings += ("Access denied", "Access denied", "Access denied", "Access denied", "Access denied", "Access denied") | |
Write-Log -logtext "Could not check for security related security settings on domain controller $dc as PS remoting not available : $($_.exception.message)" -logpath $logpath | |
} | |
$SecuritySettings += [PSCustomObject]@{ | |
DomainName = $DomainName | |
DCName = $DC | |
"Network security: LAN Manager authentication level" = $settings[0] | |
"Network security: Do not store LAN Manager hash value on next password change" = $settings[1] | |
"Network access: Allow anonymous SID/Name translation" = $settings[2] | |
"Domain controller: LDAP server signing requirements" = $settings[3] | |
"Interactive logon: Machine inactivity limit" = $settings[4] | |
"UNC Path SYSVOL hardened?" = $settings[5] | |
"UNC Path NETLGON hardened?" = $settings[6] | |
"Allow logon locally on domain controllers" = $settings[7] | |
"Allow logon through Terminal Services on domain controllers" = $settings[8] | |
"Deny access to this computer from the network" = $settings[9] | |
"Deny log on as a service" = $settings[10] | |
"Deny log on as a batch job" = $settings[11] | |
"Deny Interactive logon" = $settings[12] | |
} | |
} | |
else { | |
$SecuritySettings += [PSCustomObject]@{ | |
DomainName = $DomainName | |
DCName = $DC | |
"Network security: LAN Manager authentication level" = "DC is down" | |
"Network security: Do not store LAN Manager hash value on next password change" = "DC is down" | |
"Network access: Allow anonymous SID/Name translation" = "DC is down" | |
"Domain controller: LDAP server signing requirements" = "DC is down" | |
"Interactive logon: Machine inactivity limit" = "DC is down" | |
"UNC Path SYSVOL hardened?" = "DC is down" | |
"UNC Path NETLGON hardened?" = "DC is down" | |
"Allow logon locally on domain controllers" = "DC is down" | |
"Allow logon through Terminal Services on domain controllers" = "DC is down" | |
"Deny access to this computer from the network" = "DC is down" | |
"Deny log on as a service" = "DC is down" | |
"Deny log on as a batch job" = "DC is down" | |
"Deny Interactive logon" = "DC is down" | |
} | |
Write-Log -logtext "Could not check for security related security settings on domain controller $dc as DC is down." -logpath $logpath | |
} | |
$message = "Working over domain: $DomainName Domain Controller $DC security checks." | |
New-BaloonNotification -title "Information" -message $message | |
Write-Log -logtext $message -logpath $logpath | |
} | |
return $SecuritySettings | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment