Detection rules › Kusto

Clearing of forensic evidence from event logs using wevtutil

Status
available
Severity
high
Time window
5m
Group by
DeviceId, DeviceName
Source
github.com/Azure/Azure-Sentinel

This query checks for attempts to clear at least 10 log entries from event logs using wevtutil. Clearing event logs can be a sign of ransomware activity, as ransomware often attempts to cover its tracks by deleting logs.

MITRE ATT&CK coverage

TacticTechniques
Stealth

Telemetry coverage

Rule body

id: 515d0bba-b297-4f83-8280-20ff7f27ecb1
name: Clearing of forensic evidence from event logs using wevtutil
description: |
  This query checks for attempts to clear at least 10 log entries from event logs using wevtutil. Clearing event logs can be a sign of ransomware activity, as ransomware often attempts to cover its tracks by deleting logs.
severity: High
status: Available
requiredDataConnectors:
  - connectorId: MicrosoftThreatProtection
    dataTypes:
      - DeviceProcessEvents
queryFrequency: 1d
queryPeriod: 1d
triggerOperator: gt
triggerThreshold: 0
tactics:
  - DefenseEvasion
relevantTechniques:
  - T1070
query: |
  // Look for use of wevtutil to clear multiple logs
  DeviceProcessEvents
  | where ProcessCommandLine has "WEVTUTIL" and ProcessCommandLine has "CL"
  | summarize LogClearCount = dcount(tostring(ProcessCommandLine)), ClearedLogList = make_set(ProcessCommandLine, 100000) by DeviceId, DeviceName, bin(TimeGenerated, 5m)
  | where LogClearCount > 10
  | extend HostName = iff(DeviceName has '.', substring(DeviceName, 0, indexof(DeviceName, '.')), DeviceName)
  | extend DnsDomain = iff(DeviceName has '.', substring(DeviceName, indexof(DeviceName, '.') + 1), "")
entityMappings:
  - entityType: Host
    fieldMappings:
      - identifier: FullName
        columnName: DeviceName
      - identifier: HostName
        columnName: HostName
      - identifier: DnsDomain
        columnName: DnsDomain
version: 1.0.0
kind: Scheduled

Stages and Predicates

Stage 1: source

DeviceProcessEvents

Stage 2: where

| where ProcessCommandLine has "WEVTUTIL" and ProcessCommandLine has "CL"

Stage 3: summarize

| summarize LogClearCount = dcount(tostring(ProcessCommandLine)), ClearedLogList = make_set(ProcessCommandLine, 100000) by DeviceId, DeviceName, bin(TimeGenerated, 5m)

Stage 4: where

| where LogClearCount > 10

Stage 5: extend

| extend HostName = iff(DeviceName has '.', substring(DeviceName, 0, indexof(DeviceName, '.')), DeviceName)
HostName =
ifDeviceName has "."substring(DeviceName, 0, indexof(DeviceName, '.'))
elseDeviceName

Stage 6: extend

| extend DnsDomain = iff(DeviceName has '.', substring(DeviceName, indexof(DeviceName, '.') + 1), "")
DnsDomain =
ifDeviceName has "."substring(DeviceName, (indexof(DeviceName, '.') + 1))
else""

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
LogClearCountgt
  • 10
field:"LogClearCount" kind:gt value:"10"
ProcessCommandLinematch
  • CL transforms: term corpus 3 (sigma 2, kusto 1)
  • WEVTUTIL transforms: term
field:"CommandLine" kind:match

Output fields

These fields are emitted when the rule matches.

FieldSource
ClearedLogListsummarize
DeviceIdsummarize
DeviceNamesummarize
LogClearCountsummarize
HostNameextend
DnsDomainextend