Detection rules › Kusto

Zero Networks Segment - Rare JIT Rule Creation

Status
available
Severity
medium
Time window
14d
Group by
DestinationEntityName, PerformedByName
Source
github.com/Azure/Azure-Sentinel

'Identifies when a JIT Rule connection is new or rare by a given account today based on comparison with the previous 14 days. JIT Rule creations are indicated by the Activity Type Id 20'

MITRE ATT&CK coverage

TacticTechniques
Lateral MovementT1021 Remote Services

Rule body kusto

id: 58688058-68b2-4b39-8009-ac6dc4d81ea1
name: Zero Networks Segment - Rare JIT Rule Creation
description: |
  'Identifies when a JIT Rule connection is new or rare by a given account today based on comparison with the previous 14 days.
  JIT Rule creations are indicated by the Activity Type Id 20'
severity: Medium
status: Available
requiredDataConnectors:
  - connectorId: ZeroNetworksSegmentAuditFunction
    dataTypes:
      - ZNSegmentAudit_CL
  - connectorId: ZeroNetworksSegmentAuditNativePoller
    dataTypes:
      - ZNSegmentAuditNativePoller_CL
queryFrequency: 1d
queryPeriod: 14d
triggerOperator: gt
triggerThreshold: 0
tactics:
  - LateralMovement
relevantTechniques:
  - T1021
query: |
  let starttime = 14d;
  let endtime = 1d;
  ZNSegmentAudit
  | where TimeGenerated >= ago(endtime)
  | where AuditTypeId == 20
  | summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated), ConnectionCount = count()
  by PerformedByName, tostring(DestinationEntityName)
    // use left anti to exclude anything from the previous 14 days that is not rare
  | join kind=leftanti (
  ZNSegmentAudit
  | where TimeGenerated between (ago(starttime) .. ago(endtime))
  | where AuditTypeId == 20
  | summarize by tostring(DestinationEntityName)
  ) on DestinationEntityName
  | summarize StartTime = min(StartTime), EndTime = max(EndTime), ConnectionCount = sum(ConnectionCount)
  by PerformedByName, DestinationEntityName
  | extend TimeGenerated = StartTime
entityMappings:
  - entityType: Account
    fieldMappings:
      - identifier: Name
        columnName: PerformedByName
  - entityType: Host
    fieldMappings:
      - identifier: HostName
        columnName: DestinationEntityName
version: 1.0.2
kind: Scheduled

Stages and Predicates

Parameters

let starttime = 14d;
let endtime = 1d;

Stage 1: source

ZNSegmentAudit

Stage 2: where

| where TimeGenerated >= ago(endtime)

Stage 3: where

| where AuditTypeId == 20

Stage 4: summarize

| summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated), ConnectionCount = count()
by PerformedByName, tostring(DestinationEntityName)

Stage 5: join (negated)

| join kind=leftanti (
ZNSegmentAudit
| where TimeGenerated between (ago(starttime) .. ago(endtime))
| where AuditTypeId == 20
| summarize by tostring(DestinationEntityName)
) on DestinationEntityName

Stage 6: summarize

| summarize StartTime = min(StartTime), EndTime = max(EndTime), ConnectionCount = sum(ConnectionCount)
by PerformedByName, DestinationEntityName

Stage 7: extend

| extend TimeGenerated = StartTime

Exclusions

Top-level NOT(...) conjuncts: predicates this rule actively suppresses.

FieldKindExcluded values
AuditTypeIdeq20

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
AuditTypeIdeq
  • 20 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
ConnectionCountsummarize
DestinationEntityNamesummarize
EndTimesummarize
PerformedByNamesummarize
StartTimesummarize
TimeGeneratedextend