Microsoft Sentinel Analytic Rules
cloudbrothers.infoAzure Sentinel RepoToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeBack to homepage

Microsoft Entra ID Health Monitoring Agent Registry Keys Access

Back
Idf819c592-c5f9-4d5c-a79f-1e6819863533
RulenameMicrosoft Entra ID Health Monitoring Agent Registry Keys Access
DescriptionThis detection uses Windows security events to detect suspicious access attempts to the registry key of Microsoft Entra ID Health monitoring agent.

This detection requires an access control entry (ACE) on the system access control list (SACL) of the following securable object HKLM\SOFTWARE\Microsoft\Microsoft Online\Reporting\MonitoringAgent.

You can find more information in here https://github.com/OTRF/Set-AuditRule/blob/master/rules/registry/aad_connect_health_monitoring_agent.yml
SeverityMedium
TacticsCollection
TechniquesT1005
Required data connectorsSecurityEvents
WindowsForwardedEvents
WindowsSecurityEvents
KindScheduled
Query frequency1d
Query period1d
Trigger threshold0
Trigger operatorgt
Source Urihttps://github.com/Azure/Azure-Sentinel/blob/master/Detections/SecurityEvent/AADHealthMonAgentRegKeyAccess.yaml
Version1.1.6
Arm templatef819c592-c5f9-4d5c-a79f-1e6819863533.json
Deploy To Azure
// ADHealth Monitoring Agent Registry Key
let aadHealthMonAgentRegKey = "\\REGISTRY\\MACHINE\\SOFTWARE\\Microsoft\\Microsoft Online\\Reporting\\MonitoringAgent";
// Filter out known processes
let aadConnectHealthProcs = dynamic ([
    'Microsoft.Identity.Health.Adfs.DiagnosticsAgent.exe',
    'Microsoft.Identity.Health.Adfs.InsightsService.exe',
    'Microsoft.Identity.Health.Adfs.MonitoringAgent.Startup.exe',
    'Microsoft.Identity.Health.Adfs.PshSurrogate.exe',
    'Microsoft.Identity.Health.Common.Clients.ResourceMonitor.exe',
    'Microsoft.Identity.Health.AadSync.MonitoringAgent.Startup.exe',
    'Microsoft.Identity.AadConnect.Health.AadSync.Host.exe',
    'Microsoft.Azure.ActiveDirectory.Synchronization.Upgrader.exe',
    'miiserver.exe'
]);
(union isfuzzy=true
(
SecurityEvent
| where EventID == '4656'
| where EventData has aadHealthMonAgentRegKey
| extend EventData = parse_xml(EventData).EventData.Data
| mv-expand bagexpansion=array EventData
| evaluate bag_unpack(EventData)
| extend Key = tostring(column_ifexists('@Name', "")), Value = column_ifexists('#text', "")
| evaluate pivot(Key, any(Value), TimeGenerated, Computer, EventID)
| extend ObjectName = column_ifexists("ObjectName", ""),
    ObjectType = column_ifexists("ObjectType", "")
| where ObjectType == 'Key'
| where ObjectName == aadHealthMonAgentRegKey
| extend SubjectUserName = column_ifexists("SubjectUserName", ""),
    SubjectDomainName = column_ifexists("SubjectDomainName", ""),
    ProcessName = column_ifexists("ProcessName", "")
| extend Process = split(ProcessName, '\\', -1)[-1],
    Account = strcat(SubjectDomainName, "\\", SubjectUserName)
| where Process !in (aadConnectHealthProcs)
| summarize StartTime = max(TimeGenerated), EndTime = min(TimeGenerated), count() by EventID, Account, Computer, Process, SubjectUserName, SubjectDomainName, ObjectName, ObjectType, ProcessName
),
(
WindowsEvent
| where EventID == '4656' and EventData has aadHealthMonAgentRegKey
| extend ObjectType = tostring(EventData.ObjectType)
| where ObjectType == 'Key'
| extend ObjectName = tostring(EventData.ObjectName)
| where ObjectName == aadHealthMonAgentRegKey
| extend ProcessName = tostring(EventData.ProcessName)
| extend Process = tostring(split(ProcessName, '\\')[-1])
| where Process !in (aadConnectHealthProcs)
| extend Account =  strcat(tostring(EventData.SubjectDomainName),"\\", tostring(EventData.SubjectUserName))
| extend SubjectUserName = tostring(EventData.SubjectUserName)
| extend SubjectDomainName = tostring(EventData.SubjectDomainName)
| summarize StartTime = max(TimeGenerated), EndTime = min(TimeGenerated), count() by EventID, Account, Computer, Process, SubjectUserName, SubjectDomainName, ObjectName, ObjectType, ProcessName
),
(
SecurityEvent
| where EventID == '4663'
| where ObjectType == 'Key'
| where ObjectName == aadHealthMonAgentRegKey
| extend Process = tostring(split(ProcessName, '\\', -1)[-1])
| where Process !in (aadConnectHealthProcs)
| summarize StartTime = max(TimeGenerated), EndTime = min(TimeGenerated), count() by EventID, Account, Computer, Process, SubjectUserName, SubjectDomainName, ObjectName, ObjectType, ProcessName
),
  (
WindowsEvent
| where EventID == '4663' and EventData has aadHealthMonAgentRegKey
| extend ObjectType = tostring(EventData.ObjectType)
| where ObjectType == 'Key'
| extend ObjectName = tostring(EventData.ObjectName)
| where ObjectName == aadHealthMonAgentRegKey
| extend ProcessName = tostring(EventData.ProcessName)
| extend Process = tostring(split(ProcessName, '\\')[-1])
| where Process !in (aadConnectHealthProcs)
| extend Account =  strcat(tostring(EventData.SubjectDomainName),"\\", tostring(EventData.SubjectUserName))
| extend SubjectUserName = tostring(EventData.SubjectUserName)
| extend SubjectDomainName = tostring(EventData.SubjectDomainName)
| summarize StartTime = max(TimeGenerated), EndTime = min(TimeGenerated), count() by EventID, Account, Computer, Process, SubjectUserName, SubjectDomainName, ObjectName, ObjectType, ProcessName
)
)
// You can filter out potential machine accounts
//| where AccountType != 'Machine'
| extend HostName = tostring(split(Computer, ".")[0]), DomainIndex = toint(indexof(Computer, '.'))
| extend HostNameDomain = iff(DomainIndex != -1, substring(Computer, DomainIndex + 1), Computer)
| extend Name = tostring(split(Account, "\\")[1]), NTDomain = tostring(split(Account, "\\")[0])
| project-away DomainIndex
requiredDataConnectors:
- connectorId: SecurityEvents
  dataTypes:
  - SecurityEvent
- connectorId: WindowsSecurityEvents
  dataTypes:
  - SecurityEvents
- connectorId: WindowsForwardedEvents
  dataTypes:
  - WindowsEvent
relevantTechniques:
- T1005
queryFrequency: 1d
id: f819c592-c5f9-4d5c-a79f-1e6819863533
name: Microsoft Entra ID Health Monitoring Agent Registry Keys Access
severity: Medium
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Detections/SecurityEvent/AADHealthMonAgentRegKeyAccess.yaml
queryPeriod: 1d
entityMappings:
- fieldMappings:
  - columnName: Account
    identifier: FullName
  - columnName: Name
    identifier: Name
  - columnName: NTDomain
    identifier: NTDomain
  entityType: Account
- fieldMappings:
  - columnName: Computer
    identifier: FullName
  - columnName: HostName
    identifier: HostName
  - columnName: HostNameDomain
    identifier: DnsDomain
  entityType: Host
description: |
  'This detection uses Windows security events to detect suspicious access attempts to the registry key of Microsoft Entra ID Health monitoring agent.
  This detection requires an access control entry (ACE) on the system access control list (SACL) of the following securable object HKLM\SOFTWARE\Microsoft\Microsoft Online\Reporting\MonitoringAgent.
  You can find more information in here https://github.com/OTRF/Set-AuditRule/blob/master/rules/registry/aad_connect_health_monitoring_agent.yml
  '  
triggerThreshold: 0
tactics:
- Collection
tags:
- SimuLand
query: |
  // ADHealth Monitoring Agent Registry Key
  let aadHealthMonAgentRegKey = "\\REGISTRY\\MACHINE\\SOFTWARE\\Microsoft\\Microsoft Online\\Reporting\\MonitoringAgent";
  // Filter out known processes
  let aadConnectHealthProcs = dynamic ([
      'Microsoft.Identity.Health.Adfs.DiagnosticsAgent.exe',
      'Microsoft.Identity.Health.Adfs.InsightsService.exe',
      'Microsoft.Identity.Health.Adfs.MonitoringAgent.Startup.exe',
      'Microsoft.Identity.Health.Adfs.PshSurrogate.exe',
      'Microsoft.Identity.Health.Common.Clients.ResourceMonitor.exe',
      'Microsoft.Identity.Health.AadSync.MonitoringAgent.Startup.exe',
      'Microsoft.Identity.AadConnect.Health.AadSync.Host.exe',
      'Microsoft.Azure.ActiveDirectory.Synchronization.Upgrader.exe',
      'miiserver.exe'
  ]);
  (union isfuzzy=true
  (
  SecurityEvent
  | where EventID == '4656'
  | where EventData has aadHealthMonAgentRegKey
  | extend EventData = parse_xml(EventData).EventData.Data
  | mv-expand bagexpansion=array EventData
  | evaluate bag_unpack(EventData)
  | extend Key = tostring(column_ifexists('@Name', "")), Value = column_ifexists('#text', "")
  | evaluate pivot(Key, any(Value), TimeGenerated, Computer, EventID)
  | extend ObjectName = column_ifexists("ObjectName", ""),
      ObjectType = column_ifexists("ObjectType", "")
  | where ObjectType == 'Key'
  | where ObjectName == aadHealthMonAgentRegKey
  | extend SubjectUserName = column_ifexists("SubjectUserName", ""),
      SubjectDomainName = column_ifexists("SubjectDomainName", ""),
      ProcessName = column_ifexists("ProcessName", "")
  | extend Process = split(ProcessName, '\\', -1)[-1],
      Account = strcat(SubjectDomainName, "\\", SubjectUserName)
  | where Process !in (aadConnectHealthProcs)
  | summarize StartTime = max(TimeGenerated), EndTime = min(TimeGenerated), count() by EventID, Account, Computer, Process, SubjectUserName, SubjectDomainName, ObjectName, ObjectType, ProcessName
  ),
  (
  WindowsEvent
  | where EventID == '4656' and EventData has aadHealthMonAgentRegKey
  | extend ObjectType = tostring(EventData.ObjectType)
  | where ObjectType == 'Key'
  | extend ObjectName = tostring(EventData.ObjectName)
  | where ObjectName == aadHealthMonAgentRegKey
  | extend ProcessName = tostring(EventData.ProcessName)
  | extend Process = tostring(split(ProcessName, '\\')[-1])
  | where Process !in (aadConnectHealthProcs)
  | extend Account =  strcat(tostring(EventData.SubjectDomainName),"\\", tostring(EventData.SubjectUserName))
  | extend SubjectUserName = tostring(EventData.SubjectUserName)
  | extend SubjectDomainName = tostring(EventData.SubjectDomainName)
  | summarize StartTime = max(TimeGenerated), EndTime = min(TimeGenerated), count() by EventID, Account, Computer, Process, SubjectUserName, SubjectDomainName, ObjectName, ObjectType, ProcessName
  ),
  (
  SecurityEvent
  | where EventID == '4663'
  | where ObjectType == 'Key'
  | where ObjectName == aadHealthMonAgentRegKey
  | extend Process = tostring(split(ProcessName, '\\', -1)[-1])
  | where Process !in (aadConnectHealthProcs)
  | summarize StartTime = max(TimeGenerated), EndTime = min(TimeGenerated), count() by EventID, Account, Computer, Process, SubjectUserName, SubjectDomainName, ObjectName, ObjectType, ProcessName
  ),
    (
  WindowsEvent
  | where EventID == '4663' and EventData has aadHealthMonAgentRegKey
  | extend ObjectType = tostring(EventData.ObjectType)
  | where ObjectType == 'Key'
  | extend ObjectName = tostring(EventData.ObjectName)
  | where ObjectName == aadHealthMonAgentRegKey
  | extend ProcessName = tostring(EventData.ProcessName)
  | extend Process = tostring(split(ProcessName, '\\')[-1])
  | where Process !in (aadConnectHealthProcs)
  | extend Account =  strcat(tostring(EventData.SubjectDomainName),"\\", tostring(EventData.SubjectUserName))
  | extend SubjectUserName = tostring(EventData.SubjectUserName)
  | extend SubjectDomainName = tostring(EventData.SubjectDomainName)
  | summarize StartTime = max(TimeGenerated), EndTime = min(TimeGenerated), count() by EventID, Account, Computer, Process, SubjectUserName, SubjectDomainName, ObjectName, ObjectType, ProcessName
  )
  )
  // You can filter out potential machine accounts
  //| where AccountType != 'Machine'
  | extend HostName = tostring(split(Computer, ".")[0]), DomainIndex = toint(indexof(Computer, '.'))
  | extend HostNameDomain = iff(DomainIndex != -1, substring(Computer, DomainIndex + 1), Computer)
  | extend Name = tostring(split(Account, "\\")[1]), NTDomain = tostring(split(Account, "\\")[0])
  | project-away DomainIndex  
kind: Scheduled
triggerOperator: gt
metadata:
  support:
    tier: Community
  author:
    name: Microsoft Security Research
  source:
    kind: Community
  categories:
    domains:
    - Security - Others
    - Identity
version: 1.1.6
{
  "$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/f819c592-c5f9-4d5c-a79f-1e6819863533')]",
      "kind": "Scheduled",
      "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/f819c592-c5f9-4d5c-a79f-1e6819863533')]",
      "properties": {
        "alertRuleTemplateName": "f819c592-c5f9-4d5c-a79f-1e6819863533",
        "customDetails": null,
        "description": "'This detection uses Windows security events to detect suspicious access attempts to the registry key of Microsoft Entra ID Health monitoring agent.\nThis detection requires an access control entry (ACE) on the system access control list (SACL) of the following securable object HKLM\\SOFTWARE\\Microsoft\\Microsoft Online\\Reporting\\MonitoringAgent.\nYou can find more information in here https://github.com/OTRF/Set-AuditRule/blob/master/rules/registry/aad_connect_health_monitoring_agent.yml\n'\n",
        "displayName": "Microsoft Entra ID Health Monitoring Agent Registry Keys Access",
        "enabled": true,
        "entityMappings": [
          {
            "entityType": "Account",
            "fieldMappings": [
              {
                "columnName": "Account",
                "identifier": "FullName"
              },
              {
                "columnName": "Name",
                "identifier": "Name"
              },
              {
                "columnName": "NTDomain",
                "identifier": "NTDomain"
              }
            ]
          },
          {
            "entityType": "Host",
            "fieldMappings": [
              {
                "columnName": "Computer",
                "identifier": "FullName"
              },
              {
                "columnName": "HostName",
                "identifier": "HostName"
              },
              {
                "columnName": "HostNameDomain",
                "identifier": "DnsDomain"
              }
            ]
          }
        ],
        "OriginalUri": "https://github.com/Azure/Azure-Sentinel/blob/master/Detections/SecurityEvent/AADHealthMonAgentRegKeyAccess.yaml",
        "query": "// ADHealth Monitoring Agent Registry Key\nlet aadHealthMonAgentRegKey = \"\\\\REGISTRY\\\\MACHINE\\\\SOFTWARE\\\\Microsoft\\\\Microsoft Online\\\\Reporting\\\\MonitoringAgent\";\n// Filter out known processes\nlet aadConnectHealthProcs = dynamic ([\n    'Microsoft.Identity.Health.Adfs.DiagnosticsAgent.exe',\n    'Microsoft.Identity.Health.Adfs.InsightsService.exe',\n    'Microsoft.Identity.Health.Adfs.MonitoringAgent.Startup.exe',\n    'Microsoft.Identity.Health.Adfs.PshSurrogate.exe',\n    'Microsoft.Identity.Health.Common.Clients.ResourceMonitor.exe',\n    'Microsoft.Identity.Health.AadSync.MonitoringAgent.Startup.exe',\n    'Microsoft.Identity.AadConnect.Health.AadSync.Host.exe',\n    'Microsoft.Azure.ActiveDirectory.Synchronization.Upgrader.exe',\n    'miiserver.exe'\n]);\n(union isfuzzy=true\n(\nSecurityEvent\n| where EventID == '4656'\n| where EventData has aadHealthMonAgentRegKey\n| extend EventData = parse_xml(EventData).EventData.Data\n| mv-expand bagexpansion=array EventData\n| evaluate bag_unpack(EventData)\n| extend Key = tostring(column_ifexists('@Name', \"\")), Value = column_ifexists('#text', \"\")\n| evaluate pivot(Key, any(Value), TimeGenerated, Computer, EventID)\n| extend ObjectName = column_ifexists(\"ObjectName\", \"\"),\n    ObjectType = column_ifexists(\"ObjectType\", \"\")\n| where ObjectType == 'Key'\n| where ObjectName == aadHealthMonAgentRegKey\n| extend SubjectUserName = column_ifexists(\"SubjectUserName\", \"\"),\n    SubjectDomainName = column_ifexists(\"SubjectDomainName\", \"\"),\n    ProcessName = column_ifexists(\"ProcessName\", \"\")\n| extend Process = split(ProcessName, '\\\\', -1)[-1],\n    Account = strcat(SubjectDomainName, \"\\\\\", SubjectUserName)\n| where Process !in (aadConnectHealthProcs)\n| summarize StartTime = max(TimeGenerated), EndTime = min(TimeGenerated), count() by EventID, Account, Computer, Process, SubjectUserName, SubjectDomainName, ObjectName, ObjectType, ProcessName\n),\n(\nWindowsEvent\n| where EventID == '4656' and EventData has aadHealthMonAgentRegKey\n| extend ObjectType = tostring(EventData.ObjectType)\n| where ObjectType == 'Key'\n| extend ObjectName = tostring(EventData.ObjectName)\n| where ObjectName == aadHealthMonAgentRegKey\n| extend ProcessName = tostring(EventData.ProcessName)\n| extend Process = tostring(split(ProcessName, '\\\\')[-1])\n| where Process !in (aadConnectHealthProcs)\n| extend Account =  strcat(tostring(EventData.SubjectDomainName),\"\\\\\", tostring(EventData.SubjectUserName))\n| extend SubjectUserName = tostring(EventData.SubjectUserName)\n| extend SubjectDomainName = tostring(EventData.SubjectDomainName)\n| summarize StartTime = max(TimeGenerated), EndTime = min(TimeGenerated), count() by EventID, Account, Computer, Process, SubjectUserName, SubjectDomainName, ObjectName, ObjectType, ProcessName\n),\n(\nSecurityEvent\n| where EventID == '4663'\n| where ObjectType == 'Key'\n| where ObjectName == aadHealthMonAgentRegKey\n| extend Process = tostring(split(ProcessName, '\\\\', -1)[-1])\n| where Process !in (aadConnectHealthProcs)\n| summarize StartTime = max(TimeGenerated), EndTime = min(TimeGenerated), count() by EventID, Account, Computer, Process, SubjectUserName, SubjectDomainName, ObjectName, ObjectType, ProcessName\n),\n  (\nWindowsEvent\n| where EventID == '4663' and EventData has aadHealthMonAgentRegKey\n| extend ObjectType = tostring(EventData.ObjectType)\n| where ObjectType == 'Key'\n| extend ObjectName = tostring(EventData.ObjectName)\n| where ObjectName == aadHealthMonAgentRegKey\n| extend ProcessName = tostring(EventData.ProcessName)\n| extend Process = tostring(split(ProcessName, '\\\\')[-1])\n| where Process !in (aadConnectHealthProcs)\n| extend Account =  strcat(tostring(EventData.SubjectDomainName),\"\\\\\", tostring(EventData.SubjectUserName))\n| extend SubjectUserName = tostring(EventData.SubjectUserName)\n| extend SubjectDomainName = tostring(EventData.SubjectDomainName)\n| summarize StartTime = max(TimeGenerated), EndTime = min(TimeGenerated), count() by EventID, Account, Computer, Process, SubjectUserName, SubjectDomainName, ObjectName, ObjectType, ProcessName\n)\n)\n// You can filter out potential machine accounts\n//| where AccountType != 'Machine'\n| extend HostName = tostring(split(Computer, \".\")[0]), DomainIndex = toint(indexof(Computer, '.'))\n| extend HostNameDomain = iff(DomainIndex != -1, substring(Computer, DomainIndex + 1), Computer)\n| extend Name = tostring(split(Account, \"\\\\\")[1]), NTDomain = tostring(split(Account, \"\\\\\")[0])\n| project-away DomainIndex\n",
        "queryFrequency": "P1D",
        "queryPeriod": "P1D",
        "severity": "Medium",
        "subTechniques": [],
        "suppressionDuration": "PT1H",
        "suppressionEnabled": false,
        "tactics": [
          "Collection"
        ],
        "tags": [
          "SimuLand"
        ],
        "techniques": [
          "T1005"
        ],
        "templateVersion": "1.1.6",
        "triggerOperator": "GreaterThan",
        "triggerThreshold": 0
      },
      "type": "Microsoft.OperationalInsights/workspaces/providers/alertRules"
    }
  ]
}