Wednesday, October 30, 2019

Hunting bad LDAP queries on your DC

This is a quick guide to find bad LDAP queries running against your Domain Controller.

To get the needed events on your DC, set the following registry settings using PowerShell:

Set-ItemProperty -Path 'HKLM:\System\CurrentControlSet\Services\NTDS\Diagnostics' -Name '15 Field Engineering' -Value "5"
Set-ItemProperty -Path 'HKLM:\System\CurrentControlSet\Services\NTDS\Parameters' -Name 'Expensive Search Results Threshold' -Value "0"
Set-ItemProperty -Path 'HKLM:\System\CurrentControlSet\Services\NTDS\Parameters' -Name 'Inefficient Search Results Threshold' -Value "0"
Set-ItemProperty -Path 'HKLM:\System\CurrentControlSet\Services\NTDS\Parameters' -Name 'Search Time Threshold (msecs)' -Value "120"

Your DC is now logging event 1644, with information about the LDAP queries.

If you are using this cmds any LDAP Query that´s taking over 120ms(Search Time Threshold (msecs)) will be logged.

The Log Level is set to 5 ('15 Field Engineering' -Value "5") that means it logs all events, including debug strings and configuration changes. Also a complete log of the service is recorded.

Expensive LDAP search reults, are the searches those visit large number of entries. The default threshold for expensive search is 10000. We can set it using Expensive Search Results Threshold reg key, in this case we set it to 0 to get all queries.

Inefficient Search Results Threshold, are the searches those return less than 10% of visited entries. The default visited entries threshold limit for inefficient query is 1000 which means if a query visit less than 1000 entries then it will not be consider inefficient query even though if it return no entry. So we set it to 0 to get all queries.

So now you can open the Event Viewer, go to Directory Services log and depending of the number of "bad" LDAP queries, you will see a lot of 1644 events. In this events you will get information like User,Filter,Client and the attribute that preventing Optimization. So with this values you can identify the source and fix it.


Find attached an example event:

Internal event: A client issued a search operation with the following options. 
Client:
10.10.10.10:54601 
Starting node:
dc=domain,dc=int
Filter:
( |  (uid=Jon.Doe)  (sAMAccountName=Jon.Doe) )  
Search scope:
subtree 
Attribute selection:
uid,sAMAccountName 
Server controls:
Visited entries:
359807 
Returned entries:

Used indexes:
DNT_index:662818:N; 
Pages referenced:
2945008 
Pages read from disk:

Pages preread from disk:

Clean pages modified:

Dirty pages modified:

Search time (ms):
4111
Attributes Preventing Optimization:
uid  
User:
domain\serviceaccount.1

In this case you can contact the responsible admin for Client 10.10.10.10 and modify the query to use a better filter. For example if you don´t use the uid field in AD, you can remove it from the LDAP query and just search for teh samaccountname.

If you have enough logs collected, you can revert your changes using the following commands:

Set-ItemProperty -Path 'HKLM:\System\CurrentControlSet\Services\NTDS\Diagnostics' -Name '15 Field Engineering' -Value "0"
Remove-ItemProperty -Path 'HKLM:\System\CurrentControlSet\Services\NTDS\Parameters' -Name 'Expensive Search Results Threshold'
Remove-ItemProperty -Path 'HKLM:\System\CurrentControlSet\Services\NTDS\Parameters' -Name 'Inefficient Search Results Threshold'
Remove-ItemProperty -Path 'HKLM:\System\CurrentControlSet\Services\NTDS\Parameters' -Name 'Search Time Threshold (msecs)'





Thursday, October 24, 2019

PowerShell Get a list of IPs from DNS Names

Requirements:

You need a file C:\temp\server.csv. This file have all names in it.

server1
server2
server3
server4

And the script to get all IPs.

$names = Get-Content C:\temp\names.csv
foreach ($name in $names )
    {
    [System.Net.Dns]::GetHostAddresses("$name") | select -ExpandProperty IPAddressToString
    }