Detection rules › Kusto
Valimail Enforce - Unusual Rate of Configuration Changes or User Additions
This query searches for a single user performing more than 3 configuration changes or user additions within a 1-hour window on any domain. An unusual burst of changes may indicate a compromised admin account, unauthorized automation, or insider threat.
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Privilege Escalation | T1078 Valid Accounts |
| Stealth | T1078 Valid Accounts, T1562 Impair Defenses |
| Impact | T1531 Account Access Removal |
Rule body kusto
id: 3cbb78d9-81ac-42c9-b3cd-7e6baea7d9ff
name: Valimail Enforce - Unusual Rate of Configuration Changes or User Additions
description: |
This query searches for a single user performing more than 3 configuration changes or user
additions within a 1-hour window on any domain. An unusual burst of changes may
indicate a compromised admin account, unauthorized automation, or insider threat.
severity: Medium
status: Available
requiredDataConnectors:
- connectorId: ValimailEnforce
dataTypes:
- ValimailEnforceEvents_CL
queryFrequency: 1h
queryPeriod: 1h
triggerOperator: gt
triggerThreshold: 0
tactics:
- Impact
- DefenseEvasion
- PrivilegeEscalation
relevantTechniques:
- T1562
- T1531
- T1078
query: |
let threshold = 3;
let timeWindow = 1h;
ValimailEnforceEvents_CL
| where EventCategory in (
"DMARCPolicy",
"SPFConfiguration",
"DKIMConfiguration",
"DomainManagement",
"UserManagement"
)
| summarize
ChangeCount = count(),
HighValueCount = countif(IsHighValueEvent == true),
Domains = make_set(Subject),
DomainCount = dcount(Subject),
Actions = make_set(EventType),
Categories = make_set(EventCategory),
FirstSeen = min(PerformedAt),
LastSeen = max(PerformedAt)
by User, bin(PerformedAt, timeWindow)
| where ChangeCount > threshold
| extend
AccountName = tostring(split(User, "@")[0]),
AccountDomain = tostring(split(User, "@")[1]),
DomainName = tostring(Domains[0]),
ChangesPerMin = round(todouble(ChangeCount) / 60.0, 2)
entityMappings:
- entityType: Account
fieldMappings:
- identifier: Name
columnName: AccountName
- identifier: UPNSuffix
columnName: AccountDomain
- entityType: DNS
fieldMappings:
- identifier: DomainName
columnName: DomainName
alertDetailsOverride:
alertDisplayNameFormat: "Unusual change rate by {{User}}, {{ChangeCount}} changes in 1h across {{DomainCount}} domain(s)"
alertDescriptionFormat: |
User '{{User}}' made {{ChangeCount}} configuration changes across {{DomainCount}} domain(s) within one hour.
incidentConfiguration:
createIncident: true
groupingConfiguration:
enabled: true
reopenClosedIncident: false
lookbackDuration: 1d
matchingMethod: Selected
groupByEntities:
- Account
version: 1.0.0
kind: Scheduled
Stages and Predicates
Parameters
let threshold = 3;
let timeWindow = 1h;
Stage 1: source
ValimailEnforceEvents_CL
Stage 2: where
| where EventCategory in (
"DMARCPolicy",
"SPFConfiguration",
"DKIMConfiguration",
"DomainManagement",
"UserManagement"
)
Stage 3: summarize
| summarize
ChangeCount = count(),
HighValueCount = countif(IsHighValueEvent == true),
Domains = make_set(Subject),
DomainCount = dcount(Subject),
Actions = make_set(EventType),
Categories = make_set(EventCategory),
FirstSeen = min(PerformedAt),
LastSeen = max(PerformedAt)
by User, bin(PerformedAt, timeWindow)
Stage 4: where
| where ChangeCount > threshold
Stage 5: extend
| extend
AccountName = tostring(split(User, "@")[0]),
AccountDomain = tostring(split(User, "@")[1]),
DomainName = tostring(Domains[0]),
ChangesPerMin = round(todouble(ChangeCount) / 60.0, 2)
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.
| Field | Kind | Values |
|---|---|---|
ChangeCount | gt |
|
EventCategory | in |
|
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.
| Field | Source |
|---|---|
Actions | summarize |
Categories | summarize |
ChangeCount | summarize |
DomainCount | summarize |
Domains | summarize |
FirstSeen | summarize |
HighValueCount | summarize |
LastSeen | summarize |
User | summarize |
AccountDomain | extend |
AccountName | extend |
ChangesPerMin | extend |
DomainName | extend |