Analytic rule catalog
CTE - Stale Device No Heartbeat in 30 Days
Back
| Id | a6d51bc1-bf51-47d1-9885-b81762cd6306 |
| Rulename | CTE - Stale Device (No Heartbeat in 30 Days) |
| Description | A device is still marked active in the Devices table but has not sent a heartbeat in 30+ days. Emitted once per device by the daily tenant health-check job (api/src/functions/tenantHealthChecks.js); clears automatically if the device checks in again, so it can re-fire after a later gap. |
| Severity | Medium |
| Tactics | DefenseEvasion |
| Techniques | T1562 |
| Required data connectors | cybereinforce_cte |
| Kind | Scheduled |
| Query frequency | 24h |
| Query period | 2d |
| Trigger threshold | 0 |
| Trigger operator | gt |
| Source Uri | https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Cybereinforce/Analytic%20Rules/StaleDeviceNoHeartbeatIn30Days.yaml |
| Version | 1.0.0 |
| Arm template | a6d51bc1-bf51-47d1-9885-b81762cd6306.json |
CybereinforceCTE_CL
| where EventType == "device.stale_heartbeat"
| extend d = parse_json(Details)
| extend
DeviceId = tostring(d.deviceId),
HostName = iff(isnotempty(tostring(d.hostname)), tostring(d.hostname), strcat("cte-device-", substring(EntityId, 0, 8))),
LastSeen = tostring(d.lastSeen)
| project TimeGenerated, TenantId, DeviceId, HostName, LastSeen, Severity, Category, Source
name: CTE - Stale Device (No Heartbeat in 30 Days)
triggerOperator: gt
query: |
CybereinforceCTE_CL
| where EventType == "device.stale_heartbeat"
| extend d = parse_json(Details)
| extend
DeviceId = tostring(d.deviceId),
HostName = iff(isnotempty(tostring(d.hostname)), tostring(d.hostname), strcat("cte-device-", substring(EntityId, 0, 8))),
LastSeen = tostring(d.lastSeen)
| project TimeGenerated, TenantId, DeviceId, HostName, LastSeen, Severity, Category, Source
queryFrequency: 24h
description: |
A device is still marked active in the Devices table but has not sent a heartbeat in 30+ days. Emitted once per device by the daily tenant health-check job (api/src/functions/tenantHealthChecks.js); clears automatically if the device checks in again, so it can re-fire after a later gap.
id: a6d51bc1-bf51-47d1-9885-b81762cd6306
triggerThreshold: 0
queryPeriod: 2d
version: 1.0.0
kind: Scheduled
relevantTechniques:
- T1562
severity: Medium
requiredDataConnectors:
- connectorId: cybereinforce_cte
dataTypes:
- CybereinforceCTE_CL
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Cybereinforce/Analytic%20Rules/StaleDeviceNoHeartbeatIn30Days.yaml
tactics:
- DefenseEvasion
entityMappings:
- fieldMappings:
- identifier: HostName
columnName: HostName
entityType: Host
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"workspace": {
"type": "String"
}
},
"resources": [
{
"apiVersion": "2024-01-01-preview",
"id": "[concat(resourceId('Microsoft.OperationalInsights/workspaces/providers', parameters('workspace'), 'Microsoft.SecurityInsights'),'/alertRules/a6d51bc1-bf51-47d1-9885-b81762cd6306')]",
"kind": "Scheduled",
"name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/a6d51bc1-bf51-47d1-9885-b81762cd6306')]",
"properties": {
"alertRuleTemplateName": "a6d51bc1-bf51-47d1-9885-b81762cd6306",
"customDetails": null,
"description": "A device is still marked active in the Devices table but has not sent a heartbeat in 30+ days. Emitted once per device by the daily tenant health-check job (api/src/functions/tenantHealthChecks.js); clears automatically if the device checks in again, so it can re-fire after a later gap.\n",
"displayName": "CTE - Stale Device (No Heartbeat in 30 Days)",
"enabled": true,
"entityMappings": [
{
"entityType": "Host",
"fieldMappings": [
{
"columnName": "HostName",
"identifier": "HostName"
}
]
}
],
"OriginalUri": "https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Cybereinforce/Analytic%20Rules/StaleDeviceNoHeartbeatIn30Days.yaml",
"query": "CybereinforceCTE_CL\n| where EventType == \"device.stale_heartbeat\"\n| extend d = parse_json(Details)\n| extend\n DeviceId = tostring(d.deviceId),\n HostName = iff(isnotempty(tostring(d.hostname)), tostring(d.hostname), strcat(\"cte-device-\", substring(EntityId, 0, 8))),\n LastSeen = tostring(d.lastSeen)\n| project TimeGenerated, TenantId, DeviceId, HostName, LastSeen, Severity, Category, Source\n",
"queryFrequency": "PT24H",
"queryPeriod": "P2D",
"severity": "Medium",
"subTechniques": [],
"suppressionDuration": "PT1H",
"suppressionEnabled": false,
"tactics": [
"DefenseEvasion"
],
"techniques": [
"T1562"
],
"templateVersion": "1.0.0",
"triggerOperator": "GreaterThan",
"triggerThreshold": 0
},
"type": "Microsoft.OperationalInsights/workspaces/providers/alertRules"
}
]
}