Detection rules › Kusto

UniFi Site Manager: IPS/IDS disabled or misconfigured

Status
available
Severity
high
Time window
45m
Group by
siteId_s
Source
github.com/Azure/Azure-Sentinel

Identifies when a UniFi gateway threat-protection state transitions away from the expected IPS-active mode, which may indicate admin action or attacker tampering.

MITRE ATT&CK coverage

TacticTechniques
Defense Impairment

Rule body

id: 36a64027-729e-51d7-16bf-8e926c03712a
name: "UniFi Site Manager: IPS/IDS disabled or misconfigured"
description: |
  Identifies when a UniFi gateway threat-protection state transitions away from the expected IPS-active mode, which may indicate admin action or attacker tampering.
severity: High
status: Available
requiredDataConnectors:
  - connectorId: UniFiSiteManagerConnectorDefinition
    dataTypes:
      - Unifi_SiteManager_Sites_CL
queryFrequency: 15m
queryPeriod: 45m
triggerOperator: gt
triggerThreshold: 0
tactics:
  - DefenseEvasion
relevantTechniques:
  - T1562
subTechniques:
  - T1562.001
query: |
  let prev = Unifi_SiteManager_Sites_CL
      | where TimeGenerated between (ago(30m) .. ago(15m))
      | summarize arg_max(TimeGenerated, *) by tostring(SiteId)
      | project siteId_s = tostring(SiteId), prevIpsMode = IpsMode, prevInspection = InspectionState;
  Unifi_SiteManager_Sites_CL
  | where TimeGenerated > ago(15m)
  | summarize arg_max(TimeGenerated, *) by tostring(SiteId)
  | extend siteId_s = tostring(SiteId)
  | join kind=inner prev on siteId_s
  | where (IpsMode != 'ips' and prevIpsMode == 'ips')
       or (InspectionState != 'on' and prevInspection == 'on')
  | extend Activity = strcat('Threat protection degraded - IpsMode: ', prevIpsMode, ' -> ', IpsMode, ', inspection: ', prevInspection, ' -> ', InspectionState)
  | project TimeGenerated, SiteId, SiteName, Activity, prevIpsMode, IpsMode, prevInspection, InspectionState
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

Let binding: prev used in Stage 5

let prev = Unifi_SiteManager_Sites_CL
    | where TimeGenerated between (ago(30m) .. ago(15m))
    | summarize arg_max(TimeGenerated, *) by tostring(SiteId)
    | project siteId_s = tostring(SiteId), prevIpsMode = IpsMode, prevInspection = InspectionState;

Stage 1: source

Unifi_SiteManager_Sites_CL

Stage 2: where

| where TimeGenerated > ago(15m)

Stage 3: summarize

| summarize arg_max(TimeGenerated, *) by tostring(SiteId)

Stage 4: extend

| extend siteId_s = tostring(SiteId)

Stage 5: join

| join kind=inner prev on siteId_s

Stage 6: where

| where (IpsMode != 'ips' and prevIpsMode == 'ips')
     or (InspectionState != 'on' and prevInspection == 'on')

Stage 7: extend

| extend Activity = strcat('Threat protection degraded - IpsMode: ', prevIpsMode, ' -> ', IpsMode, ', inspection: ', prevInspection, ' -> ', InspectionState)

Stage 8: project

| project TimeGenerated, SiteId, SiteName, Activity, prevIpsMode, IpsMode, prevInspection, InspectionState

Indicators

These rows show field, operator, and value matches.

Output fields

These fields are emitted when the rule matches.

FieldSource
Activityproject
InspectionStateproject
IpsModeproject
SiteIdproject
SiteNameproject
TimeGeneratedproject
prevInspectionproject
prevIpsModeproject