← Back to SOC feed Coverage →

System Guard Security Level Drop

kql MEDIUM Azure-Sentinel
DeviceEvents
huntingmicrosoftofficial
This rule was pulled from an open-source repository and enriched with AI. Validate in a test environment before deploying to production.
View original rule at Azure-Sentinel →
Retrieved: 2026-05-22T23:00:00Z · Confidence: medium

Hunt Hypothesis

Adversaries may be attempting to lower the SystemGuardSecurityLevel to evade detection or disable security controls. SOC teams should proactively hunt for this behavior in Azure Sentinel to identify potential tampering with system security settings and detect early signs of compromise.

KQL Query

let SecurityLevels = DeviceEvents
| where Timestamp >= ago(7d)
| where ActionType == "DeviceBootAttestationInfo"
| extend AdditionalFieldData = parse_json(AdditionalFields)
| project DeviceId, Timestamp, SystemGuardSecurityLevel = toint(AdditionalFieldData.SystemGuardSecurityLevel), ReportId
| where isnotnull(SystemGuardSecurityLevel);
// Step 2: Get the *latest* record for *each* machine from the SecurityLevels table
let LatestLevelsPerMachine = SecurityLevels
 // This is going to be the most recent event
| summarize arg_max(Timestamp, SystemGuardSecurityLevel) by DeviceId
| project DeviceId, LatestSystemGuardSecurityLevel=SystemGuardSecurityLevel, LatestEventTime=Timestamp;
// Step 3: Join the two tables together where the LatestSystemGuardSecurityLevel is LESS than the SystemGuardSecurityLevel 
let MachinesExhibitingSecurityLevelDrop = LatestLevelsPerMachine
| join (
 SecurityLevels
) on DeviceId
| project-away DeviceId1
| where LatestSystemGuardSecurityLevel < SystemGuardSecurityLevel 
| summarize arg_max(Timestamp, LatestSystemGuardSecurityLevel, SystemGuardSecurityLevel, LatestEventTime, ReportId) by DeviceId;
MachinesExhibitingSecurityLevelDrop

Analytic Rule Definition

id: 701bee2f-c4d9-4f72-be03-e6bb1314e71c
name: System Guard Security Level Drop
description: |
  Goal: Find machines in the last N days where the SystemGuardSecurityLevel value NOW is less than it was BEFORE.
  Step 1: Get a list of all security levels in the system where the level is not null.
requiredDataConnectors:
- connectorId: MicrosoftThreatProtection
  dataTypes:
  - DeviceEvents
query: |
  let SecurityLevels = DeviceEvents
  | where Timestamp >= ago(7d)
  | where ActionType == "DeviceBootAttestationInfo"
  | extend AdditionalFieldData = parse_json(AdditionalFields)
  | project DeviceId, Timestamp, SystemGuardSecurityLevel = toint(AdditionalFieldData.SystemGuardSecurityLevel), ReportId
  | where isnotnull(SystemGuardSecurityLevel);
  // Step 2: Get the *latest* record for *each* machine from the SecurityLevels table
  let LatestLevelsPerMachine = SecurityLevels
   // This is going to be the most recent event
  | summarize arg_max(Timestamp, SystemGuardSecurityLevel) by DeviceId
  | project DeviceId, LatestSystemGuardSecurityLevel=SystemGuardSecurityLevel, LatestEventTime=Timestamp;
  // Step 3: Join the two tables together where the LatestSystemGuardSecurityLevel is LESS than the SystemGuardSecurityLevel 
  let MachinesExhibitingSecurityLevelDrop = LatestLevelsPerMachine
  | join (
   SecurityLevels
  ) on DeviceId
  | project-away DeviceId1
  | where LatestSystemGuardSecurityLevel < SystemGuardSecurityLevel 
  | summarize arg_max(Timestamp, LatestSystemGuardSecurityLevel, SystemGuardSecurityLevel, LatestEventTime, ReportId) by DeviceId;
  MachinesExhibitingSecurityLevelDrop

Required Data Sources

Sentinel TableNotes
DeviceEventsEnsure this data connector is enabled

References

False Positive Guidance

Original source: https://github.com/Azure/Azure-Sentinel/blob/main/Hunting Queries/Microsoft 365 Defender/General queries/System Guard Security Level Drop.yaml