Query Details

Hunt Device Discovery Subnet Ranges

Query

# *Hunt Device Discovery Subnet Ranges*

## Query Information

#### MITRE ATT&CK Technique(s)

N/A

#### Description
This KQL query helps you identify which subnet ranges are behind the Microsoft Defender for Endpoint Device Discovery 'Monitored Networks' page. By using this query you can investigate if all of your corporate networks are being monitored and change monitored states effectivly. More information can be found in the references.

#### Risk
This query helps mitigating the risk that you do not perform Device Discovery on all monitored networks, which would result into an incomplete asset inventory list in Defender XDR.

#### Author <Optional>
- **Name:** Robbe Van den Daele
- **Github:** https://github.com/RobbeVandenDaele
- **Twitter:** https://x.com/RobbeVdDaele
- **LinkedIn:** https://www.linkedin.com/in/robbe-van-den-daele-677986190/
- **Website:** https://hybridbrothers.com/

#### References
- https://hybridbrothers.com/mde-device-discovery-improving-the-monitored-network-page/

## Defender XDR
```KQL
// OPTIONAL - Device cap used to ignore network with less then X devices in them
let device_cap = 0;
DeviceNetworkInfo
| where Timestamp > ago(7d)
// Ignore empty networks
| where ConnectedNetworks  != ""
// Get networks data
| extend ConnectedNetworksExp = parse_json(ConnectedNetworks)
| mv-expand bagexpansion = array ConnectedNetworks=ConnectedNetworksExp
| extend NetworkName = tostring(ConnectedNetworks ["Name"]), NetworkDescription = tostring(ConnectedNetworks ["Description"]), NetworkCategory = tostring(ConnectedNetworks ["Category"])
// Get subnet data for IPv4 Addresses
| extend IPAddressesExp = parse_json(IPAddresses)
| mv-expand bagexpansion = array IPAddresses=IPAddressesExp
| extend IPAddress = tostring(IPAddresses ["IPAddress"]), SubnetPrefix = tolong(IPAddresses ["SubnetPrefix"])
| extend NetworkAddress = format_ipv4(IPAddress, SubnetPrefix)
| extend SubnetRange = strcat(NetworkAddress, "/", SubnetPrefix)
// Exclude IPv6 and APIPPA
| where SubnetPrefix <= 32
| where IPAddress !startswith "169.254"
// Ignore unidentified networks
| where not(NetworkName has_any ("Unidentified", "Identifying..."))
// Provide list
| distinct DeviceId, NetworkName, IPv4Dhcp, SubnetRange
| summarize Devices = count(), SubnetRanges = make_set(SubnetRange) by NetworkName, IPv4Dhcp
// Ignore network with very low device count
| where Devices >= device_cap
| sort by Devices desc
```

## Sentinel
```KQL
// OPTIONAL - Device cap used to ignore network with less then X devices in them
let device_cap = 0;
DeviceNetworkInfo
| where TimeGenerated > ago(7d)
// Ignore empty networks
| where ConnectedNetworks  != ""
// Get networks data
| extend ConnectedNetworksExp = parse_json(ConnectedNetworks)
| mv-expand bagexpansion = array ConnectedNetworks=ConnectedNetworksExp
| extend NetworkName = tostring(ConnectedNetworks ["Name"]), NetworkDescription = tostring(ConnectedNetworks ["Description"]), NetworkCategory = tostring(ConnectedNetworks ["Category"])
// Get subnet data for IPv4 Addresses
| extend IPAddressesExp = parse_json(IPAddresses)
| mv-expand bagexpansion = array IPAddresses=IPAddressesExp
| extend IPAddress = tostring(IPAddresses ["IPAddress"]), SubnetPrefix = tolong(IPAddresses ["SubnetPrefix"])
| extend NetworkAddress = format_ipv4(IPAddress, SubnetPrefix)
| extend SubnetRange = strcat(NetworkAddress, "/", SubnetPrefix)
// Exclude IPv6 and APIPPA
| where SubnetPrefix <= 32
| where IPAddress !startswith "169.254"
// Ignore unidentified networks
| where not(NetworkName has_any ("Unidentified", "Identifying..."))
// Provide list
| distinct DeviceId, NetworkName, IPv4Dhcp, SubnetRange
| summarize Devices = count(), SubnetRanges = make_set(SubnetRange) by NetworkName, IPv4Dhcp
// Ignore network with very low device count
| where Devices >= device_cap
| sort by Devices desc
```

Explanation

This KQL query is designed to help you identify and monitor the subnet ranges of networks that are being tracked by Microsoft Defender for Endpoint's Device Discovery feature. Here's a simplified breakdown of what the query does:

  1. Time Frame: It looks at network data from the past 7 days.

  2. Filter Out Empty Networks: It ignores any networks that don't have any connected devices.

  3. Extract Network Information: The query parses the network data to extract details such as network name, description, and category.

  4. Extract Subnet Data: It focuses on IPv4 addresses, extracting the IP address and subnet prefix to determine the subnet range.

  5. Exclude Certain Networks:

    • It excludes IPv6 addresses and addresses starting with "169.254" (which are typically self-assigned and not useful for monitoring).
    • It also ignores networks that are unidentified or still being identified.
  6. Summarize Results:

    • It provides a list of distinct devices and their associated network names, DHCP information, and subnet ranges.
    • It counts the number of devices per network and lists the subnet ranges for each network.
  7. Filter by Device Count: It allows you to set a minimum number of devices required for a network to be included in the results, helping to focus on more significant networks.

  8. Sort by Device Count: Finally, it sorts the networks by the number of devices in descending order, so you can easily see which networks have the most devices.

Overall, this query helps ensure that all relevant corporate networks are being monitored, reducing the risk of having an incomplete asset inventory in Defender XDR.

Details

Robbe Van den Daele profile picture

Robbe Van den Daele

Released: March 19, 2025

Tables

DeviceNetworkInfo

Keywords

DeviceNetworkSubnetIPv4

Operators

let|whereago()!=extendparse_json()mv-expandtostring()tolong()format_ipv4()strcat()<=!startswithnot()has_any()distinctsummarizecount()make_set()by>=sort by

Actions