Back
Ide3f4a5b6-3c4d-5e6f-7a8b-9c0d1e2f3a4b
RulenameTailscale Premium: Network flow beaconing detected
DescriptionIdentifies when flows between a src-dst pair recur at a regular interval (80%+ of inter-flow gaps cluster on the same delta over 10+ flows). Signature of C2 beaconing or scheduled exfiltration. Requires Tailscale Premium or Enterprise.
SeverityMedium
TacticsCommandAndControl
Exfiltration
TechniquesT1071
T1095
T1029
Required data connectorsTailscalePremiumCCF
KindScheduled
Query frequency1h
Query period2d
Trigger threshold0
Trigger operatorgt
Source Urihttps://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Tailscale%20%28CCF%29/Analytic%20Rules/TailscalePremiumBeaconingDetected.yaml
Version1.0.0
Arm templatee3f4a5b6-3c4d-5e6f-7a8b-9c0d1e2f3a4b.json
Deploy To Azure
let lookback = 2d;
let minFlows = 10;
let beaconPercentThreshold = 80.0;
Tailscale_Network_CL
| where TimeGenerated > ago(lookback)
| where HasVirtualTraffic
| mv-expand t = VirtualTraffic
| extend Src = tostring(t.src), Dst = tostring(t.dst), Proto = toint(t.proto)
| project TimeGenerated, Src, Dst, Proto, SrcNodeName, SrcUser, DstNodeName, DstUser
| sort by Src asc, Dst asc, Proto asc, TimeGenerated asc
| serialize
| extend NextTime = next(TimeGenerated), NextSrc = next(Src), NextDst = next(Dst), NextProto = next(Proto)
| where Src == NextSrc and Dst == NextDst and Proto == NextProto
| extend DeltaSec = datetime_diff('second', NextTime, TimeGenerated)
| where DeltaSec > 5
| summarize DeltaCount = count() by Src, Dst, Proto, DeltaSec, SrcNodeName, SrcUser, DstNodeName, DstUser
| summarize (MostFrequentDeltaCount, MostFrequentDeltaSec) = arg_max(DeltaCount, DeltaSec), TotalFlows = sum(DeltaCount) by Src, Dst, Proto, SrcNodeName, SrcUser, DstNodeName, DstUser
| where TotalFlows >= minFlows
| extend BeaconPercent = round(MostFrequentDeltaCount * 100.0 / TotalFlows, 1)
| where BeaconPercent >= beaconPercentThreshold
incidentConfiguration:
  groupingConfiguration:
    lookbackDuration: P1D
    reopenClosedIncident: false
    matchingMethod: AllEntities
    enabled: true
  createIncident: true
name: 'Tailscale Premium: Network flow beaconing detected'
triggerOperator: gt
query: |
  let lookback = 2d;
  let minFlows = 10;
  let beaconPercentThreshold = 80.0;
  Tailscale_Network_CL
  | where TimeGenerated > ago(lookback)
  | where HasVirtualTraffic
  | mv-expand t = VirtualTraffic
  | extend Src = tostring(t.src), Dst = tostring(t.dst), Proto = toint(t.proto)
  | project TimeGenerated, Src, Dst, Proto, SrcNodeName, SrcUser, DstNodeName, DstUser
  | sort by Src asc, Dst asc, Proto asc, TimeGenerated asc
  | serialize
  | extend NextTime = next(TimeGenerated), NextSrc = next(Src), NextDst = next(Dst), NextProto = next(Proto)
  | where Src == NextSrc and Dst == NextDst and Proto == NextProto
  | extend DeltaSec = datetime_diff('second', NextTime, TimeGenerated)
  | where DeltaSec > 5
  | summarize DeltaCount = count() by Src, Dst, Proto, DeltaSec, SrcNodeName, SrcUser, DstNodeName, DstUser
  | summarize (MostFrequentDeltaCount, MostFrequentDeltaSec) = arg_max(DeltaCount, DeltaSec), TotalFlows = sum(DeltaCount) by Src, Dst, Proto, SrcNodeName, SrcUser, DstNodeName, DstUser
  | where TotalFlows >= minFlows
  | extend BeaconPercent = round(MostFrequentDeltaCount * 100.0 / TotalFlows, 1)
  | where BeaconPercent >= beaconPercentThreshold
queryFrequency: 1h
description: |
  Identifies when flows between a src-dst pair recur at a regular interval (80%+ of inter-flow gaps cluster on the same delta over 10+ flows). Signature of C2 beaconing or scheduled exfiltration. Requires Tailscale Premium or Enterprise.
id: e3f4a5b6-3c4d-5e6f-7a8b-9c0d1e2f3a4b
triggerThreshold: 0
queryPeriod: 2d
version: 1.0.0
kind: Scheduled
status: Available
severity: Medium
requiredDataConnectors:
- connectorId: TailscalePremiumCCF
  dataTypes:
  - Tailscale_Network_CL
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Tailscale%20%28CCF%29/Analytic%20Rules/TailscalePremiumBeaconingDetected.yaml
relevantTechniques:
- T1071
- T1095
- T1029
tactics:
- CommandAndControl
- Exfiltration
entityMappings:
- fieldMappings:
  - identifier: HostName
    columnName: SrcNodeName
  entityType: Host
- fieldMappings:
  - identifier: HostName
    columnName: DstNodeName
  entityType: Host
- fieldMappings:
  - identifier: FullName
    columnName: SrcUser
  entityType: Account
- fieldMappings:
  - identifier: Address
    columnName: Src
  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/e3f4a5b6-3c4d-5e6f-7a8b-9c0d1e2f3a4b')]",
      "kind": "Scheduled",
      "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/e3f4a5b6-3c4d-5e6f-7a8b-9c0d1e2f3a4b')]",
      "properties": {
        "alertRuleTemplateName": "e3f4a5b6-3c4d-5e6f-7a8b-9c0d1e2f3a4b",
        "customDetails": null,
        "description": "Identifies when flows between a src-dst pair recur at a regular interval (80%+ of inter-flow gaps cluster on the same delta over 10+ flows). Signature of C2 beaconing or scheduled exfiltration. Requires Tailscale Premium or Enterprise.\n",
        "displayName": "Tailscale Premium: Network flow beaconing detected",
        "enabled": true,
        "entityMappings": [
          {
            "entityType": "Host",
            "fieldMappings": [
              {
                "columnName": "SrcNodeName",
                "identifier": "HostName"
              }
            ]
          },
          {
            "entityType": "Host",
            "fieldMappings": [
              {
                "columnName": "DstNodeName",
                "identifier": "HostName"
              }
            ]
          },
          {
            "entityType": "Account",
            "fieldMappings": [
              {
                "columnName": "SrcUser",
                "identifier": "FullName"
              }
            ]
          },
          {
            "entityType": "IP",
            "fieldMappings": [
              {
                "columnName": "Src",
                "identifier": "Address"
              }
            ]
          }
        ],
        "incidentConfiguration": {
          "createIncident": true,
          "groupingConfiguration": {
            "enabled": true,
            "lookbackDuration": "P1D",
            "matchingMethod": "AllEntities",
            "reopenClosedIncident": false
          }
        },
        "OriginalUri": "https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Tailscale%20%28CCF%29/Analytic%20Rules/TailscalePremiumBeaconingDetected.yaml",
        "query": "let lookback = 2d;\nlet minFlows = 10;\nlet beaconPercentThreshold = 80.0;\nTailscale_Network_CL\n| where TimeGenerated > ago(lookback)\n| where HasVirtualTraffic\n| mv-expand t = VirtualTraffic\n| extend Src = tostring(t.src), Dst = tostring(t.dst), Proto = toint(t.proto)\n| project TimeGenerated, Src, Dst, Proto, SrcNodeName, SrcUser, DstNodeName, DstUser\n| sort by Src asc, Dst asc, Proto asc, TimeGenerated asc\n| serialize\n| extend NextTime = next(TimeGenerated), NextSrc = next(Src), NextDst = next(Dst), NextProto = next(Proto)\n| where Src == NextSrc and Dst == NextDst and Proto == NextProto\n| extend DeltaSec = datetime_diff('second', NextTime, TimeGenerated)\n| where DeltaSec > 5\n| summarize DeltaCount = count() by Src, Dst, Proto, DeltaSec, SrcNodeName, SrcUser, DstNodeName, DstUser\n| summarize (MostFrequentDeltaCount, MostFrequentDeltaSec) = arg_max(DeltaCount, DeltaSec), TotalFlows = sum(DeltaCount) by Src, Dst, Proto, SrcNodeName, SrcUser, DstNodeName, DstUser\n| where TotalFlows >= minFlows\n| extend BeaconPercent = round(MostFrequentDeltaCount * 100.0 / TotalFlows, 1)\n| where BeaconPercent >= beaconPercentThreshold\n",
        "queryFrequency": "PT1H",
        "queryPeriod": "P2D",
        "severity": "Medium",
        "status": "Available",
        "subTechniques": [],
        "suppressionDuration": "PT1H",
        "suppressionEnabled": false,
        "tactics": [
          "CommandAndControl",
          "Exfiltration"
        ],
        "techniques": [
          "T1029",
          "T1071",
          "T1095"
        ],
        "templateVersion": "1.0.0",
        "triggerOperator": "GreaterThan",
        "triggerThreshold": 0
      },
      "type": "Microsoft.OperationalInsights/workspaces/providers/alertRules"
    }
  ]
}