Analytic rule catalog
Whisper Security - BGP Route Anomaly with Traffic Spike
Back
| Id | 1c08a7cb-7ff4-5a37-a961-39c29f8d07bd |
| Rulename | Whisper Security - BGP Route Anomaly with Traffic Spike |
| Description | Detects BGP origin AS changes for IP prefixes correlated with network traffic volume spikes. May indicate BGP hijacking or adversary-in-the-middle attacks. |
| Severity | High |
| Tactics | Collection |
| Techniques | T1557 |
| Required data connectors | WhisperSecurityConnector |
| Kind | Scheduled |
| Query frequency | 15m |
| Query period | 1d |
| Trigger threshold | 0 |
| Trigger operator | gt |
| Source Uri | https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Whisper/Analytic%20Rules/BgpRouteAnomalyTrafficSpike.yaml |
| Version | 1.0.0 |
| Arm template | 1c08a7cb-7ff4-5a37-a961-39c29f8d07bd.json |
// MITRE ATT&CK: T1557 - Adversary-in-the-Middle
// Tactic: Collection
// Detects BGP route origin changes correlated with traffic volume anomalies
let lookbackPeriod = 1d;
let bgpChanges = WhisperHistory_CL
| where TimeGenerated > ago(lookbackPeriod)
| where isnotempty(bgpOrigin)
| serialize
| extend PreviousOrigin = prev(bgpOrigin), PreviousIndicator = prev(indicator)
| where indicator == PreviousIndicator
| where bgpOrigin != PreviousOrigin
| where isnotempty(PreviousOrigin)
| project indicator, bgpPrefix, OldOrigin = PreviousOrigin, NewOrigin = bgpOrigin, ChangeTime = snapshotDate;
let CommonSecurityLogSafe = union isfuzzy=true CommonSecurityLog, (datatable(TimeGenerated:datetime, DestinationIP:string, SentBytes:long, ReceivedBytes:long)[]);
let trafficBaseline = CommonSecurityLogSafe
| where TimeGenerated > ago(lookbackPeriod)
| where isnotempty(DestinationIP)
| summarize BaselineBytes = avg(SentBytes + ReceivedBytes), BaselineCount = count() by DestinationIP, bin(TimeGenerated, 1h)
| summarize AvgBaselineBytes = avg(BaselineBytes), AvgBaselineCount = avg(BaselineCount) by DestinationIP;
let recentTraffic = CommonSecurityLogSafe
| where TimeGenerated > ago(15m)
| where isnotempty(DestinationIP)
| summarize RecentBytes = sum(SentBytes + ReceivedBytes), RecentCount = count() by DestinationIP;
recentTraffic
| join kind=inner (trafficBaseline) on DestinationIP
| where RecentBytes > AvgBaselineBytes * 3 or RecentCount > AvgBaselineCount * 3
| extend TrafficChange = iff(AvgBaselineBytes > 0, round((RecentBytes - AvgBaselineBytes) / AvgBaselineBytes * 100, 2), 0.0)
| join kind=inner (bgpChanges) on $left.DestinationIP == $right.indicator
| project TimeGenerated = ChangeTime, IPAddress = DestinationIP, Prefix = bgpPrefix, OriginASN = NewOrigin, OldOriginASN = OldOrigin, TrafficChange, RecentBytes, AvgBaselineBytes
incidentConfiguration:
groupingConfiguration:
lookbackDuration: PT5H
reopenClosedIncident: false
matchingMethod: AllEntities
enabled: true
createIncident: true
name: Whisper Security - BGP Route Anomaly with Traffic Spike
triggerOperator: gt
query: |
// MITRE ATT&CK: T1557 - Adversary-in-the-Middle
// Tactic: Collection
// Detects BGP route origin changes correlated with traffic volume anomalies
let lookbackPeriod = 1d;
let bgpChanges = WhisperHistory_CL
| where TimeGenerated > ago(lookbackPeriod)
| where isnotempty(bgpOrigin)
| serialize
| extend PreviousOrigin = prev(bgpOrigin), PreviousIndicator = prev(indicator)
| where indicator == PreviousIndicator
| where bgpOrigin != PreviousOrigin
| where isnotempty(PreviousOrigin)
| project indicator, bgpPrefix, OldOrigin = PreviousOrigin, NewOrigin = bgpOrigin, ChangeTime = snapshotDate;
let CommonSecurityLogSafe = union isfuzzy=true CommonSecurityLog, (datatable(TimeGenerated:datetime, DestinationIP:string, SentBytes:long, ReceivedBytes:long)[]);
let trafficBaseline = CommonSecurityLogSafe
| where TimeGenerated > ago(lookbackPeriod)
| where isnotempty(DestinationIP)
| summarize BaselineBytes = avg(SentBytes + ReceivedBytes), BaselineCount = count() by DestinationIP, bin(TimeGenerated, 1h)
| summarize AvgBaselineBytes = avg(BaselineBytes), AvgBaselineCount = avg(BaselineCount) by DestinationIP;
let recentTraffic = CommonSecurityLogSafe
| where TimeGenerated > ago(15m)
| where isnotempty(DestinationIP)
| summarize RecentBytes = sum(SentBytes + ReceivedBytes), RecentCount = count() by DestinationIP;
recentTraffic
| join kind=inner (trafficBaseline) on DestinationIP
| where RecentBytes > AvgBaselineBytes * 3 or RecentCount > AvgBaselineCount * 3
| extend TrafficChange = iff(AvgBaselineBytes > 0, round((RecentBytes - AvgBaselineBytes) / AvgBaselineBytes * 100, 2), 0.0)
| join kind=inner (bgpChanges) on $left.DestinationIP == $right.indicator
| project TimeGenerated = ChangeTime, IPAddress = DestinationIP, Prefix = bgpPrefix, OriginASN = NewOrigin, OldOriginASN = OldOrigin, TrafficChange, RecentBytes, AvgBaselineBytes
queryFrequency: 15m
description: |
Detects BGP origin AS changes for IP prefixes correlated with network traffic volume spikes. May indicate BGP hijacking or adversary-in-the-middle attacks.
id: 1c08a7cb-7ff4-5a37-a961-39c29f8d07bd
triggerThreshold: 0
queryPeriod: 1d
version: 1.0.0
kind: Scheduled
customDetails:
TrafficChange: TrafficChange
OriginASN: OriginASN
Prefix: Prefix
status: Available
severity: High
requiredDataConnectors:
- connectorId: WhisperSecurityConnector
dataTypes:
- WhisperHistory_CL
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Whisper/Analytic%20Rules/BgpRouteAnomalyTrafficSpike.yaml
relevantTechniques:
- T1557
tactics:
- Collection
entityMappings:
- fieldMappings:
- identifier: Address
columnName: IPAddress
entityType: IP
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"workspace": {
"type": "String"
}
},
"resources": [
{
"apiVersion": "2024-01-01-preview",
"id": "[concat(resourceId('Microsoft.OperationalInsights/workspaces/providers', parameters('workspace'), 'Microsoft.SecurityInsights'),'/alertRules/1c08a7cb-7ff4-5a37-a961-39c29f8d07bd')]",
"kind": "Scheduled",
"name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/1c08a7cb-7ff4-5a37-a961-39c29f8d07bd')]",
"properties": {
"alertRuleTemplateName": "1c08a7cb-7ff4-5a37-a961-39c29f8d07bd",
"customDetails": {
"OriginASN": "OriginASN",
"Prefix": "Prefix",
"TrafficChange": "TrafficChange"
},
"description": "Detects BGP origin AS changes for IP prefixes correlated with network traffic volume spikes. May indicate BGP hijacking or adversary-in-the-middle attacks.\n",
"displayName": "Whisper Security - BGP Route Anomaly with Traffic Spike",
"enabled": true,
"entityMappings": [
{
"entityType": "IP",
"fieldMappings": [
{
"columnName": "IPAddress",
"identifier": "Address"
}
]
}
],
"incidentConfiguration": {
"createIncident": true,
"groupingConfiguration": {
"enabled": true,
"lookbackDuration": "PT5H",
"matchingMethod": "AllEntities",
"reopenClosedIncident": false
}
},
"OriginalUri": "https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Whisper/Analytic%20Rules/BgpRouteAnomalyTrafficSpike.yaml",
"query": "// MITRE ATT&CK: T1557 - Adversary-in-the-Middle\n// Tactic: Collection\n// Detects BGP route origin changes correlated with traffic volume anomalies\nlet lookbackPeriod = 1d;\nlet bgpChanges = WhisperHistory_CL\n | where TimeGenerated > ago(lookbackPeriod)\n | where isnotempty(bgpOrigin)\n | serialize\n | extend PreviousOrigin = prev(bgpOrigin), PreviousIndicator = prev(indicator)\n | where indicator == PreviousIndicator\n | where bgpOrigin != PreviousOrigin\n | where isnotempty(PreviousOrigin)\n | project indicator, bgpPrefix, OldOrigin = PreviousOrigin, NewOrigin = bgpOrigin, ChangeTime = snapshotDate;\nlet CommonSecurityLogSafe = union isfuzzy=true CommonSecurityLog, (datatable(TimeGenerated:datetime, DestinationIP:string, SentBytes:long, ReceivedBytes:long)[]);\nlet trafficBaseline = CommonSecurityLogSafe\n | where TimeGenerated > ago(lookbackPeriod)\n | where isnotempty(DestinationIP)\n | summarize BaselineBytes = avg(SentBytes + ReceivedBytes), BaselineCount = count() by DestinationIP, bin(TimeGenerated, 1h)\n | summarize AvgBaselineBytes = avg(BaselineBytes), AvgBaselineCount = avg(BaselineCount) by DestinationIP;\nlet recentTraffic = CommonSecurityLogSafe\n | where TimeGenerated > ago(15m)\n | where isnotempty(DestinationIP)\n | summarize RecentBytes = sum(SentBytes + ReceivedBytes), RecentCount = count() by DestinationIP;\nrecentTraffic\n | join kind=inner (trafficBaseline) on DestinationIP\n | where RecentBytes > AvgBaselineBytes * 3 or RecentCount > AvgBaselineCount * 3\n | extend TrafficChange = iff(AvgBaselineBytes > 0, round((RecentBytes - AvgBaselineBytes) / AvgBaselineBytes * 100, 2), 0.0)\n | join kind=inner (bgpChanges) on $left.DestinationIP == $right.indicator\n | project TimeGenerated = ChangeTime, IPAddress = DestinationIP, Prefix = bgpPrefix, OriginASN = NewOrigin, OldOriginASN = OldOrigin, TrafficChange, RecentBytes, AvgBaselineBytes\n",
"queryFrequency": "PT15M",
"queryPeriod": "P1D",
"severity": "High",
"status": "Available",
"subTechniques": [],
"suppressionDuration": "PT1H",
"suppressionEnabled": false,
"tactics": [
"Collection"
],
"techniques": [
"T1557"
],
"templateVersion": "1.0.0",
"triggerOperator": "GreaterThan",
"triggerThreshold": 0
},
"type": "Microsoft.OperationalInsights/workspaces/providers/alertRules"
}
]
}