Detection rules › Kusto

Malware in the recycle bin

Status
available
Severity
medium
Time window
1d
Source
github.com/Azure/Azure-Sentinel

The query detects Windows binaries that can be used for executing malware and have been hidden in the recycle bin. The list of these binaries is sourced from https://lolbas-project.github.io/ References: https://azure.microsoft.com/blog/how-azure-security-center-helps-reveal-a-cyberattack/.

MITRE ATT&CK coverage

TacticTechniques
Stealth

Telemetry coverage

Rule body

id: 75bf9902-0789-47c1-a5d8-f57046aa72df
name: Malware in the recycle bin
description: |
  'The query detects Windows binaries that can be used for executing malware and have been hidden in the recycle bin.
  The list of these binaries is sourced from https://lolbas-project.github.io/
  References: https://azure.microsoft.com/blog/how-azure-security-center-helps-reveal-a-cyberattack/.'
severity: Medium
status: Available
requiredDataConnectors:
  - connectorId: SecurityEvents
    dataTypes:
      - SecurityEvent
  - connectorId: WindowsSecurityEvents
    dataTypes:
      - SecurityEvent
  - connectorId: WindowsSecurityEvents
    dataTypes: 
      - SecurityEvents 
  - connectorId: WindowsForwardedEvents
    dataTypes: 
      - WindowsEvent 
queryFrequency: 1d
queryPeriod: 1d
triggerOperator: gt
triggerThreshold: 0
tactics:
  - DefenseEvasion
relevantTechniques:
  - T1564
query: |
  let procList = externaldata(Process:string) [@"https://raw.githubusercontent.com/Azure/Azure-Sentinel/master/Sample%20Data/Microsoft_Lolbas_Execution_Binaries.csv"] with (format="csv", ignoreFirstRecord=True);
  let recycle_bin_paths = dynamic([@":\RECYCLER", @":\$RECYCLE.BIN"]);
  let ProcessCreationEvents=(union isfuzzy=true
  (SecurityEvent
  | where EventID==4688
  | where isnotempty(CommandLine)
  | project TimeGenerated, Computer, Account = SubjectUserName, AccountDomain = SubjectDomainName, NewProcessName,
  FileName = Process, CommandLine,  ParentProcessName
  ),
  (WindowsEvent
  | where EventID==4688 and EventData has_any (procList) and EventData has_any (recycle_bin_paths)
  | extend CommandLine = tostring(EventData.CommandLine)
  | where isnotempty(CommandLine)
  | extend SubjectUserName = tostring(EventData.SubjectUserName)
  | extend SubjectDomainName = tostring(EventData.SubjectDomainName) 
  | extend NewProcessName = tostring(EventData.NewProcessName)  
  | extend ParentProcessName = tostring(EventData.ParentProcessName)
  | extend Process=tostring(split(NewProcessName, '\\')[-1])
  | project TimeGenerated, Computer, Account = SubjectUserName, AccountDomain = SubjectDomainName, NewProcessName,
  FileName = Process, CommandLine,  ParentProcessName
  ));
  ProcessCreationEvents 
  | where FileName in~ (procList)
  | where CommandLine has_any (recycle_bin_paths)
  | project StartTimeUtc = TimeGenerated, Computer, Account, NewProcessName, FileName, CommandLine, ParentProcessName
  | 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: Account
  - entityType: Host
    fieldMappings:
      - identifier: FullName
        columnName: Computer
      - identifier: HostName
        columnName: HostName
      - identifier: DnsDomain
        columnName: DnsDomain
version: 1.1.5
kind: Scheduled

Stages and Predicates

Parameters

let recycle_bin_paths = dynamic([@":\RECYCLER", @":\$RECYCLE.BIN"]);

Let binding: procList

let procList = externaldata(Process:string) [@"https://raw.githubusercontent.com/Azure/Azure-Sentinel/master/Sample%20Data/Microsoft_Lolbas_Execution_Binaries.csv"] with (format="csv", ignoreFirstRecord=True);

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==4688
| where isnotempty(CommandLine)
| project TimeGenerated, Computer, Account = SubjectUserName, AccountDomain = SubjectDomainName, NewProcessName,
FileName = Process, CommandLine,  ParentProcessName

Leg 2: WindowsEvent

WindowsEvent
| where EventID==4688 and EventData has_any (procList) and EventData has_any (recycle_bin_paths)
| extend CommandLine = tostring(EventData.CommandLine)
| where isnotempty(CommandLine)
| extend SubjectUserName = tostring(EventData.SubjectUserName)
| extend SubjectDomainName = tostring(EventData.SubjectDomainName) 
| extend NewProcessName = tostring(EventData.NewProcessName)  
| extend ParentProcessName = tostring(EventData.ParentProcessName)
| extend Process=tostring(split(NewProcessName, '\\')[-1])
| project TimeGenerated, Computer, Account = SubjectUserName, AccountDomain = SubjectDomainName, NewProcessName,
FileName = Process, CommandLine,  ParentProcessName

Applied to the combined result

| where FileName in~ (procList) | where CommandLine has_any (recycle_bin_paths) | project StartTimeUtc = TimeGenerated, Computer, Account, NewProcessName, FileName, CommandLine, ParentProcessName | extend HostName = iif(Computer has '.',substring(Computer,0,indexof(Computer,'.')),Computer) , DnsDomain = iif(Computer has '.',substring(Computer,indexof(Computer,'.')+1),'')

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
CommandLineis_not_null
  • (no value, null check)
field:"CommandLine" kind:is_not_null
CommandLinematch
  • :\$RECYCLE.BIN transforms: term corpus 2 (sigma 1, kusto 1)
  • :\RECYCLER transforms: term
field:"CommandLine" kind:match
EventDatamatch
  • :\$RECYCLE.BIN transforms: term
  • :\RECYCLER transforms: term
  • procList transforms: term
field:"EventData" kind:match
EventIDeq
  • 4688 corpus 317 (splunk 283, kusto 33, elastic 1)
field:"EventID" kind:eq value:"4688"
FileNamein
  • procList
field:"file_name" kind:in value:"procList"

Output fields

These fields are emitted when the rule matches.

FieldSource
Accountproject
CommandLineproject
Computerproject
FileNameproject
NewProcessNameproject
ParentProcessNameproject
StartTimeUtcproject
DnsDomainextend
HostNameextend