Query Details

MDE Internet Facing

Query

# Defender for Endpoint - internet-facing devices

## Query Information

### Description

Use these queries to identify internet-facing endpoints, review exposed ports and protocols, and investigate devices observed by external scans.

### MITRE ATT&CK Technique(s)

| Technique ID | Title | Link |
| --- | --- | --- |
| T1190 | Initial Access: Exploit Public-Facing Application | https://attack.mitre.org/techniques/T1190/ |
| T1133 | Initial Access: External Remote Services | https://attack.mitre.org/techniques/T1133/ |
| T1021.001 | Lateral Movement: Remote Services: Remote Desktop Protocol | https://attack.mitre.org/techniques/T1021/001/ |
| T1021.002 | Lateral Movement: Remote Services: SMB/Windows Admin Shares | https://attack.mitre.org/techniques/T1021/002/ |
| T1595 | Reconnaissance: Active Scanning | https://attack.mitre.org/techniques/T1595/ |

#### References

- [Discovering internet-facing devices using Microsoft Defender for Endpoint](https://techcommunity.microsoft.com/t5/microsoft-defender-for-endpoint/discovering-internet-facing-devices-using-microsoft-defender-for/ba-p/3778975)

### KQL

```kql
DeviceInfo
| where IsInternetFacing == true
| extend InternetFacingInfo = AdditionalFields
| extend AF = parse_json(tostring(AdditionalFields))
| extend
    InternetFacingLastSeen = todatetime(AF.InternetFacingLastSeen),
    InternetFacingLocalIp = tostring(AF.InternetFacingLocalIp),
    InternetFacingLocalPort = toint(AF.InternetFacingLocalPort),
    InternetFacingPublicScannedIp = tostring(AF.InternetFacingPublicScannedIp),
    InternetFacingPublicScannedPort = toint(AF.InternetFacingPublicScannedPort),
    InternetFacingReason = tostring(AF.InternetFacingReason),
    InternetFacingTransportProtocol = tostring(AF.InternetFacingTransportProtocol)
| summarize
    Ports = make_set(InternetFacingPublicScannedPort),
    LocalPorts = make_set(InternetFacingLocalPort),
    Reasons = make_set(InternetFacingReason),
    LocalIPs = make_set(InternetFacingLocalIp),
    Protocols = make_set(InternetFacingTransportProtocol),
    LastSeen = max(InternetFacingLastSeen)
    by DeviceName
| order by LastSeen desc
```

Devices detected by an external scan

```kql
DeviceNetworkEvents
| where TimeGenerated > ago(7d)
| where ActionType == "InboundInternetScanInspected"
| extend AF = parse_json(tostring(AdditionalFields))
| extend
    PublicScannedIp = tostring(AF.PublicScannedIp),
    PublicScannedPort = toint(AF.PublicScannedPort)
| summarize arg_max(TimeGenerated, *) by DeviceId
| project
    TimeGenerated,
    DeviceName,
    DeviceId,
    ActionType,
    PublicScannedIp,
    PublicScannedPort
```

Devices detected by an external scan with IP geolocation information

```kql
DeviceNetworkEvents
| where TimeGenerated > ago(7d)
| where ActionType == "InboundInternetScanInspected"
| extend AF = parse_json(tostring(AdditionalFields))
| extend
    PublicScannedIp = tostring(AF.PublicScannedIp),
    PublicScannedPort = toint(AF.PublicScannedPort)
| where isnotempty(PublicScannedIp)
| extend GeoInfo = geo_info_from_ip_address(PublicScannedIp)
| extend
    PublicScannedCountry = tostring(GeoInfo.country),
    PublicScannedState = tostring(GeoInfo.state),
    PublicScannedCity = tostring(GeoInfo.city),
    PublicScannedLatitude = todouble(GeoInfo.latitude),
    PublicScannedLongitude = todouble(GeoInfo.longitude)
| summarize arg_max(TimeGenerated, *) by DeviceId
| project
    TimeGenerated,
    DeviceName,
    DeviceId,
    ActionType,
    PublicScannedIp,
    PublicScannedPort,
    PublicScannedCountry,
    PublicScannedState,
    PublicScannedCity
//    PublicScannedLatitude,
    // PublicScannedLongitude
| order by TimeGenerated desc
```




SMB

```kql
DeviceInfo
| where IsInternetFacing == true
| extend InternetFacingInfo = AdditionalFields
| extend AF = parse_json(tostring(AdditionalFields))
| extend
    InternetFacingLastSeen = todatetime(AF.InternetFacingLastSeen),
    InternetFacingLocalIp = tostring(AF.InternetFacingLocalIp),
    InternetFacingLocalPort = toint(AF.InternetFacingLocalPort),
    InternetFacingPublicScannedIp = tostring(AF.InternetFacingPublicScannedIp),
    InternetFacingPublicScannedPort = toint(AF.InternetFacingPublicScannedPort),
    InternetFacingReason = tostring(AF.InternetFacingReason),
    InternetFacingTransportProtocol = tostring(AF.InternetFacingTransportProtocol)
| where InternetFacingLocalPort in (139, 445)
| project
    TimeGenerated,
    DeviceName,
    PublicIP,
    InternetFacingLastSeen,
    InternetFacingLocalIp,
    InternetFacingLocalPort,
    InternetFacingPublicScannedIp,
    InternetFacingPublicScannedPort,
    InternetFacingReason,
    InternetFacingTransportProtocol
```

RDP

```kql
DeviceInfo
| where IsInternetFacing == true
| extend AF = parse_json(tostring(AdditionalFields))
| extend
    InternetFacingLastSeen = todatetime(AF.InternetFacingLastSeen),
    InternetFacingLocalIp = tostring(AF.InternetFacingLocalIp),
    InternetFacingLocalPort = toint(AF.InternetFacingLocalPort),
    InternetFacingPublicScannedIp = tostring(AF.InternetFacingPublicScannedIp),
    InternetFacingPublicScannedPort = toint(AF.InternetFacingPublicScannedPort),
    InternetFacingReason = tostring(AF.InternetFacingReason),
    InternetFacingTransportProtocol = tostring(AF.InternetFacingTransportProtocol)
| where InternetFacingLocalPort == 3389
| project
    TimeGenerated,
    DeviceName,
    PublicIP,
    InternetFacingLastSeen,
    InternetFacingLocalIp,
    InternetFacingLocalPort,
    InternetFacingPublicScannedIp,
    InternetFacingPublicScannedPort,
    InternetFacingReason,
    InternetFacingTransportProtocol
```

ExternalNetworkConnection (still testing....)

```kql
let InternetFacingDevices =
DeviceInfo
| where IsInternetFacing == true
| extend AF = parse_json(tostring(AdditionalFields))
| extend
    InternetFacingLastSeen = todatetime(AF.InternetFacingLastSeen),
    InternetFacingLocalIp = tostring(AF.InternetFacingLocalIp),
    InternetFacingLocalPort = toint(AF.InternetFacingLocalPort),
    InternetFacingPublicScannedIp = tostring(AF.InternetFacingPublicScannedIp),
    InternetFacingPublicScannedPort = toint(AF.InternetFacingPublicScannedPort),
    InternetFacingReason = tostring(AF.InternetFacingReason),
    InternetFacingTransportProtocol = tostring(AF.InternetFacingTransportProtocol)
| where InternetFacingReason == "ExternalNetworkConnection"
| project
    DeviceId,
    DeviceName,
    TimeGenerated,
    InternetFacingLastSeen,
    InternetFacingLocalIp,
    InternetFacingLocalPort,
    InternetFacingPublicScannedIp,
    InternetFacingPublicScannedPort,
    InternetFacingReason,
    InternetFacingTransportProtocol;
let PublicNetworkConnections =
DeviceNetworkEvents
| where TimeGenerated > ago(30d)
| where RemoteIPType == "Public"
| project
    DeviceId,
    DeviceName,
    NetworkTimestamp = TimeGenerated,
    LocalIP,
    LocalPort,
    LocalIPType,
    RemoteIP,
    RemotePort,
    RemoteIPType,
    ActionType,
    InitiatingProcessFolderPath,
    InitiatingProcessCommandLine,
    InitiatingProcessFileName;
InternetFacingDevices
| join kind=leftouter PublicNetworkConnections on DeviceId
| where tostring(LocalIP) == InternetFacingLocalIp
| where toint(LocalPort) == InternetFacingLocalPort
| project
    TimeGenerated,
    NetworkTimestamp,
    DeviceName,
    InternetFacingPublicScannedIp,
    InternetFacingPublicScannedPort,
    InternetFacingLocalIp,
    InternetFacingLocalPort,
    InternetFacingTransportProtocol,
    LocalIP,
    LocalPort,
    RemoteIP,
    RemotePort,
    RemoteIPType,
    ActionType,
    InitiatingProcessFileName,
    InitiatingProcessFolderPath,
    InitiatingProcessCommandLine
| order by NetworkTimestamp desc
```

Combine IP address with TI in Sentinel

```kql
DeviceInfo
| where IsInternetFacing
| extend InternetFacingInfo = AdditionalFields 
| extend InternetFacingLastSeen = tostring(AdditionalFields.InternetFacingLastSeen)
| extend InternetFacingLocalIp = tostring(AdditionalFields.InternetFacingLocalIp)
| extend InternetFacingLocalPort = tostring(AdditionalFields.InternetFacingLocalPort)
| extend InternetFacingPublicScannedIp = tostring(AdditionalFields.InternetFacingPublicScannedIp)
| extend InternetFacingPublicScannedPort = tostring(AdditionalFields.InternetFacingPublicScannedPort)
| extend InternetFacingReason = tostring(AdditionalFields.InternetFacingReason)
| extend InternetFacingTransportProtocol = tostring(AdditionalFields.InternetFacingTransportProtocol)
| where InternetFacingReason == "ExternalNetworkConnection"
| join kind=leftouter  (DeviceNetworkEvents
| where RemoteIPType == "Public"
| distinct DeviceName, LocalIP, LocalPort, LocalIPType, RemoteIP, RemoteIPType, RemotePort, ActionType,InitiatingProcessFolderPath
)
on $left. DeviceName == $right. DeviceName
| where LocalIP contains InternetFacingLocalIp
| where LocalPort == InternetFacingLocalPort
| project-keep TimeGenerated, DeviceName,PublicIP, LocalIP, LocalPort, RemoteIP, RemotePort, RemoteIPType, ActionType,  InternetFacing*, InitiatingProcessFolderPath 
| project-away InternetFacingInfo
| join kind=innerunique  (ThreatIntelligenceIndicator
    | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
    | where Active == true
    | where isnotempty(NetworkIP)
        or isnotempty(EmailSourceIpAddress)
        or isnotempty(NetworkDestinationIP)
        or isnotempty(NetworkSourceIP)
    | extend TI_ipEntity = iff(isnotempty(NetworkIP), NetworkIP, NetworkDestinationIP)
    | extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(NetworkSourceIP), NetworkSourceIP, TI_ipEntity)
    | extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(EmailSourceIpAddress), EmailSourceIpAddress, TI_ipEntity))
    on $left. RemoteIP == $right. TI_ipEntity
```

Explanation

This set of KQL queries is designed to help identify and analyze internet-facing devices within a network using Microsoft Defender for Endpoint. Here's a simplified breakdown of what each query does:

  1. Identify Internet-Facing Devices:

    • This query finds devices that are exposed to the internet. It extracts details such as the last time they were seen online, their local and public IP addresses, ports, reasons for being internet-facing, and the protocols used. It summarizes this information by device name and orders the results by the last seen time.
  2. Devices Detected by External Scans:

    • This query looks for devices that have been scanned from the internet in the last 7 days. It captures the time of the scan, device details, and the public IP and port that were scanned.
  3. Devices Detected by External Scans with Geolocation:

    • Similar to the previous query, this one also includes geolocation information for the public IPs that scanned the devices. It provides details like country, state, and city, helping to understand where the scans originated.
  4. SMB Ports:

    • This query focuses on internet-facing devices that have SMB ports (139 and 445) open. It provides details about these devices, including their IP addresses and the reasons they are exposed.
  5. RDP Ports:

    • This query identifies devices with the Remote Desktop Protocol (RDP) port (3389) open to the internet. It provides similar details as the SMB query.
  6. External Network Connections:

    • This query is still in testing and aims to find devices with external network connections. It combines information about internet-facing devices with public network connections over the past 30 days.
  7. Combine IP Address with Threat Intelligence in Sentinel:

    • This query attempts to match internet-facing devices with threat intelligence data. It looks for any overlap between the devices' IP addresses and known threat indicators, helping to identify potential security threats.

Overall, these queries are used to monitor and investigate devices that are exposed to the internet, helping to assess potential security risks and take appropriate actions to protect the network.

Details

Alex Verboon profile picture

Alex Verboon

Released: June 20, 2026

Tables

DeviceInfoDeviceNetworkEventsThreatIntelligenceIndicator

Keywords

DevicesPortsProtocolsIPGeoLocationNetworkConnectionThreatIntelligence

Operators

`where``extend``parse_json``tostring``todatetime``toint``summarize``make_set``max``by``order by``desc``ago``arg_max``project``isnotempty``geo_info_from_ip_address``todouble``in``let``join``kind=leftouter``kind=innerunique``distinct``contains``project-keep``project-away``summarize``arg_max``iff``isempty`

Actions