Detection rules › Kusto
Zscaler - Unexpected update operation
'Detects unexpected version of update operation.'
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Initial Access | T1133 External Remote Services, T1190 Exploit Public-Facing Application |
Rule body kusto
id: 672e2846-4226-11ec-81d3-0242ac130003
name: Zscaler - Unexpected update operation
description: |
'Detects unexpected version of update operation.'
severity: Medium
status: Available
requiredDataConnectors:
- connectorId: CustomLogsAma
datatypes:
- ZPA_CL
queryFrequency: 1h
queryPeriod: 1h
triggerOperator: gt
triggerThreshold: 0
tactics:
- InitialAccess
relevantTechniques:
- T1190
- T1133
query: |
ZPAEvent
| where isnotempty(AuditOperationType)
| extend ExpectedVersion1 = extract(@'(expectedVersion":")([0-9]+)\.([0-9]+\.[0-9]+)', 2, AuditOldValue)
| extend ExpectedVersion2 = extract(@'(expectedVersion":")([0-9]+)\.([0-9]+\.[0-9]+)', 3, AuditOldValue)
| extend NewVersion1 = extract(@'("currentVersion":")([0-9]+)\.([0-9]+\.[0-9]+)', 2, AuditNewValue)
| extend NewVersion2 = extract(@'("currentVersion":")([0-9]+)\.([0-9]+\.[0-9]+)', 3, AuditNewValue)
| extend Comparision1 = iff(tolong(ExpectedVersion2) > tolong(NewVersion2), 'Unexpected version', 'Expected version')
| extend VersionCheck = iff(tolong(ExpectedVersion1) > tolong(NewVersion1), 'Unexpected version', Comparision1)
| project-away ExpectedVersion1, ExpectedVersion2, NewVersion1, NewVersion2, Comparision1
| extend ProcessCustomEntity = AuditOperationType
entityMappings:
- entityType: Process
fieldMappings:
- identifier: ProcessId
columnName: ProcessCustomEntity
version: 1.0.2
kind: Scheduled
Stages and Predicates
Stage 1: source
ZPAEvent
Stage 2: where
| where isnotempty(AuditOperationType)
Stage 3: extend (6 consecutive steps)
| extend ExpectedVersion1 = extract(@'(expectedVersion":")([0-9]+)\.([0-9]+\.[0-9]+)', 2, AuditOldValue)
| extend ExpectedVersion2 = extract(@'(expectedVersion":")([0-9]+)\.([0-9]+\.[0-9]+)', 3, AuditOldValue)
| extend NewVersion1 = extract(@'("currentVersion":")([0-9]+)\.([0-9]+\.[0-9]+)', 2, AuditNewValue)
| extend NewVersion2 = extract(@'("currentVersion":")([0-9]+)\.([0-9]+\.[0-9]+)', 3, AuditNewValue)
| extend Comparision1 = iff(tolong(ExpectedVersion2) > tolong(NewVersion2), 'Unexpected version', 'Expected version')
| extend VersionCheck = iff(tolong(ExpectedVersion1) > tolong(NewVersion1), 'Unexpected version', Comparision1)
Stage 4: project-away
| project-away ExpectedVersion1, ExpectedVersion2, NewVersion1, NewVersion2, Comparision1
Stage 5: extend
| extend ProcessCustomEntity = AuditOperationType
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 |
|---|---|---|
AuditOperationType | is_not_null |
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 |
|---|---|
VersionCheck | extend |
ProcessCustomEntity | extend |