Detection rules › Kusto
UniFi Site Manager: New WAN2 (secondary) issue recorded
Identifies a new issue index on the secondary WAN failover link. Fires only on newly-recorded issue indexes, not while existing issues persist.
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Impact |
Rule body
id: b16f13ae-343b-9513-e684-469cdf9471b2
name: "UniFi Site Manager: New WAN2 (secondary) issue recorded"
description: |
Identifies a new issue index on the secondary WAN failover link. Fires only on newly-recorded issue indexes, not while existing issues persist.
severity: Medium
status: Available
requiredDataConnectors:
- connectorId: UniFiSiteManagerConnectorDefinition
dataTypes:
- Unifi_SiteManager_Sites_CL
queryFrequency: 15m
queryPeriod: 45m
triggerOperator: gt
triggerThreshold: 0
tactics:
- Impact
relevantTechniques:
- T1498
subTechniques:
- T1498.001
query: |
// UniFi reports a monotonically-rising wanIssues.count rather than discrete events.
// Detect a NEW occurrence by checking whether the per-site max(count) has grown
// in the most recent 15-min window vs the prior 15-min window.
Unifi_SiteManager_Sites_CL
| where TimeGenerated > ago(45m)
| extend siteId_s = tostring(SiteId)
| where isnotempty(tostring(SiteStatistics.wans.WAN2))
| mv-expand issue = todynamic(tostring(SiteStatistics.wans.WAN2.wanIssues))
| extend issueCount = tolong(issue.count), idx = tolong(issue.index)
| summarize
PrevMaxCount = maxif(issueCount, TimeGenerated < ago(15m)),
CurrentMaxCount = maxif(issueCount, TimeGenerated >= ago(15m)),
LatestIndex = maxif(idx, TimeGenerated >= ago(15m))
by siteId_s, SiteName
| extend PrevMaxCount = coalesce(PrevMaxCount, tolong(0))
| where CurrentMaxCount > PrevMaxCount
| extend
TimeGenerated = now(),
Delta = CurrentMaxCount - PrevMaxCount,
Activity = strcat('New WAN2 issue: count rose from ', PrevMaxCount, ' to ', CurrentMaxCount)
| project TimeGenerated, SiteId = siteId_s, SiteName, Activity, IssueIndex = LatestIndex, PrevMaxCount, CurrentMaxCount, Delta
entityMappings:
- entityType: Host
fieldMappings:
- identifier: HostName
columnName: SiteId
- identifier: DnsDomain
columnName: SiteName
incidentConfiguration:
createIncident: true
groupingConfiguration:
enabled: true
reopenClosedIncident: false
lookbackDuration: PT5H
matchingMethod: AllEntities
kind: Scheduled
version: 1.0.1
Stages and Predicates
Stage 1: source
Unifi_SiteManager_Sites_CL
Stage 2: where
| where TimeGenerated > ago(45m)
Stage 3: extend
| extend siteId_s = tostring(SiteId)
Stage 4: where
| where isnotempty(tostring(SiteStatistics.wans.WAN2))
Stage 5: mv-expand
| mv-expand issue = todynamic(tostring(SiteStatistics.wans.WAN2.wanIssues))
Stage 6: extend
| extend issueCount = tolong(issue.count), idx = tolong(issue.index)
Stage 7: summarize
| summarize
PrevMaxCount = maxif(issueCount, TimeGenerated < ago(15m)),
CurrentMaxCount = maxif(issueCount, TimeGenerated >= ago(15m)),
LatestIndex = maxif(idx, TimeGenerated >= ago(15m))
by siteId_s, SiteName
Stage 8: extend
| extend PrevMaxCount = coalesce(PrevMaxCount, tolong(0))
Stage 9: where
| where CurrentMaxCount > PrevMaxCount
Stage 10: extend
| extend
TimeGenerated = now(),
Delta = CurrentMaxCount - PrevMaxCount,
Activity = strcat('New WAN2 issue: count rose from ', PrevMaxCount, ' to ', CurrentMaxCount)
Stage 11: project
| project TimeGenerated, SiteId = siteId_s, SiteName, Activity, IssueIndex = LatestIndex, PrevMaxCount, CurrentMaxCount, Delta
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
CurrentMaxCount | cross_field_compare |
| field:"CurrentMaxCount" kind:cross_field_compare value:"PrevMaxCount" |
Output fields
These fields are emitted when the rule matches.
| Field | Source |
|---|---|
Activity | project |
CurrentMaxCount | project |
Delta | project |
IssueIndex | project |
PrevMaxCount | project |
SiteId | project |
SiteName | project |
TimeGenerated | project |