Detection rules › Kusto

Security Event log cleared

Status
available
Severity
medium
Time window
1d
Group by
Account, Activity, Computer, EventID
Source
github.com/Azure/Azure-Sentinel

Checks for event id 1102 which indicates the security event log was cleared. It uses Event Source Name "Microsoft-Windows-Eventlog" to avoid generating false positives from other sources, like AD FS servers for instance.

MITRE ATT&CK coverage

TacticTechniques
StealthT1070 Indicator Removal

Event coverage

ProviderEventTitle
EventlogEvent ID 1102The audit log was cleared.

Rule body kusto

id: 80da0a8f-cfe1-4cd0-a895-8bc1771a720e
name: Security Event log cleared
description: |
  'Checks for event id 1102 which indicates the security event log was cleared.
  It uses Event Source Name "Microsoft-Windows-Eventlog" to avoid generating false positives from other sources, like AD FS servers for instance.'
severity: Medium
status: Available
requiredDataConnectors:
  - connectorId: SecurityEvents
    dataTypes:
      - SecurityEvent
  - connectorId: WindowsSecurityEvents
    dataTypes:
      - SecurityEvent
  - connectorId: WindowsForwardedEvents
    dataTypes:
      - WindowsEvent
queryFrequency: 1d
queryPeriod: 1d
triggerOperator: gt
triggerThreshold: 0
tactics:
  - DefenseEvasion
relevantTechniques:
  - T1070
query: |
  (union isfuzzy=true
  (
  SecurityEvent
  | where EventID == 1102 and EventSourceName =~ "Microsoft-Windows-Eventlog"
  | summarize StartTimeUtc = min(TimeGenerated), EndTimeUtc = max(TimeGenerated), EventCount = count() by Computer, Account, EventID, Activity
  ),
  (
  WindowsEvent
  | where EventID == 1102 and Provider =~ "Microsoft-Windows-Eventlog"
  | extend Account =  strcat(tostring(EventData.SubjectDomainName),"\\", tostring(EventData.SubjectUserName))
  | extend Activity= "1102 - The audit log was cleared."
  | summarize StartTimeUtc = min(TimeGenerated), EndTimeUtc = max(TimeGenerated), EventCount = count() by Computer, Account, EventID, Activity
  )
  )
  | extend Name=tostring(split(Account, "@")[0]), UPNSuffix=tostring(split(Account, "@")[1])
  | extend HostName = iif(Computer has '.',substring(Computer,0,indexof(Computer,'.')),Computer) , DnsDomain = iif(Computer has '.',substring(Computer,indexof(Computer,'.')+1),'')
entityMappings:
  - entityType: Account
    fieldMappings:
      - identifier: Name
        columnName: Name
      - identifier: UPNSuffix
        columnName: UPNSuffix
  - entityType: Host
    fieldMappings:
      - identifier: FullName
        columnName: Computer
      - identifier: HostName
        columnName: HostName
      - identifier: DnsDomain
        columnName: DnsDomain
version: 1.1.5
kind: Scheduled

Stages and Predicates

union isfuzzy=true (2 sources)

Each leg below queries one source; the rule matches if any leg does. Sources: SecurityEvent, WindowsEvent

Leg 1: SecurityEvent

SecurityEvent
| where EventID == 1102 and EventSourceName =~ "Microsoft-Windows-Eventlog"
| summarize StartTimeUtc = min(TimeGenerated), EndTimeUtc = max(TimeGenerated), EventCount = count() by Computer, Account, EventID, Activity

Leg 2: WindowsEvent

WindowsEvent
| where EventID == 1102 and Provider =~ "Microsoft-Windows-Eventlog"
| extend Account =  strcat(tostring(EventData.SubjectDomainName),"\\", tostring(EventData.SubjectUserName))
| extend Activity= "1102 - The audit log was cleared."
| summarize StartTimeUtc = min(TimeGenerated), EndTimeUtc = max(TimeGenerated), EventCount = count() by Computer, Account, EventID, Activity

Applied to the combined result

| extend Name=tostring(split(Account, "@")[0]), UPNSuffix=tostring(split(Account, "@")[1])
| extend HostName = iif(Computer has '.',substring(Computer,0,indexof(Computer,'.')),Computer) , DnsDomain = iif(Computer has '.',substring(Computer,indexof(Computer,'.')+1),'')

Indicators

Each row is a field, operator, and value that the rule matches. The corpus column counts how many other rules in the catalog look for the same combination: high numbers point to widely-used, community-vetted indicators. Blank or 1 shows that the indicator is specific to this rule.

FieldKindValues
EventIDeq
  • 1102 transforms: cased corpus 4 (splunk 2, kusto 2)
EventSourceNameeq
  • Microsoft-Windows-Eventlog corpus 2 (kusto 2)
Providereq
  • Microsoft-Windows-Eventlog

Output fields

Fields the rule emits when it matches. Chronicle authors list these in the outcome block; they appear on the detection and $risk_score drives alerting. Sentinel / Defender XDR rules build them up through project / summarize / extend stages. Sentinel maps these into alert fields via entityMappings and customDetails; Defender XDR custom detections surface them as alert fields directly.

FieldSource
Accountsummarize
Activitysummarize
Computersummarize
EndTimeUtcsummarize
EventCountsummarize
EventIDsummarize
StartTimeUtcsummarize
Nameextend
UPNSuffixextend
DnsDomainextend
HostNameextend