Detection rules › Kusto

WMI Spawning Suspicious Child Process (Living off the Land)

Status
available
Severity
high
Time window
1h
Source
github.com/Azure/Azure-Sentinel

Detects WmiPrvSE.exe (the WMI Provider Host) spawning high-risk processes such as PowerShell, cmd.exe, cscript, or other LOLBins. WMI requires no external tools, generates minimal disk artifacts, and can execute code on remote systems over DCOM/RPC while bypassing many controls. Tune AllowlistedCmdPatterns for known-safe management tools such as SCCM.

MITRE ATT&CK coverage

Telemetry coverage

Rule body

id: 3c8e5f0b-1d4a-4b69-9c2e-7f0d3a5e8b1f
name: WMI Spawning Suspicious Child Process (Living off the Land)
description: |
  Detects WmiPrvSE.exe (the WMI Provider Host) spawning high-risk processes
  such as PowerShell, cmd.exe, cscript, or other LOLBins.
  WMI requires no external tools, generates minimal disk artifacts, and can
  execute code on remote systems over DCOM/RPC while bypassing many controls.
  Tune AllowlistedCmdPatterns for known-safe management tools such as SCCM.
severity: High
status: Available
requiredDataConnectors:
  - connectorId: MicrosoftThreatProtection
    dataTypes:
      - DeviceProcessEvents
  - connectorId: SecurityEvents
    dataTypes:
      - SecurityEvent
queryFrequency: 1h
queryPeriod: 1h
triggerOperator: gt
triggerThreshold: 0
tactics:
  - Execution
  - LateralMovement
  - Persistence
relevantTechniques:
  - T1047
  - T1021.006
  - T1059.001
  - T1059.003
  - T1059.005
query: |
  let Lookback = 1h;
  let SuspiciousChildProcesses = dynamic([
    "powershell.exe", "pwsh.exe", "cmd.exe", "cscript.exe", "wscript.exe",
    "mshta.exe", "certutil.exe", "bitsadmin.exe", "regsvr32.exe",
    "rundll32.exe", "msiexec.exe", "installutil.exe", "cmstp.exe",
    "msbuild.exe", "wmic.exe", "net.exe", "net1.exe", "nltest.exe",
    "whoami.exe", "ipconfig.exe", "tasklist.exe", "schtasks.exe",
    "at.exe", "sc.exe", "reg.exe"
  ]);
  let AllowlistedCmdPatterns = dynamic([
    "ccmexec", "SMSAgent", "MOMAgent", "nessus", "qualys"
  ]);
  let NetworkIndicators = dynamic([
    "http://", "https://", "ftp://", "Net.WebClient",
    "DownloadString", "IEX", "Invoke-Expression", "/transfer", "-urlcache"
  ]);
  let CredentialIndicators = dynamic([
    "lsass", "mimikatz", "sekurlsa", "dump", "sam", "ntds"
  ]);
  let MDE_Results =
    DeviceProcessEvents
    | where Timestamp >= ago(Lookback)
    | where InitiatingProcessFileName =~ "WmiPrvSE.exe"
    | where FileName in~ (SuspiciousChildProcesses)
    | where not(ProcessCommandLine has_any (AllowlistedCmdPatterns))
    | extend
        ChildProcess       = FileName,
        ChildCmdLine       = ProcessCommandLine,
        AccountName        = InitiatingProcessAccountName,
        AccountDomain      = InitiatingProcessAccountDomain,
        HostName           = DeviceName,
        EventTime          = Timestamp,
        NetworkActivity    = ProcessCommandLine has_any (NetworkIndicators),
        CredentialActivity = ProcessCommandLine has_any (CredentialIndicators)
    | project EventTime, HostName, AccountName, AccountDomain, ChildProcess,
        ChildCmdLine, NetworkActivity, CredentialActivity;
  let SecEvent_Results =
    SecurityEvent
    | where TimeGenerated >= ago(Lookback)
    | where EventID == 4688
    | where ParentProcessName endswith "\\WmiPrvSE.exe"
    | extend ChildProcess = tostring(split(NewProcessName, "\\")[-1])
    | where ChildProcess in~ (SuspiciousChildProcesses)
    | where not(CommandLine has_any (AllowlistedCmdPatterns))
    | extend
        ChildCmdLine       = CommandLine,
        AccountName        = SubjectUserName,
        AccountDomain      = SubjectDomainName,
        HostName           = Computer,
        EventTime          = TimeGenerated,
        NetworkActivity    = CommandLine has_any (NetworkIndicators),
        CredentialActivity = CommandLine has_any (CredentialIndicators)
    | project EventTime, HostName, AccountName, AccountDomain, ChildProcess,
        ChildCmdLine, NetworkActivity, CredentialActivity;
  union MDE_Results, SecEvent_Results
  | extend RiskScore = iif(CredentialActivity == true, 3, iif(NetworkActivity == true, 2, 1))
  | sort by RiskScore desc, EventTime desc
entityMappings:
  - entityType: Host
    fieldMappings:
      - identifier: FullName
        columnName: HostName
  - entityType: Account
    fieldMappings:
      - identifier: Name
        columnName: AccountName
      - identifier: NTDomain
        columnName: AccountDomain
  - entityType: Process
    fieldMappings:
      - identifier: CommandLine
        columnName: ChildCmdLine
version: 1.0.5
kind: Scheduled

Stages and Predicates

Stage 0: let

let Lookback = 1h;
let SuspiciousChildProcesses = dynamic([
  "powershell.exe", "pwsh.exe", "cmd.exe", "cscript.exe", "wscript.exe",
  "mshta.exe", "certutil.exe", "bitsadmin.exe", "regsvr32.exe",
  "rundll32.exe", "msiexec.exe", "installutil.exe", "cmstp.exe",
  "msbuild.exe", "wmic.exe", "net.exe", "net1.exe", "nltest.exe",
  "whoami.exe", "ipconfig.exe", "tasklist.exe", "schtasks.exe",
  "at.exe", "sc.exe", "reg.exe"
]);
let AllowlistedCmdPatterns = dynamic([
  "ccmexec", "SMSAgent", "MOMAgent", "nessus", "qualys"
]);
let NetworkIndicators = dynamic([
  "http://", "https://", "ftp://", "Net.WebClient",
  "DownloadString", "IEX", "Invoke-Expression", "/transfer", "-urlcache"
]);
let CredentialIndicators = dynamic([
  "lsass", "mimikatz", "sekurlsa", "dump", "sam", "ntds"
]);
let MDE_Results = DeviceProcessEvents <inlined as stages below>;
let SecEvent_Results = SecurityEvent <inlined as stages below>;

Stage 1: source

let MDE_Results

Stage 2: source

let SecEvent_Results

Stage 3: union

union of 2 branches

Stage 4: source

DeviceProcessEvents

Stage 5: where

where Timestamp >= ago(3600s)

Stage 6: where

where InitiatingProcessFileName =~ "WmiPrvSE.exe"

Stage 7: where

where FileName in~ ("at.exe", "bitsadmin.exe", "certutil.exe", "cmd.exe", "cmstp.exe", "cscript.exe", "installutil.exe", "ipconfig.exe", "msbuild.exe", "mshta.exe", "msiexec.exe", "net.exe", "net1.exe", "nltest.exe", "powershell.exe", "pwsh.exe", "reg.exe", "regsvr32.exe", "rundll32.exe", "sc.exe", "schtasks.exe", "tasklist.exe", "whoami.exe", "wmic.exe", "wscript.exe")

Stage 8: where

where not ((ProcessCommandLine contains "ccmexec" or ProcessCommandLine contains "SMSAgent" or ProcessCommandLine contains "MOMAgent" or ProcessCommandLine contains "nessus" or ProcessCommandLine contains "qualys"))

Stage 9: extend

extend AccountDomain, AccountName, ChildCmdLine, ChildProcess, CredentialActivity, EventTime, HostName, NetworkActivity

Stage 10: project

project AccountDomain, AccountName, ChildCmdLine, ChildProcess, CredentialActivity, EventTime, HostName, NetworkActivity

Stage 11: source

SecurityEvent

Stage 12: where

where TimeGenerated >= ago(3600s)

Stage 13: where

where EventID == 4688

Stage 14: where

where ParentProcessName endswith @"\WmiPrvSE.exe"

Stage 15: extend

extend ChildProcess

Stage 16: where

where ChildProcess in~ ("at.exe", "bitsadmin.exe", "certutil.exe", "cmd.exe", "cmstp.exe", "cscript.exe", "installutil.exe", "ipconfig.exe", "msbuild.exe", "mshta.exe", "msiexec.exe", "net.exe", "net1.exe", "nltest.exe", "powershell.exe", "pwsh.exe", "reg.exe", "regsvr32.exe", "rundll32.exe", "sc.exe", "schtasks.exe", "tasklist.exe", "whoami.exe", "wmic.exe", "wscript.exe")

Stage 17: where

where not ((CommandLine contains "ccmexec" or CommandLine contains "SMSAgent" or CommandLine contains "MOMAgent" or CommandLine contains "nessus" or CommandLine contains "qualys"))

Stage 18: extend

extend AccountDomain, AccountName, ChildCmdLine, CredentialActivity, EventTime, HostName, NetworkActivity

Stage 19: project

project AccountDomain, AccountName, ChildCmdLine, ChildProcess, CredentialActivity, EventTime, HostName, NetworkActivity

Stage 20: extend

extend RiskScore

Stage 21: sort

sort by EventTime, RiskScore

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
ChildProcessin
  • at.exe
  • bitsadmin.exe
  • certutil.exe
  • cmd.exe
  • cmstp.exe
  • cscript.exe
  • installutil.exe
  • ipconfig.exe
  • msbuild.exe
  • mshta.exe
  • msiexec.exe
  • net.exe
  • net1.exe
  • nltest.exe
  • powershell.exe
  • pwsh.exe
  • reg.exe
  • regsvr32.exe
  • rundll32.exe
  • sc.exe
  • schtasks.exe
  • tasklist.exe
  • whoami.exe
  • wmic.exe
  • wscript.exe
field:"ChildProcess" kind:in
EventIDeq
  • 4688 corpus 317 (splunk 283, kusto 33, elastic 1)
field:"EventID" kind:eq value:"4688"
FileNamein
  • at.exe
  • bitsadmin.exe
  • certutil.exe corpus 2 (kusto 2)
  • cmd.exe
  • cmstp.exe
  • cscript.exe
  • installutil.exe
  • ipconfig.exe
  • msbuild.exe
  • mshta.exe
  • msiexec.exe
  • net.exe
  • net1.exe
  • nltest.exe
  • powershell.exe corpus 3 (kusto 3)
  • pwsh.exe
  • reg.exe
  • regsvr32.exe
  • rundll32.exe
  • sc.exe
  • schtasks.exe
  • tasklist.exe
  • whoami.exe
  • wmic.exe
  • wscript.exe
field:"file_name" kind:in
InitiatingProcessFileNameeq
  • WmiPrvSE.exe corpus 25 (elastic 19, splunk 5, kusto 1)
field:"parent_process_name" kind:eq value:"WmiPrvSE.exe"
ParentProcessNameends_with
  • \WmiPrvSE.exe corpus 3 (sigma 2, kusto 1)
field:"parent_process_name" kind:ends_with value:"\WmiPrvSE.exe"

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
ProcessCommandLinematchccmexec, SMSAgent, MOMAgent, nessus, qualysexcludes:ProcessCommandLine
CommandLinematchccmexec, SMSAgent, MOMAgent, nessus, qualysexcludes:CommandLine

Output fields

These fields are emitted when the rule matches.

FieldSource
AccountDomainproject
AccountNameproject
ChildCmdLineproject
ChildProcessproject
CredentialActivityproject
EventTimeproject
HostNameproject
NetworkActivityproject
RiskScoreextend