Detection rules › Kusto

UniFi Site Manager: External WAN IP changed

Status
available
Severity
high
Time window
1h
Group by
SiteId, SiteName
Source
github.com/Azure/Azure-Sentinel

Identifies when a site reports more than one distinct WAN external IP within an hour, which may indicate ISP DHCP refresh, WAN reconfiguration, or routing hijack.

MITRE ATT&CK coverage

TacticTechniques
Reconnaissance

Rule body

id: ef1a293a-9e2b-b087-7816-2610814ed2d4
name: "UniFi Site Manager: External WAN IP changed"
description: |
  Identifies when a site reports more than one distinct WAN external IP within an hour, which may indicate ISP DHCP refresh, WAN reconfiguration, or routing hijack.
severity: High
status: Available
requiredDataConnectors:
  - connectorId: UniFiSiteManagerConnectorDefinition
    dataTypes:
      - Unifi_SiteManager_Sites_CL
queryFrequency: 1h
queryPeriod: 1h
triggerOperator: gt
triggerThreshold: 0
tactics:
  - Reconnaissance
relevantTechniques:
  - T1590
subTechniques:
  - T1590.005
query: |
  Unifi_SiteManager_Sites_CL
        | where TimeGenerated > ago(1h)
        | extend SiteName = tostring(Meta.name),
                 currentIp = tostring(SiteStatistics.wans.WAN.externalIp)
        | where isnotempty(currentIp)
        | summarize DistinctIps = make_set(currentIp), arg_max(TimeGenerated, currentIp) by SiteId, SiteName
        | where array_length(DistinctIps) > 1
        | extend Activity = strcat('WAN IP changed; observed: ', tostring(DistinctIps))
        | project TimeGenerated, SiteId, SiteName, Activity, CurrentIp = currentIp, ObservedIps = DistinctIps
entityMappings:
  - entityType: IP
    fieldMappings:
      - identifier: Address
        columnName: CurrentIp
  - entityType: Host
    fieldMappings:
      - identifier: HostName
        columnName: SiteName
incidentConfiguration:
  createIncident: true
  groupingConfiguration:
    enabled: true
    reopenClosedIncident: false
    lookbackDuration: PT5H
    matchingMethod: AllEntities
kind: Scheduled
version: 1.0.0

Stages and Predicates

Stage 1: source

Unifi_SiteManager_Sites_CL

Stage 2: where

| where TimeGenerated > ago(1h)

Stage 3: extend

| extend SiteName = tostring(Meta.name),
               currentIp = tostring(SiteStatistics.wans.WAN.externalIp)

Stage 4: where

| where isnotempty(currentIp)

Stage 5: summarize

| summarize DistinctIps = make_set(currentIp), arg_max(TimeGenerated, currentIp) by SiteId, SiteName

Stage 6: where

| where array_length(DistinctIps) > 1

Stage 7: extend

| extend Activity = strcat('WAN IP changed; observed: ', tostring(DistinctIps))

Stage 8: project

| project TimeGenerated, SiteId, SiteName, Activity, CurrentIp = currentIp, ObservedIps = DistinctIps

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
currentIpis_not_null
  • (no value, null check)
field:"currentIp" kind:is_not_null

Output fields

These fields are emitted when the rule matches.

FieldSource
Activityproject
CurrentIpproject
ObservedIpsproject
SiteIdproject
SiteNameproject
TimeGeneratedproject