Advanced Hunting to Find all Devices not onboarded and discovered Devices to Defender

// Non-onboarded/discovered devices + who saw them + network details + IPs
DeviceInfo
| where Timestamp > ago(30d)
| where OnboardingStatus != "Onboarded"               // all not onboarded/discovered
| where isempty(MergedToDeviceId)                    // Remove invalidated/merged devices
| summarize arg_max(Timestamp, *) by DeviceId
| invoke SeenBy()                                    // Add detecting onboarded devices
| join kind=leftouter (
    DeviceNetworkInfo
    | where Timestamp > ago(30d)
    | summarize arg_max(Timestamp, *) by DeviceId    // Latest network info
) on DeviceId
| extend ConnectedNetworksParsed = parse_json(ConnectedNetworks)
| extend IPAddressesParsed = parse_json(IPAddresses)
| summarize 
    IPsSeen              = make_set(IPAddressesParsed.Address),
    DetectingDevices     = make_set(SeenBy),         // Onboarded devices that saw it
    NetworkNames         = make_set(ConnectedNetworksParsed.Name),      // e.g., WiFi SSID or network name
    NetworkCategories    = make_set(ConnectedNetworksParsed.Category),  // e.g., Enterprise, Public
    LastSeen             = max(Timestamp),
    FirstSeen            = min(Timestamp)
    by NonOnboardedName = DeviceName, OSPlatform, DeviceId
| project-reorder NonOnboardedName, IPsSeen, DetectingDevices, NetworkNames, NetworkCategories, OSPlatform, LastSeen, FirstSeen
| order by LastSeen desc

Cleaner Version

// Non-onboarded/discovered devices + who saw them + network details + IPs (excluding Unknown OS, iOS, Android, Linux; remove with no detecting devices)
DeviceInfo
| where Timestamp > ago(30d)
| where OnboardingStatus != "Onboarded"               // all not onboarded/discovered
| where isempty(MergedToDeviceId)                    // Remove invalidated/merged devices
| summarize arg_max(Timestamp, *) by DeviceId
| where isnotempty(OSPlatform) and OSPlatform != "Unknown" and OSPlatform !in ("iOS", "Android", "Linux")
| invoke SeenBy()                                    // Add detecting onboarded devices
| join kind=leftouter (
    DeviceNetworkInfo
    | where Timestamp > ago(30d)
    | summarize arg_max(Timestamp, *) by DeviceId    // Latest network info
) on DeviceId
| extend IPAddresses = iff(isempty(IPAddresses) or isnull(IPAddresses), tostring(pack_array(pack_dictionary("IPAddress", PublicIP, "PrefixSize", "0", "AddressSpace", "Public"))), IPAddresses)
| extend ConnectedNetworks = iff(isempty(ConnectedNetworks) or isnull(ConnectedNetworks), '[]', ConnectedNetworks)
| mv-apply IPAddressesParsed = parse_json(IPAddresses) on (
    extend IPAddress = tostring(IPAddressesParsed.IPAddress)
    | summarize IPsSeen = make_set(IPAddress) by DeviceId, NonOnboardedName = DeviceName, OSPlatform, tostring(SeenBy), ConnectedNetworks, Timestamp
)
| mv-apply ConnectedNetworksParsed = parse_json(ConnectedNetworks) on (
    extend Name = tostring(ConnectedNetworksParsed.Name),
           Category = tostring(ConnectedNetworksParsed.Category)
    | summarize NetworkNames = make_set(Name),
                NetworkCategories = make_set(Category) by DeviceId, NonOnboardedName, OSPlatform, tostring(SeenBy), tostring(IPsSeen), Timestamp
)
| summarize 
    IPsSeen = make_set(IPsSeen),
    DetectingDevices = make_set(SeenBy),         // Onboarded devices that saw it
    NetworkNames = make_set(NetworkNames),      
    NetworkCategories = make_set(NetworkCategories),  
    LastSeen = max(Timestamp),
    FirstSeen = min(Timestamp)
    by NonOnboardedName, OSPlatform, DeviceId
| where array_length(DetectingDevices) > 0          // Remove devices with no detecting devices
| project-reorder NonOnboardedName, IPsSeen, DetectingDevices, NetworkNames, NetworkCategories, OSPlatform, LastSeen, FirstSeen
| order by LastSeen desc
1 Star2 Stars3 Stars4 Stars5 Stars (No Ratings Yet)
Loading...