Microsoft Sentinel Analytic Rules
cloudbrothers.infoAzure Sentinel RepoToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeBack to homepage

Beacon Traffic Based on Common User Agents Visiting Limited Number of Domains

Back
Id6345c923-99eb-4a83-b11d-7af0ffa75577
RulenameBeacon Traffic Based on Common User Agents Visiting Limited Number of Domains
DescriptionThis query searches web proxy logs for a specific type of beaconing behavior by joining a number of sources together:

- Traffic by actual web browsers - by looking at traffic generated by a UserAgent that looks like a browser and is used by multiple users to visit a large number of domains.

- Users that make requests using one of these actual browsers, but only to a small set of domains, none of which are common domains.

- The traffic is beacon-like; meaning that it occurs during many different hours of the day (i.e. periodic).
SeverityMedium
TacticsCommandAndControl
TechniquesT1071.001
Required data connectorsZscaler
KindScheduled
Query frequency1d
Query period7d
Trigger threshold0
Trigger operatorgt
Source Urihttps://github.com/Azure/Azure-Sentinel/blob/master/Solutions/FalconFriday/Analytic Rules/RecognizingBeaconingTraffic.yaml
Version1.0.1
Arm template6345c923-99eb-4a83-b11d-7af0ffa75577.json
Deploy To Azure
let timeframe = 1d; // Timeframe during which to search for beaconing behavior.
let lookback = 7d; // Look back period to find if browser was used for other domains by user.
let min_requests=50; // Minimum number of requests to consider it beacon traffic.
let min_hours=8; // Minimum number of different hours during which connections were made to consider it beacon traffic.
let trusted_user_count=10; // If visited by this many users a domain is considered 'trusted'.
let max_sites=3; // Maximum number of different sites visited using this user-agent.
// Client-specific query to obtain 'browser-like' traffic from proxy logs.
let BrowserTraffic = (p:timespan) {
CommonSecurityLog
| where DeviceVendor == "Zscaler" and DeviceProduct == "NSSWeblog"
| where TimeGenerated >ago(p)
| project TimeGenerated, SourceUserName, DestinationHostName, RequestClientApplication
| where (RequestClientApplication startswith "Mozilla/" and RequestClientApplication contains "Gecko")
};
let CommonDomains = BrowserTraffic(timeframe)
| summarize source_count=dcount(SourceUserName) by DestinationHostName
| where source_count>trusted_user_count
| project DestinationHostName;
let CommonUA = BrowserTraffic(timeframe)
| summarize source_count=dcount(SourceUserName), host_count=dcount(DestinationHostName) by RequestClientApplication
| where source_count>trusted_user_count and host_count > 100 // Normal browsers are browsers used by many people and visiting many different sites.
| project RequestClientApplication;
// Find browsers that are common, i.e. many users use them and they use them to visit many different sites,
// but some users only use the browser to visit a very limited set of sites.
// These are considered suspicious, since they might be an attacker masquerading a beacon as a legitimate browser.
let SuspiciousBrowers = BrowserTraffic(timeframe)
| where RequestClientApplication in(CommonUA)
| summarize BrowserHosts=make_set(DestinationHostName),request_count=count() by RequestClientApplication, SourceUserName
| where array_length(BrowserHosts) <= max_sites and request_count >= min_requests
| project RequestClientApplication, SourceUserName,BrowserHosts;
// Just reporting on suspicious browsers gives too many false positives.
// For example, users that have the browser open on the login screen of 1 specific application.
// In the suspicious browsers we can search for 'beacon-like' behavior.
// Get all browser traffic by the suspicious browsers.
let PotentialAlerts=SuspiciousBrowers
| join BrowserTraffic(timeframe) on RequestClientApplication, SourceUserName
// Find beaconing-like traffic - i.e. contacting the same host in many different hours.
| summarize hour_count=dcount(bin(TimeGenerated,1h)), BrowserHosts=any(BrowserHosts), request_count=count() by RequestClientApplication, SourceUserName, DestinationHostName
| where hour_count >= min_hours and request_count >= min_requests
// Remove common domains like login.microsoft.com.
| join kind=leftanti CommonDomains on DestinationHostName
| summarize RareHosts=make_set(DestinationHostName), TotalRequestCount=sum(request_count), BrowserHosts=any(BrowserHosts) by RequestClientApplication, SourceUserName
// Remove browsers that visit any common domains.
| where array_length(RareHosts) == array_length(BrowserHosts);
// Look back for X days to see if the browser was not used to visit more hosts.
// This is to get rid of someone that started up the browser a long time ago, and left only a single tab open.
PotentialAlerts
| join BrowserTraffic(lookback) on SourceUserName, RequestClientApplication
| summarize RareHosts=any(RareHosts),BrowserHosts1d=any(BrowserHosts),BrowserHostsLookback=make_set(DestinationHostName) by SourceUserName, RequestClientApplication
| where array_length(RareHosts) == array_length(BrowserHostsLookback)
entityMappings:
- entityType: Account
  fieldMappings:
  - identifier: FullName
    columnName: SourceUserName
queryFrequency: 1d
name: Beacon Traffic Based on Common User Agents Visiting Limited Number of Domains
kind: Scheduled
tactics:
- CommandAndControl
triggerThreshold: 0
query: |
  let timeframe = 1d; // Timeframe during which to search for beaconing behavior.
  let lookback = 7d; // Look back period to find if browser was used for other domains by user.
  let min_requests=50; // Minimum number of requests to consider it beacon traffic.
  let min_hours=8; // Minimum number of different hours during which connections were made to consider it beacon traffic.
  let trusted_user_count=10; // If visited by this many users a domain is considered 'trusted'.
  let max_sites=3; // Maximum number of different sites visited using this user-agent.
  // Client-specific query to obtain 'browser-like' traffic from proxy logs.
  let BrowserTraffic = (p:timespan) {
  CommonSecurityLog
  | where DeviceVendor == "Zscaler" and DeviceProduct == "NSSWeblog"
  | where TimeGenerated >ago(p)
  | project TimeGenerated, SourceUserName, DestinationHostName, RequestClientApplication
  | where (RequestClientApplication startswith "Mozilla/" and RequestClientApplication contains "Gecko")
  };
  let CommonDomains = BrowserTraffic(timeframe)
  | summarize source_count=dcount(SourceUserName) by DestinationHostName
  | where source_count>trusted_user_count
  | project DestinationHostName;
  let CommonUA = BrowserTraffic(timeframe)
  | summarize source_count=dcount(SourceUserName), host_count=dcount(DestinationHostName) by RequestClientApplication
  | where source_count>trusted_user_count and host_count > 100 // Normal browsers are browsers used by many people and visiting many different sites.
  | project RequestClientApplication;
  // Find browsers that are common, i.e. many users use them and they use them to visit many different sites,
  // but some users only use the browser to visit a very limited set of sites.
  // These are considered suspicious, since they might be an attacker masquerading a beacon as a legitimate browser.
  let SuspiciousBrowers = BrowserTraffic(timeframe)
  | where RequestClientApplication in(CommonUA)
  | summarize BrowserHosts=make_set(DestinationHostName),request_count=count() by RequestClientApplication, SourceUserName
  | where array_length(BrowserHosts) <= max_sites and request_count >= min_requests
  | project RequestClientApplication, SourceUserName,BrowserHosts;
  // Just reporting on suspicious browsers gives too many false positives.
  // For example, users that have the browser open on the login screen of 1 specific application.
  // In the suspicious browsers we can search for 'beacon-like' behavior.
  // Get all browser traffic by the suspicious browsers.
  let PotentialAlerts=SuspiciousBrowers
  | join BrowserTraffic(timeframe) on RequestClientApplication, SourceUserName
  // Find beaconing-like traffic - i.e. contacting the same host in many different hours.
  | summarize hour_count=dcount(bin(TimeGenerated,1h)), BrowserHosts=any(BrowserHosts), request_count=count() by RequestClientApplication, SourceUserName, DestinationHostName
  | where hour_count >= min_hours and request_count >= min_requests
  // Remove common domains like login.microsoft.com.
  | join kind=leftanti CommonDomains on DestinationHostName
  | summarize RareHosts=make_set(DestinationHostName), TotalRequestCount=sum(request_count), BrowserHosts=any(BrowserHosts) by RequestClientApplication, SourceUserName
  // Remove browsers that visit any common domains.
  | where array_length(RareHosts) == array_length(BrowserHosts);
  // Look back for X days to see if the browser was not used to visit more hosts.
  // This is to get rid of someone that started up the browser a long time ago, and left only a single tab open.
  PotentialAlerts
  | join BrowserTraffic(lookback) on SourceUserName, RequestClientApplication
  | summarize RareHosts=any(RareHosts),BrowserHosts1d=any(BrowserHosts),BrowserHostsLookback=make_set(DestinationHostName) by SourceUserName, RequestClientApplication
  | where array_length(RareHosts) == array_length(BrowserHostsLookback)  
relevantTechniques:
- T1071.001
triggerOperator: gt
queryPeriod: 7d
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/FalconFriday/Analytic Rules/RecognizingBeaconingTraffic.yaml
severity: Medium
status: Available
id: 6345c923-99eb-4a83-b11d-7af0ffa75577
requiredDataConnectors:
- connectorId: Zscaler
  dataTypes:
  - CommonSecurityLog
version: 1.0.1
description: |
  This query searches web proxy logs for a specific type of beaconing behavior by joining a number of sources together: 
  - Traffic by actual web browsers - by looking at traffic generated by a UserAgent that looks like a browser and is used by multiple users to visit a large number of domains.
  - Users that make requests using one of these actual browsers, but only to a small set of domains, none of which are common domains.
  - The traffic is beacon-like; meaning that it occurs during many different hours of the day (i.e. periodic).   
{
  "$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/6345c923-99eb-4a83-b11d-7af0ffa75577')]",
      "kind": "Scheduled",
      "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/6345c923-99eb-4a83-b11d-7af0ffa75577')]",
      "properties": {
        "alertRuleTemplateName": "6345c923-99eb-4a83-b11d-7af0ffa75577",
        "customDetails": null,
        "description": "This query searches web proxy logs for a specific type of beaconing behavior by joining a number of sources together: \n- Traffic by actual web browsers - by looking at traffic generated by a UserAgent that looks like a browser and is used by multiple users to visit a large number of domains.\n- Users that make requests using one of these actual browsers, but only to a small set of domains, none of which are common domains.\n- The traffic is beacon-like; meaning that it occurs during many different hours of the day (i.e. periodic). \n",
        "displayName": "Beacon Traffic Based on Common User Agents Visiting Limited Number of Domains",
        "enabled": true,
        "entityMappings": [
          {
            "entityType": "Account",
            "fieldMappings": [
              {
                "columnName": "SourceUserName",
                "identifier": "FullName"
              }
            ]
          }
        ],
        "OriginalUri": "https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/FalconFriday/Analytic Rules/RecognizingBeaconingTraffic.yaml",
        "query": "let timeframe = 1d; // Timeframe during which to search for beaconing behavior.\nlet lookback = 7d; // Look back period to find if browser was used for other domains by user.\nlet min_requests=50; // Minimum number of requests to consider it beacon traffic.\nlet min_hours=8; // Minimum number of different hours during which connections were made to consider it beacon traffic.\nlet trusted_user_count=10; // If visited by this many users a domain is considered 'trusted'.\nlet max_sites=3; // Maximum number of different sites visited using this user-agent.\n// Client-specific query to obtain 'browser-like' traffic from proxy logs.\nlet BrowserTraffic = (p:timespan) {\nCommonSecurityLog\n| where DeviceVendor == \"Zscaler\" and DeviceProduct == \"NSSWeblog\"\n| where TimeGenerated >ago(p)\n| project TimeGenerated, SourceUserName, DestinationHostName, RequestClientApplication\n| where (RequestClientApplication startswith \"Mozilla/\" and RequestClientApplication contains \"Gecko\")\n};\nlet CommonDomains = BrowserTraffic(timeframe)\n| summarize source_count=dcount(SourceUserName) by DestinationHostName\n| where source_count>trusted_user_count\n| project DestinationHostName;\nlet CommonUA = BrowserTraffic(timeframe)\n| summarize source_count=dcount(SourceUserName), host_count=dcount(DestinationHostName) by RequestClientApplication\n| where source_count>trusted_user_count and host_count > 100 // Normal browsers are browsers used by many people and visiting many different sites.\n| project RequestClientApplication;\n// Find browsers that are common, i.e. many users use them and they use them to visit many different sites,\n// but some users only use the browser to visit a very limited set of sites.\n// These are considered suspicious, since they might be an attacker masquerading a beacon as a legitimate browser.\nlet SuspiciousBrowers = BrowserTraffic(timeframe)\n| where RequestClientApplication in(CommonUA)\n| summarize BrowserHosts=make_set(DestinationHostName),request_count=count() by RequestClientApplication, SourceUserName\n| where array_length(BrowserHosts) <= max_sites and request_count >= min_requests\n| project RequestClientApplication, SourceUserName,BrowserHosts;\n// Just reporting on suspicious browsers gives too many false positives.\n// For example, users that have the browser open on the login screen of 1 specific application.\n// In the suspicious browsers we can search for 'beacon-like' behavior.\n// Get all browser traffic by the suspicious browsers.\nlet PotentialAlerts=SuspiciousBrowers\n| join BrowserTraffic(timeframe) on RequestClientApplication, SourceUserName\n// Find beaconing-like traffic - i.e. contacting the same host in many different hours.\n| summarize hour_count=dcount(bin(TimeGenerated,1h)), BrowserHosts=any(BrowserHosts), request_count=count() by RequestClientApplication, SourceUserName, DestinationHostName\n| where hour_count >= min_hours and request_count >= min_requests\n// Remove common domains like login.microsoft.com.\n| join kind=leftanti CommonDomains on DestinationHostName\n| summarize RareHosts=make_set(DestinationHostName), TotalRequestCount=sum(request_count), BrowserHosts=any(BrowserHosts) by RequestClientApplication, SourceUserName\n// Remove browsers that visit any common domains.\n| where array_length(RareHosts) == array_length(BrowserHosts);\n// Look back for X days to see if the browser was not used to visit more hosts.\n// This is to get rid of someone that started up the browser a long time ago, and left only a single tab open.\nPotentialAlerts\n| join BrowserTraffic(lookback) on SourceUserName, RequestClientApplication\n| summarize RareHosts=any(RareHosts),BrowserHosts1d=any(BrowserHosts),BrowserHostsLookback=make_set(DestinationHostName) by SourceUserName, RequestClientApplication\n| where array_length(RareHosts) == array_length(BrowserHostsLookback)\n",
        "queryFrequency": "P1D",
        "queryPeriod": "P7D",
        "severity": "Medium",
        "status": "Available",
        "subTechniques": [
          "T1071.001"
        ],
        "suppressionDuration": "PT1H",
        "suppressionEnabled": false,
        "tactics": [
          "CommandAndControl"
        ],
        "techniques": [
          "T1071"
        ],
        "templateVersion": "1.0.1",
        "triggerOperator": "GreaterThan",
        "triggerThreshold": 0
      },
      "type": "Microsoft.OperationalInsights/workspaces/providers/alertRules"
    }
  ]
}