Detection rules › Kusto

Vectra AI Detect - Detections with High Severity

Status
available
Severity
high
Time window
5m
Group by
Activity, source_entity
Source
github.com/Azure/Azure-Sentinel

'Create an incident for high severity malicious behavior detected by Vectra AI (Threat score superior to 7.0). The Severity is a mapping with the Threat score assigned to a detection. It ranges between 0 and 10. The severity_threshold variable can be adjusted as desired.'

MITRE ATT&CK coverage

Rule body kusto

id: 39e48890-2c02-487e-aa9e-3ba494061798
name: Vectra AI Detect - Detections with High Severity 
description: |
  'Create an incident for high severity malicious behavior detected by Vectra AI (Threat score superior to 7.0). 
  The Severity is a mapping with the Threat score assigned to a detection. It ranges between 0 and 10. 
  The severity_threshold variable can be adjusted as desired.' 
severity: High
status: Available
requiredDataConnectors:
  - connectorId: CefAma
    dataTypes:
      - CommonSecurityLog
queryFrequency: 5m
queryPeriod: 5m
triggerOperator: gt
triggerThreshold: 0
eventGroupingSettings:
  aggregationKind: AlertPerResult
tactics:
  - CredentialAccess
  - Discovery
  - LateralMovement
  - Collection
  - CommandAndControl
  - Exfiltration
  - Impact
relevantTechniques:
  - T1003
  - T1087
  - T1021
  - T1119
  - T1071
  - T1041
  - T1499
query: |
  // Edit this variable to only keep the tactics where an incident needs to be created (Defaults are: "COMMAND & CONTROL", "BOTNET ACTIVITY", "EXFILTRATION", "LATERAL MOVEMENT", "RECONNAISSANCE")   
  let configured_tactics = dynamic(["COMMAND & CONTROL", "BOTNET ACTIVITY", "EXFILTRATION", "LATERAL MOVEMENT", "RECONNAISSANCE"]);
  //default threshold is 7 (meaning a threat score of 70)
  let severity_threshold = 7.0;
  //Map by default to High Severity in Sentinel
  let Severity = "High";
  CommonSecurityLog
  | where DeviceVendor == "Vectra Networks"
  | where DeviceProduct == "X Series"
  | where DeviceEventClassID != "campaigns" and DeviceEventClassID != "hsc" and DeviceEventClassID != "audit" and DeviceEventClassID != "health" and DeviceEventClassID != "asc"
  | extend Category = coalesce(
                            column_ifexists("DeviceEventCategory", ""), 
                            extract("cat=(.+?)(;|$)", 1, AdditionalExtensions), 
                            ""
                        )
  | project-rename threat_score = FlexNumber1
  | project-rename certainty_score = FlexNumber2
  | project-rename vectra_URL = DeviceCustomString4
  | project-rename detection_name = DeviceEventClassID
  | where todecimal(LogSeverity) >= severity_threshold
  | extend Tactic = case( Category == "COMMAND & CONTROL", "CommandAndControl",
                          Category == "BOTNET ACTIVITY" , "Impact",
                          Category == "EXFILTRATION", "Exfiltration",
                          Category == "LATERAL MOVEMENT", "LateralMovement",
                          Category == "RECONNAISSANCE", "Discovery",
                          "UNKNOWN")
  | extend level = case(threat_score == 0 and certainty_score == 0, "Info",
      threat_score < 50 and certainty_score < 50, "Low",
      threat_score < 50 and certainty_score >= 50, "Medium", 
      threat_score >= 50 and certainty_score <= 50, "High", 
      threat_score >= 50 and certainty_score >= 50, "Critical",
      "UNKNOWN")
  | extend Severity = case(level == "Info", "Informational",level == "Critical", "High", level)
  | extend account = extract("account=(.+?);", 1, AdditionalExtensions)
  | extend upn = iff(account matches regex ":", tostring(split(account,":")[1]) ,tostring(split(account,":")[0]))
  | extend name = tostring(split(upn, "@")[0])
  | extend upn_suffix = tostring(split(upn, "@")[1])
  | extend source_entity = case( isnotempty(upn), upn,
                                 isnotempty(SourceHostName), SourceHostName,
                                 "UNKNWON") 
  | where Category in (configured_tactics) 
  | summarize arg_max(threat_score, *) by source_entity, Activity
  | sort by TimeGenerated
entityMappings:
  - entityType: Host
    fieldMappings:
      - identifier: HostName
        columnName: SourceHostName
  - entityType: Account
    fieldMappings:
      - identifier: Name
        columnName: name
      - identifier: UPNSuffix
        columnName: upn_suffix
alertDetailsOverride:
  alertDisplayNameFormat: Vectra AI Detect - {{Activity}} detected
  alertDescriptionFormat: Source entity is {{source_entity}} and category is {{Category}}. Threat score is {{threat_score}}.
  alertSeverityColumnName: Severity
  alertDynamicProperties:
    - alertProperty: AlertLink
      value: vectra_URL
    - alertProperty: ProductName
      value: DeviceProduct
    - alertProperty: ProviderName
      value: DeviceVendor
    - alertProperty: ConfidenceScore
      value: certainty_score
incidentConfiguration:
  createIncident: true
  groupingConfiguration:
    enabled: true
    reopenClosedIncident: true
    lookbackDuration: 7d
    matchingMethod: AllEntities
customDetails:
  AttackType: Activity
  AttackCategory: Category  
version: 1.1.0
kind: Scheduled

Stages and Predicates

Parameters

let configured_tactics = dynamic(["COMMAND & CONTROL", "BOTNET ACTIVITY", "EXFILTRATION", "LATERAL MOVEMENT", "RECONNAISSANCE"]);
let severity_threshold = 7.0;
let Severity = "High";

Stage 1: source

CommonSecurityLog

Stage 2: where

| where DeviceVendor == "Vectra Networks"

Stage 3: where

| where DeviceProduct == "X Series"

Stage 4: where

| where DeviceEventClassID != "campaigns" and DeviceEventClassID != "hsc" and DeviceEventClassID != "audit" and DeviceEventClassID != "health" and DeviceEventClassID != "asc"

Stage 5: extend

| extend Category = coalesce(
                          column_ifexists("DeviceEventCategory", ""), 
                          extract("cat=(.+?)(;|$)", 1, AdditionalExtensions), 
                          ""
                      )

Stage 6: project-rename

| project-rename threat_score = FlexNumber1

Stage 7: project-rename

| project-rename certainty_score = FlexNumber2

Stage 8: project-rename

| project-rename vectra_URL = DeviceCustomString4

Stage 9: project-rename

| project-rename detection_name = DeviceEventClassID

Stage 10: where

| where todecimal(LogSeverity) >= severity_threshold

Stage 11: extend (8 consecutive steps)

| extend Tactic = case( Category == "COMMAND & CONTROL", "CommandAndControl",
                        Category == "BOTNET ACTIVITY" , "Impact",
                        Category == "EXFILTRATION", "Exfiltration",
                        Category == "LATERAL MOVEMENT", "LateralMovement",
                        Category == "RECONNAISSANCE", "Discovery",
                        "UNKNOWN")
| extend level = case(threat_score == 0 and certainty_score == 0, "Info",
    threat_score < 50 and certainty_score < 50, "Low",
    threat_score < 50 and certainty_score >= 50, "Medium", 
    threat_score >= 50 and certainty_score <= 50, "High", 
    threat_score >= 50 and certainty_score >= 50, "Critical",
    "UNKNOWN")
| extend Severity = case(level == "Info", "Informational",level == "Critical", "High", level)
| extend account = extract("account=(.+?);", 1, AdditionalExtensions)
| extend upn = iff(account matches regex ":", tostring(split(account,":")[1]) ,tostring(split(account,":")[0]))
| extend name = tostring(split(upn, "@")[0])
| extend upn_suffix = tostring(split(upn, "@")[1])
| extend source_entity = case( isnotempty(upn), upn,
                               isnotempty(SourceHostName), SourceHostName,
                               "UNKNWON")
Tactic =
ifCategory == "COMMAND & CONTROL""CommandAndControl"
elifCategory == "BOTNET ACTIVITY""Impact"
elifCategory == "EXFILTRATION""Exfiltration"
elifCategory == "LATERAL MOVEMENT""LateralMovement"
elifCategory == "RECONNAISSANCE""Discovery"
else"UNKNOWN"

Stage 12: where

| where Category in (configured_tactics)

Stage 13: summarize

| summarize arg_max(threat_score, *) by source_entity, Activity

Stage 14: sort

| sort by TimeGenerated

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
Categoryin
  • BOTNET ACTIVITY transforms: cased
  • COMMAND & CONTROL transforms: cased
  • EXFILTRATION transforms: cased
  • LATERAL MOVEMENT transforms: cased
  • RECONNAISSANCE transforms: cased
DeviceEventClassIDne
  • asc transforms: cased
  • audit transforms: cased
  • campaigns transforms: cased
  • health transforms: cased
  • hsc transforms: cased
DeviceProducteq
  • X Series transforms: cased
DeviceVendoreq
  • Vectra Networks 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
Activitysummarize
source_entitysummarize