Suspicious LDAP Reconnaissance From Non Compliant Devices
Query
let Lookback = 1d;
let BinSize = 15m;
let RiskyDevices = materialize(
IntuneDeviceComplianceOrg
| where TimeGenerated > ago(7d)
| summarize arg_max(TimeGenerated, DeviceHealthThreatLevel, ComplianceState) by DeviceName
| where DeviceHealthThreatLevel in~ ("Low", "Medium", "High")
or ComplianceState =~ "Noncompliant"
| extend DeviceKey = tolower(tostring(split(DeviceName, ".")[0]))
| distinct DeviceKey, DeviceHealthThreatLevel, ComplianceState
);
// Attributes split by signal strength instead of a flat has_any
let RxHigh = @"ms-mcs-admpwd|mslaps-(encrypted)?password|ntsecuritydescriptor|msds-allowedtodelegateto|msds-keycredentiallink|sidhistory|unixuserpassword";
let RxMed = @"serviceprincipalname|admincount|msds-managedpassword|gplink|scriptpath";
let RxLow = @"useraccountcontrol|memberof|member|primarygroupid|grouptype";
// LDAP matching rules and bitmask filters, almost exclusively seen from offensive tooling
let RxTool = @"1\.2\.840\.113556\.1\.4\.1941|1\.2\.840\.113556\.1\.4\.803:=(4194304|524288|16777216|8192)";
IdentityQueryEvents
| where TimeGenerated > ago(Lookback)
| where ActionType == "LDAP query"
| where isnotempty(Query) and isnotempty(DeviceName)
| where AccountName !endswith "$" // Computer accounts need their own baseline
| extend DeviceKey = tolower(tostring(split(DeviceName, ".")[0]))
| lookup kind=inner RiskyDevices on DeviceKey
| extend q = tolower(Query)
| extend
ToolHit = extract(RxTool, 0, q),
Score = iff(q matches regex RxHigh, 5, 0)
+ iff(q matches regex RxMed, 2, 0)
+ iff(q matches regex RxLow, 1, 0)
+ iff(q matches regex RxTool, 5, 0)
+ iff(q contains "objectcategory=person" and q contains "(&", 1, 0)
| where Score > 0
| summarize
Events = count(),
DistinctQueries = dcount(Query),
Targets = dcount(QueryTarget),
MaxScore = max(Score),
TotalScore = sum(Score),
ToolIndicators = make_set_if(ToolHit, isnotempty(ToolHit), 10),
SampleQueries = make_set(substring(Query, 0, 200), 8),
IPs = make_set(IPAddress, 5),
TargetDCs = make_set(DestinationDeviceName, 5),
FirstSeen = min(TimeGenerated),
LastSeen = max(TimeGenerated)
by bin(TimeGenerated, BinSize), DeviceKey, AccountUpn, AccountDisplayName, DeviceHealthThreatLevel, ComplianceState
// Two separate triggers: single high confidence hit OR bulk enumeration
| where MaxScore >= 5 or (TotalScore >= 15 and DistinctQueries >= 20)
| extend Verdict = case(
array_length(ToolIndicators) > 0, "High: LDAP matching rule or bitmask filter, typical for offensive tooling",
MaxScore >= 5, "High: access to highly sensitive AD attributes (LAPS/ACL/delegation)",
DistinctQueries >= 50, "Medium: broad AD enumeration in a short time window",
"Low: elevated LDAP activity, review context")
| order by MaxScore desc, DistinctQueries descAbout this query
Explanation
This query is designed to detect suspicious LDAP reconnaissance activities originating from devices that are reported as non-compliant or at risk by Intune. It focuses on identifying potentially malicious Active Directory queries that could indicate reconnaissance efforts by attackers.
Here's a simplified breakdown of what the query does:
-
Identify Risky Devices: It first identifies devices that have been flagged by Intune as non-compliant or having a threat level (low, medium, or high) within the last seven days.
-
Categorize LDAP Queries: The query categorizes LDAP queries based on their sensitivity:
- High Sensitivity: Queries accessing highly sensitive attributes like LAPS passwords or security descriptors.
- Medium Sensitivity: Queries accessing attributes like service principal names.
- Low Sensitivity: Queries accessing common attributes like user account control.
-
Detect Offensive Tooling: It looks for patterns in LDAP queries that are characteristic of offensive tools like BloodHound or PowerView, which are often used for reconnaissance.
-
Score and Aggregate: Each LDAP query is scored based on its sensitivity and potential use of offensive tooling. The results are aggregated by device, account, and time period.
-
Trigger Alerts: Alerts are triggered based on two conditions:
- A single high-confidence indicator (e.g., access to highly sensitive attributes or use of offensive tooling).
- Bulk enumeration activity (e.g., a high volume of diverse LDAP queries).
-
Provide Context: Each alert includes details like sample queries, source IP addresses, and targeted domain controllers to help with further investigation.
The query helps security teams identify and respond to potential reconnaissance activities that could precede more serious attacks, providing a detailed context for each alert to aid in triage and response.