Query Details
# *Hunt for public remotly exploitable devices (with high EPSS)*
## Query Information
#### MITRE ATT&CK Technique(s)
| Technique ID | Title | Link |
| --- | --- | --- |
| T1190 | Exploit Public-Facing Application | https://attack.mitre.org/techniques/T1190 |
#### Description
This query searches for devices that comply with the following criteria:
- Incomming connections from public IP addresses in last 7 days (internet exposed)
- High or Critical severity CVE's
- CVE's must have known exploits
- CVE's are remotely exploitable over the network
- No user interaction is required to exploit the CVE's
- EPSS score of CVE must by above 10% (likelihood of exploitation)
> If devices are placed behind a proxy, they will not be returned in this query by default
#### Risk
Devices that return from these results are possible high-risk devices that could be exploited successfully any time.
#### 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
## Defender XDR
```KQL
// Flag remotly exploitable, no user interaction, CVE's with a EPSS score above a certain threshold (likelyhood of exploitation)
// For devices with incomming public connections
// See efficiency research on https://www.first.org/epss/model
let epss_threshold = 0.1;
let exploit_statusses = dynamic(["ExploitIsPublic","ExploitIsInKit","ExploitIsVerified"]);
// Xspm base query we materialize since we need these results multiple times
let xspm_base = materialize (
ExposureGraphNodes
// Get device nodes with their inventory ID
| mv-expand EntityIds
| where EntityIds.type == "DeviceInventoryId"
// Get first important properties
| extend DeviceId = tostring(parse_json(EntityIds)["id"]),
ExposureScore = tostring(parse_json(NodeProperties)["rawData"]["exposureScore"]),
HasHighOrCriticalCve = tostring(parse_json(NodeProperties)["rawData"]["highRiskVulnerabilityInsights"]["hasHighOrCritical"])
// Focus on devices with high exposure
| where ExposureScore == "High"
// Get vulnerability exploit information
| extend RceExploitLevels = parse_json(NodeProperties)["rawData"]["highRiskVulnerabilityInsights"]["vulnerableToRemoteCodeExecution"]["explotabilityLevels"]
| extend PrivEscExploitLevels = parse_json(NodeProperties)["rawData"]["highRiskVulnerabilityInsights"]["vulnerableToPrivilegeEscalation"]["explotabilityLevels"]
// Focus on devices where cve has known epxloits
| where RceExploitLevels has_any (exploit_statusses) or PrivEscExploitLevels has_any (exploit_statusses)
// Focus on devices that are public exposed
| join kind=inner (
DeviceNetworkEvents
| where TimeGenerated > ago(7d)
| where ActionType contains "InboundConnection"
| where RemoteIPType == "Public"
// Exclude MacOS Rapportd and ControlCenter
| where InitiatingProcessFileName != "rapportd" and InitiatingProcessFileName != "controlcenter"
| distinct DeviceName, DeviceId, LocalPort, InitiatingProcessFolderPath, InitiatingProcessVersionInfoProductName, InitiatingProcessFileName
) on $left.DeviceId == $right.DeviceId
// Save all the open ports and their process in a JSON
| extend OpenPortJson = bag_pack_columns(LocalPort, InitiatingProcessFolderPath, InitiatingProcessFileName)
// Save open ports by Device ID
| summarize PublicOpenPortList = make_set(OpenPortJson) by DeviceId
);
// Save flagged device IDs in list to limit results of CVE's we need to search later
let flagged_devices = toscalar(
xspm_base
| summarize make_set(DeviceId)
);
// CVE base query we materialize since we need these results multiple times
let cve_base = materialize (
DeviceTvmSoftwareVulnerabilities
| where VulnerabilitySeverityLevel in ("High", "Critical")
| where DeviceId in ( flagged_devices )
);
// Save flagged CVE IDs in list to limit results of CVE database we need to search later
let flagged_cves = toscalar(
cve_base
| summarize make_set(CveId)
);
// Query the CVE's of the flagged devices
cve_base
// Enrich the CVE data with their EPSS and CVSS Score
| join kind=inner (
DeviceTvmSoftwareVulnerabilitiesKB
// Focus on flagged CVE's
| where CveId in ( flagged_cves )
// Focus on CVE's tagged with Attack Vector being over the Network
// 'Vulnerabilities with this rating are remotely exploitable, from one or more hops away, up to and including remote exploitation over the Internet.'
// 'Does not require user interaction'
| where CvssVector contains "/AV:N" and CvssVector contains "/UI:N"
// Focus on CVE's where an exploit is available
| where IsExploitAvailable != 0
| distinct CveId, EpssScore, CvssScore, CvssVector, IsExploitAvailable, AffectedSoftwareList=tostring(AffectedSoftware)
) on CveId
// Continue with only relevant data
| project DeviceId, DeviceName, OSPlatform, OSVersion, OSArchitecture, SoftwareName, SoftwareVendor, SoftwareVersion, CveId, VulnerabilitySeverityLevel, EpssScore, CvssScore, CvssVector, IsExploitAvailable, AffectedSoftwareList
// Now flag CVE's with a EPSS score above a certain threshold
// See efficiency research on https://www.first.org/epss/model
| where EpssScore >= epss_threshold
// Save all the CVE data in a JSON column
| extend CveJson = bag_pack_columns(SoftwareName, SoftwareVendor, SoftwareVersion, CveId, EpssScore, CvssScore, CvssVector, IsExploitAvailable, AffectedSoftwareList)
// Group the CVE data for each device per device
| summarize CveList = make_list(CveJson) by DeviceId, DeviceName
// Add xspm data again
| join kind=inner xspm_base on DeviceId
| project-away DeviceId1
// Sort by CVE amount
| extend CveCount = array_length(CveList)
| sort by CveCount desc
```This query is designed to identify potentially vulnerable devices within a network that are at high risk of being exploited. Here's a simplified breakdown of what the query does:
Objective: The query aims to find devices that are exposed to the internet and have vulnerabilities that can be exploited remotely without user interaction. These vulnerabilities have a high likelihood of being exploited, as indicated by their EPSS (Exploit Prediction Scoring System) score.
Criteria for Identifying Devices:
Process:
Output:
Risk:
Overall, this query helps security teams proactively identify and mitigate risks associated with publicly exposed devices that have severe vulnerabilities.

Robbe Van den Daele
Released: September 15, 2025
Tables
Keywords
Operators