Using in to Search Multiple Indicators
Investigations often start with more than one clue.
Two suspicious IP addresses.
Three domains.
Several users.
A small list of devices.
Typing the same where line again and again quickly becomes messy.
In this Agent Foskett Academy lesson, you will learn how defenders use the KQL in operator to search for multiple indicators at once and keep Microsoft Defender XDR and Sentinel investigations clean, focused and repeatable.
Lesson overview
Learn how to search multiple users, IP addresses, domains and devices with cleaner KQL instead of building long chains of OR conditions.
Why the in operator matters
You may need to search for several IP addresses from a phishing kit, multiple domains from a suspicious email campaign or a short list of users who received the same message.
The in operator lets you compare one column against a list of values.
Investigation scenario
The analyst wants to search Microsoft Defender XDR telemetry for matching activity without writing a long and messy query.
Step 1 — The messy way with OR
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
EmailEvents | where Timestamp > ago(7d) | where SenderFromDomain == "contoso-login.com" or SenderFromDomain == "secure-contoso.net" or SenderFromDomain == "account-review.org" | project Timestamp, SenderFromAddress, RecipientEmailAddress, Subject, DeliveryAction
Step 2 — The cleaner way with in
- 1
- 2
- 3
- 4
- 5
- 6
EmailEvents | where Timestamp > ago(7d) | where SenderFromDomain in ("contoso-login.com", "secure-contoso.net", "account-review.org") | project Timestamp, SenderFromAddress, RecipientEmailAddress, Subject, DeliveryAction
Step 3 — Use in with a let statement
- 1
- 2
- 3
- 4
- 5
- 6
- 7
let suspiciousDomains = dynamic(["contoso-login.com", "secure-contoso.net", "account-review.org"]); EmailEvents | where Timestamp > ago(7d) | where SenderFromDomain in (suspiciousDomains) | project Timestamp, SenderFromAddress, RecipientEmailAddress, Subject, DeliveryAction | sort by Timestamp desc
What in does
Think of it as asking: does this value appear in my investigation list?
Step 4 — Search multiple IP addresses
- 1
- 2
- 3
- 4
- 5
- 6
- 7
let suspiciousIPs = dynamic(["203.0.113.10", "198.51.100.25"]); DeviceNetworkEvents | where Timestamp > ago(7d) | where RemoteIP in (suspiciousIPs) | project Timestamp, DeviceName, InitiatingProcessAccountName, RemoteIP, RemotePort, InitiatingProcessFileName | sort by Timestamp desc
Step 5 — Search multiple users
- 1
- 2
- 3
- 4
- 5
- 6
- 7
let targetUsers = dynamic(["user1@contoso.com", "user2@contoso.com", "user3@contoso.com"]); UrlClickEvents | where Timestamp > ago(7d) | where AccountUpn in (targetUsers) | project Timestamp, AccountUpn, Url, ActionType, ThreatTypes | sort by Timestamp desc
Step 6 — Use !in to exclude known safe values
- 1
- 2
- 3
- 4
- 5
- 6
- 7
let trustedDomains = dynamic(["contoso.com", "microsoft.com", "office.com"]); EmailEvents | where Timestamp > ago(7d) | where SenderFromDomain !in (trustedDomains) | summarize EmailCount = count() by SenderFromDomain | sort by EmailCount desc
Investigator notes
If you are looking for partial text, patterns or words inside longer strings, operators such as contains or has may be a better fit.
What you learned
Continue your investigation
Continue learning with Using let Statements to Reuse Evidence, Building Investigation Timelines, KQL Threat Hunting Guide, UrlClickEvents and Microsoft Security.
Develop IT. Protect IT. GEMXIT PTY LTD | GEMXIT UK LTD