Detection rules › Kusto

Whisper Security - Co-Hosted Malware Cluster Detection

Status
available
Severity
high
Time window
1d
Group by
cohostedCount, countries, indicator, parsedIp, registrar
Source
github.com/Azure/Azure-Sentinel

Identifies IP addresses that host multiple domains associated with malware. When an IP has more than 3 co-hosted domains and at least 3 of those domains are flagged as malware by Whisper threat intelligence, it strongly indicates compromised or adversary-controlled infrastructure.

MITRE ATT&CK coverage

TacticTechniques
Resource Development

Rule body

id: 374a77f4-23ed-55dc-8441-8e47a1e079e9
name: Whisper Security - Co-Hosted Malware Cluster Detection
description: |
  Identifies IP addresses that host multiple domains associated with malware. When an IP has more than 3 co-hosted domains and at least 3 of those domains are flagged as malware by Whisper threat intelligence, it strongly indicates compromised or adversary-controlled infrastructure.
severity: High
status: Available
requiredDataConnectors:
- connectorId: WhisperSecurityConnector
  dataTypes:
  - WhisperInfraContext_CL
  - WhisperThreatIntel_CL
queryFrequency: 1h
queryPeriod: 1d
triggerOperator: gt
triggerThreshold: 0
tactics:
- ResourceDevelopment
relevantTechniques:
- T1584
query: |
  // MITRE ATT&CK: T1584.001 - Compromise Infrastructure: Domains
  // Tactic: Resource Development
  // Detects clusters of malware-hosting domains sharing the same IP infrastructure
  let minCohostedCount = 3;
  let minMalwareCoHosts = 3;
  let cohostedInfra = WhisperInfraContext_CL
      | where TimeGenerated > ago(1d)
      | where cohostedCount > minCohostedCount
      | extend parsedIp = tostring(split(ipAddresses, ",")[0])
      | project indicator, parsedIp, cohostedCount, countries, registrar;
  let malwareIndicators = WhisperThreatIntel_CL
      | where TimeGenerated > ago(1d)
      | where isMalware == true
      | project indicator, threatScore, threatLevel, feedNames;
  cohostedInfra
      | join kind=inner (malwareIndicators) on indicator
      | summarize malwareCoHostCount = dcount(indicator), DnsDomains = make_set(indicator, 10), avgThreatScore = avg(threatScore), maxThreatScore = max(threatScore) by parsedIp, cohostedCount, countries, registrar
      | where malwareCoHostCount >= minMalwareCoHosts
      | extend DnsDomain = tostring(DnsDomains[0]), IPAddress = parsedIp
      | project TimeGenerated = now(), DnsDomain, IPAddress, malwareCoHostCount, cohostedCount, avgThreatScore, maxThreatScore, countries, registrar, DnsDomains
entityMappings:
- entityType: DNS
  fieldMappings:
  - identifier: DomainName
    columnName: DnsDomain
- entityType: IP
  fieldMappings:
  - identifier: Address
    columnName: IPAddress
customDetails:
  MalwareCoHostCount: malwareCoHostCount
  CoHostedCount: cohostedCount
  MaxThreatScore: maxThreatScore
incidentConfiguration:
  createIncident: true
  groupingConfiguration:
    enabled: true
    reopenClosedIncident: false
    lookbackDuration: PT5H
    matchingMethod: AllEntities
version: 1.0.0
kind: Scheduled

Stages and Predicates

Stage 0: let

let minCohostedCount = 3;
let minMalwareCoHosts = 3;
let cohostedInfra = WhisperInfraContext_CL <inlined as stages below>;
let malwareIndicators = WhisperThreatIntel_CL
    | where TimeGenerated > ago(1d)
    | where isMalware == true
    | project indicator, threatScore, threatLevel, feedNames;

Stage 1: source

WhisperInfraContext_CL

Stage 2: where

| where TimeGenerated > ago(1d)

Stage 3: where

| where cohostedCount > minCohostedCount

Stage 4: extend

| extend parsedIp = tostring(split(ipAddresses, ",")[0])

Stage 5: project

| project indicator, parsedIp, cohostedCount, countries, registrar

Stage 6: join

| join kind=inner (malwareIndicators) on indicator

Stage 7: summarize

summarize DnsDomains, avgThreatScore, malwareCoHostCount, maxThreatScore by parsedIp, cohostedCount, countries, registrar

Stage 8: where

where malwareCoHostCount >= 3

Stage 9: extend

extend DnsDomain, IPAddress

Stage 10: project

project DnsDomain, DnsDomains, IPAddress, TimeGenerated, avgThreatScore, cohostedCount, countries, malwareCoHostCount, maxThreatScore, registrar

Indicators

These rows show field, operator, and value matches.

Output fields

These fields are emitted when the rule matches.

FieldSource
DnsDomainproject
DnsDomainsproject
IPAddressproject
TimeGeneratedproject
avgThreatScoreproject
cohostedCountproject
countriesproject
malwareCoHostCountproject
maxThreatScoreproject
registrarproject