Featured image of post Monitoring with PowerShell: Monitoring Security state

Monitoring with PowerShell: Monitoring Security state

After the last couple of blogs I’ve been asked how I monitor the security state of Windows Servers, so I figured I would create a blog about monitoring some security advisement. Of course there is another disclaimer involved.

Disclaimer: Monitoring these security settings is only a small part of what your entire security monitoring suite should look like. There are a lot more settings and changes you’d need to monitor than just these, but these are items that can be used as a early warning system.

Now that we’ve got that out of the way we can start our monitoring script. We will dissect the script together and have the complete version at the bottom of the page.

The Script

First we will start on monitoring debuggers. This can be done both on both workstations and on servers. Debuggers are often used to secretly start a different process with elevated credentials, or you can have a executable start without the user ever clicking on it.

1
2
3
4
5
6
7
8
$debug = Get-Childitem -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options" -Recurse | Where-Object { $_.Property -eq "Debugger" } | Where-Object { $_.pschildname -ne "DeviceCensus.exe" }
if(!$debug) {
    $DebuggerFound = "Healthy - No Debugers found"
} else {
foreach($key in $debug){
$DebuggerFound += "$($key.pschildname) is debugged `n"
}
}

Using this we find exactly which process has a debugger attached. DeviceCensus.exe always has a debugger attached so we can ignore this executable. Next we’ll be moving on to WDigest monitoring.

WDigest was a protocol that was introduced in the Windows XP time, the idea at that time was that this was to be used for web based authentication. Wdigest is enabled by default from server 2003 until Server 2012R2. The problem is that to have wdigest run correctly plain-text passwords got stored in LLASS. To resolve this Microsoft released an update to make sure you can disable wdigest on systems.

The problem is that all that is required to enable wdigest again is to change a registry key, We are going to monitor this key with two simple PowerShell commands. You want these items to be set to 0. If not, you should resolve by setting it to 0.

1
2
$WDigestNegotiate           = get-childitem -path "HKLM:\System\CurrentControlSet\Control\SecurityProviders\WDigest" | Where-Object {$_.Property -eq "Negotiate"}
$WDigestUseLogonCredential  =  get-childitem -path "HKLM:\System\CurrentControlSet\Control\SecurityProviders\WDigest" | Where-Object {$_.Property -eq "UseLogonCredential"}

Next up is Cached Credentials Account monitoring, again this can be used on both workstations and servers. Cached Credentials are used to logon when the domain controller is not available. For servers and workstations I would advise to lower this to 0. On laptops that is more difficult as users need to be able to work offline, currently we set it to 3 (2 for system logons, and 1 for the actual user account).

1
$CachedCredentialsAllowed   = (Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon").CachedLogonsCount

And as a last check we monitor the LM Compatibility Level. This declares what types of authentications can be used on the device. For more information on NTLM, LM Compatibility, and kerberos check this blog from Microsoft. We always completely go to the maximum security level of 5.

1
$NTLMCompatibilityLevel     = (Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\Lsa").lmcompatibilitylevel

And that’s it. Monitoring these items make your environment a little bit more secure, and protects you against most forms of Pass The Hash. The full script can be found below.

Full Script

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
$debug = Get-Childitem -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options" -Recurse | Where-Object { $_.Property -eq "Debugger" } | Where-Object { $_.pschildname -ne "DeviceCensus.exe" }
if(!$debug) {
    $DebuggerFound = "Healthy - No Debugers found"
} else {
foreach($key in $debug){
$DebuggerFound += "$($key.pschildname) is debugged <br>`n"
}
}
$WDigestNegotiate           = get-childitem -path "HKLM:\System\CurrentControlSet\Control\SecurityProviders\WDigest" | Where-Object {$_.Property -eq "Negotiate"}
$WDigestUseLogonCredential  =  get-childitem -path "HKLM:\System\CurrentControlSet\Control\SecurityProviders\WDigest" | Where-Object {$_.Property -eq "UseLogonCredential"}
$CachedCredentialsAllowed   = (Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon").CachedLogonsCount
$NTLMCompatibilityLevel     = (Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\Lsa").lmcompatibilitylevel
All blogs are posted under AGPL3.0 unless stated otherwise
comments powered by Disqus
Built with Hugo
Theme Stack designed by Jimmy