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
queryFrequency: 1h
entityMappings:
- fieldMappings:
  - columnName: SrcNodeName
    identifier: HostName
  entityType: Host
- fieldMappings:
  - columnName: DstNodeName
    identifier: HostName
  entityType: Host
- fieldMappings:
  - columnName: SrcUser
    identifier: FullName
  entityType: Account
- fieldMappings:
  - columnName: Src
    identifier: Address
  entityType: IP
incidentConfiguration:
  createIncident: true
  groupingConfiguration:
    lookbackDuration: P1D
    matchingMethod: AllEntities
    enabled: true
    reopenClosedIncident: false
triggerThreshold: 0
triggerOperator: gt
severity: Medium
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Tailscale%20%28CCF%29/Analytic%20Rules/TailscalePremiumBeaconingDetected.yaml
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
tactics:
- CommandAndControl
- Exfiltration
queryPeriod: 2d
relevantTechniques:
- T1071
- T1095
- T1029
requiredDataConnectors:
- connectorId: TailscalePremiumCCF
  dataTypes:
  - Tailscale_Network_CL
id: e3f4a5b6-3c4d-5e6f-7a8b-9c0d1e2f3a4b
kind: Scheduled
version: 1.0.0
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.
status: Available
name: 'Tailscale Premium: Network flow beaconing detected'
{
  "$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"
    }
  ]
}