Detection rules › Kusto

Network endpoint to host executable correlation

Status
available
Severity
medium
Time window
1d
Group by
shortFileName, suspectExeName
Source
github.com/Azure/Azure-Sentinel

'Correlates blocked URLs hosting [malicious] executables with host endpoint data to identify potential instances of executables of the same name having been recently run.

MITRE ATT&CK coverage

TacticTechniques
Execution

Telemetry coverage

Rule body

id: 01f64465-b1ef-41ea-a7f5-31553a11ad43
name: Network endpoint to host executable correlation
description: |
  'Correlates blocked URLs hosting [malicious] executables with host endpoint data to identify potential instances of executables of the same name having been recently run.
severity: Medium
status: Available
requiredDataConnectors:
  - connectorId: TrendMicro
    dataTypes:
      - CommonSecurityLog
  - connectorId: SecurityEvents
    dataTypes:
      - SecurityEvent
  - connectorId: WindowsSecurityEvents
    dataTypes: 
      - SecurityEvents 
  - connectorId: WindowsForwardedEvents
    dataTypes: 
      - WindowsEvent 
queryFrequency: 1d
queryPeriod: 1d
triggerOperator: gt
triggerThreshold: 0
tactics:
  - Execution
relevantTechniques:
  - T1204
query: |
  let endpointData = 
  (union isfuzzy=true
  (SecurityEvent
    | where EventID == 4688
    | extend shortFileName = tolower(tostring(split(NewProcessName, '\\')[-1]))
    ),
    (WindowsEvent
    | where EventID == 4688
    | extend  NewProcessName = tostring(EventData.NewProcessName)
    | extend shortFileName = tolower(tostring(split(NewProcessName, '\\')[-1]))
    | extend TargetUserName = tostring(EventData.TargetUserName)
    ));
  // Correlate suspect executables seen in TrendMicro rule updates with similar activity on endpoints
  CommonSecurityLog
  | where DeviceVendor =~ "Trend Micro"
  | where Activity =~ "Deny List updated" 
  | where RequestURL endswith ".exe"
  | project TimeGenerated, Activity , RequestURL , SourceIP, DestinationIP
  | extend suspectExeName = tolower(tostring(split(RequestURL, '/')[-1]))
  | join kind=innerunique (endpointData) on $left.suspectExeName == $right.shortFileName 
  | extend HostName = tostring(split(Computer, '.', 0)[0]), DnsDomain = tostring(strcat_array(array_slice(split(Computer, '.'), 1, -1), '.'))
entityMappings:
  - entityType: Account
    fieldMappings:
      - identifier: Name
        columnName: TargetUserName
  - entityType: Host
    fieldMappings:
      - identifier: HostName
        columnName: HostName
      - identifier: DnsDomain
        columnName: DnsDomain
  - entityType: IP
    fieldMappings:
      - identifier: Address
        columnName: DestinationIP
  - entityType: URL
    fieldMappings:
      - identifier: Url
        columnName: RequestURL
version: 1.1.6
kind: Scheduled

Stages and Predicates

Stage 0: let

let endpointData = 
(union isfuzzy=true
(SecurityEvent
  | where EventID == 4688
  | extend shortFileName = tolower(tostring(split(NewProcessName, '\\')[-1]))
  ),
  (WindowsEvent
  | where EventID == 4688
  | extend  NewProcessName = tostring(EventData.NewProcessName)
  | extend shortFileName = tolower(tostring(split(NewProcessName, '\\')[-1]))
  | extend TargetUserName = tostring(EventData.TargetUserName)
  ));

Stage 1: source

let endpointData

Stage 2: source

CommonSecurityLog

Stage 3: where

| where DeviceVendor =~ "Trend Micro"

Stage 4: where

| where Activity =~ "Deny List updated"

Stage 5: where

| where RequestURL endswith ".exe"

Stage 6: project

| project TimeGenerated, Activity , RequestURL , SourceIP, DestinationIP

Stage 7: extend

| extend suspectExeName = tolower(tostring(split(RequestURL, '/')[-1]))

Stage 8: join

join kind=innerunique (endpointData) on suspectExeName, shortFileName

Stage 9: extend

extend DnsDomain, HostName

Indicators

These rows show field, operator, and value matches.

Output fields

These fields are emitted when the rule matches.

FieldSource
Activityproject
DestinationIPproject
RequestURLproject
SourceIPproject
TimeGeneratedproject
suspectExeNameextend
DnsDomainextend
HostNameextend