Detection rules › Kusto

Potential Ransomware activity related to Cobalt Strike

Status
available
Severity
high
Time window
1d
Group by
AlertId, AlertTime, DeviceId, Title
Source
github.com/Azure/Azure-Sentinel

This query searches for alerts related to suspected ransomware and Cobalt Strike activity, a tool used in numerous ransomware campaigns. It looks for alerts that indicate potential ransomware activity, such as attempts to clear security event logs, delete backup files, and execute Cobalt Strike malware.

MITRE ATT&CK coverage

Rule body kusto

id: 4bd9ce9d-8586-4beb-8fdb-bd018cacbe7d
name: Potential Ransomware activity related to Cobalt Strike
description: |
  This query searches for alerts related to suspected ransomware and Cobalt Strike activity, a tool used in numerous ransomware campaigns. It looks for alerts that indicate potential ransomware activity, such as attempts to clear security event logs, delete backup files, and execute Cobalt Strike malware.
severity: High
status: Available
requiredDataConnectors:
  - connectorId: MicrosoftThreatProtection
    dataTypes:
      - AlertInfo
      - AlertEvidence
      - DeviceLogonEvents
queryFrequency: 1d
queryPeriod: 1d
triggerOperator: gt
triggerThreshold: 0
tactics:
  - Execution
  - Persistence
  - DefenseEvasion
  - Impact
relevantTechniques:
  - T1059
  - T1078
  - T1070
  - T1490
query: |
  // Look for sc.exe disabling services
  AlertInfo 
  // Attempts to clear security event logs. 
  | where Title in("Event log was cleared", 
  // List alerts flagging attempts to delete backup files. 
  "File backups were deleted", 
  // Potential Cobalt Strike activity - Note that other threat activity can also 
  // trigger alerts for suspicious decoded content 
  "Suspicious decoded content", 
  // Cobalt Strike activity 
  "\'Atosev\' malware was detected", 
  "\'Ploty\' malware was detected", 
  "\'Bynoco\' malware was detected",
  "\'Cobaltstrike\' malware was detected",
  "Echo command over pipe on localhost",
  "Known attack framework activity was observed",
  "An active \'Cobaltstrike\' malware was detected",
  "Suspicious \'CobaltStrike\' behavior was prevented",
  "Suspicious process launch by Rundll32.exe") 
  | extend AlertTime = TimeGenerated | distinct AlertTime, AlertId, Title 
  | join AlertEvidence on $left.AlertId == $right.AlertId
  | summarize by DeviceId, AlertTime, Title, AlertId
  // Get device IDs
  | join DeviceLogonEvents on $left.DeviceId == $right.DeviceId 
  // Creating 10 day Window surrounding alert activity 
  | where TimeGenerated < AlertTime + 12h and TimeGenerated > AlertTime - 12h // Projecting specific columns 
  | project Title, DeviceName, DeviceId, TimeGenerated, LogonType, AccountDomain, AccountName, AccountSid, AlertTime, AlertId, RemoteIP, RemoteDeviceName
  | extend AccountFullName = tostring(strcat(AccountDomain, "\\", AccountName))
  | 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
  - entityType: Account
    fieldMappings:
      - identifier: FullName
        columnName: AccountFullName
      - identifier: Name
        columnName: AccountName
      - identifier: DnsDomain
        columnName: AccountDomain
  - entityType: IP
    fieldMappings:
      - identifier: Address
        columnName: RemoteIP
version: 1.0.1
kind: Scheduled

Stages and Predicates

Stage 1: source

AlertInfo

Stage 2: where

| where Title in("Event log was cleared", 
"File backups were deleted", 
"Suspicious decoded content", 
"\'Atosev\' malware was detected", 
"\'Ploty\' malware was detected", 
"\'Bynoco\' malware was detected",
"\'Cobaltstrike\' malware was detected",
"Echo command over pipe on localhost",
"Known attack framework activity was observed",
"An active \'Cobaltstrike\' malware was detected",
"Suspicious \'CobaltStrike\' behavior was prevented",
"Suspicious process launch by Rundll32.exe")

Stage 3: extend

| extend AlertTime = TimeGenerated

Stage 4: distinct

| distinct AlertTime, AlertId, Title

Stage 5: join

| join AlertEvidence on $left.AlertId == $right.AlertId

Stage 6: summarize

| summarize by DeviceId, AlertTime, Title, AlertId

Stage 7: join

| join DeviceLogonEvents on $left.DeviceId == $right.DeviceId

Stage 8: where where TimeGenerated - AlertTime < 12h

| where TimeGenerated < AlertTime + 12h and TimeGenerated > AlertTime - 12h

Stage 9: project

| project Title, DeviceName, DeviceId, TimeGenerated, LogonType, AccountDomain, AccountName, AccountSid, AlertTime, AlertId, RemoteIP, RemoteDeviceName

Stage 10: extend (3 consecutive steps)

| extend AccountFullName = tostring(strcat(AccountDomain, "\\", AccountName))
| extend HostName = iff(DeviceName has '.', substring(DeviceName, 0, indexof(DeviceName, '.')), DeviceName)
| extend DnsDomain = iff(DeviceName has '.', substring(DeviceName, indexof(DeviceName, '.') + 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
Titlein
  • An active \'Cobaltstrike\' malware was detected transforms: cased
  • Echo command over pipe on localhost transforms: cased
  • Event log was cleared transforms: cased
  • File backups were deleted transforms: cased
  • Known attack framework activity was observed transforms: cased
  • Suspicious \'CobaltStrike\' behavior was prevented transforms: cased
  • Suspicious decoded content transforms: cased
  • Suspicious process launch by Rundll32.exe transforms: cased
  • \'Atosev\' malware was detected transforms: cased
  • \'Bynoco\' malware was detected transforms: cased
  • \'Cobaltstrike\' malware was detected transforms: cased
  • \'Ploty\' malware was detected transforms: cased

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
AccountDomainproject
AccountNameproject
AccountSidproject
AlertIdproject
AlertTimeproject
DeviceIdproject
DeviceNameproject
LogonTypeproject
RemoteDeviceNameproject
RemoteIPproject
TimeGeneratedproject
Titleproject
AccountFullNameextend
HostNameextend
DnsDomainextend