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

Detect presence of uncommon user agents in web requests ASIM Web Session

Back
Id2d50d937-d7f2-4c05-b151-9af7f9ec747e
RulenameDetect presence of uncommon user agents in web requests (ASIM Web Session)
DescriptionThis rule assists in detecting rare user agents, which may indicate web browsing activity by an unconventional process different from the usual ones. The rule specifically searches for UserAgent strings that have not been seen in the past 14 days. This query will perform better when run over summarized data
SeverityMedium
TacticsInitialAccess
TechniquesT1190
T1133
KindScheduled
Query frequency1h
Query period14d
Trigger threshold0
Trigger operatorgt
Source Urihttps://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Web Session Essentials/Analytic Rules/RareUserAgentDetected.yaml
Version1.0.1
Arm template2d50d937-d7f2-4c05-b151-9af7f9ec747e.json
Deploy To Azure
let lookBack = 14d;
let timeframe = 1h;
// calculate avg. eps(events per second)
let eps = materialize(_Im_WebSession(starttime=ago(1d))
    | project TimeGenerated
    | summarize AvgPerSec = count() / 3600 by bin(TimeGenerated, 1h)
    | summarize round(avg(AvgPerSec))
    );
let summarizationexist  = (
    union isfuzzy=true 
        (
        WebSession_Summarized_SrcInfo_CL
        | where EventTime_t > ago(1d) 
        | project v = int(2)
        ),
        (
        print int(1) 
        | project v = print_0
        )
    | summarize maxv = max(v)
    | extend sumexist = (maxv > 1)
    );
let allUserAgents = union isfuzzy=true
        (
        (datatable(exists: int, sumexist: bool)[1, false]
        | where toscalar(eps) > 1000
        | join (summarizationexist) on sumexist)
        | join (
            _Im_WebSession(starttime=todatetime(ago(2d)), endtime=bin(ago(timeframe), 1h), eventresult='Success')
            | where isnotempty(HttpUserAgent)
            | summarize UserAgentsSet =  make_set(HttpUserAgent) // This could contain upto 10,48,576 unique values
            | extend exists=int(1)
            )
            on exists
        | project-away exist*, maxv, sum*
        ),
        (
        (datatable(exists: int, sumexist: bool)[1, false]
        | where toscalar(eps) between (501 .. 1000)
        | join (summarizationexist) on sumexist)
        | join (
            _Im_WebSession(starttime=todatetime(ago(3d)), endtime=bin(ago(timeframe), 1h), eventresult='Success')
            | where isnotempty(HttpUserAgent)
            | summarize UserAgentsSet = make_set(HttpUserAgent) // This could contain upto 10,48,576 unique values
            | extend exists=int(1)
            )
            on exists
        | project-away exist*, maxv, sum*
        ),
        (
        (datatable(exists: int, sumexist: bool)[1, false]
        | where toscalar(eps) <= 500
        | join (summarizationexist) on sumexist)
        | join (
            _Im_WebSession(starttime=todatetime(ago(4d)), endtime=bin(ago(timeframe), 1h), eventresult='Success')
            | where isnotempty(HttpUserAgent)
            | summarize UserAgentsSet = make_set(HttpUserAgent) // This could contain upto 10,48,576 unique values
            | extend exists=int(1)
            )
            on exists
        | project-away exist*, maxv, sum*
        ),
        (
        WebSession_Summarized_SrcInfo_CL
        | where EventTime_t between (ago(14d) .. ago(timeframe))
            and isnotempty(HttpUserAgent_s)
            and EventResult_s =~ 'Success'
        | summarize UserAgentsSet = make_set(HttpUserAgent_s) // This could contain upto 10,48,576 unique values
        );
_Im_WebSession (starttime=bin(ago(timeframe), 1h), eventresult='Success')
| project
    SrcIpAddr,
    SrcUsername,
    SrcHostname,
    DstIpAddr,
    DstPortNumber,
    Url,
    HttpUserAgent,
    TimeGenerated
| where isnotempty(HttpUserAgent) and HttpUserAgent !in~ (allUserAgents)
| summarize
    EventCount=count(),
    EventStartTime=min(TimeGenerated),
    EventEndTime=max(TimeGenerated)
    by
    SrcIpAddr,
    SrcUsername,
    SrcHostname,
    DstIpAddr,
    Url,
    HttpUserAgent,
    DstPortNumber
| extend Name = iif(SrcUsername contains "@", tostring(split(SrcUsername,'@',0)[0]),SrcUsername), UPNSuffix = iif(SrcUsername contains "@",tostring(split(SrcUsername,'@',1)[0]),"")
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Web Session Essentials/Analytic Rules/RareUserAgentDetected.yaml
query: |
  let lookBack = 14d;
  let timeframe = 1h;
  // calculate avg. eps(events per second)
  let eps = materialize(_Im_WebSession(starttime=ago(1d))
      | project TimeGenerated
      | summarize AvgPerSec = count() / 3600 by bin(TimeGenerated, 1h)
      | summarize round(avg(AvgPerSec))
      );
  let summarizationexist  = (
      union isfuzzy=true 
          (
          WebSession_Summarized_SrcInfo_CL
          | where EventTime_t > ago(1d) 
          | project v = int(2)
          ),
          (
          print int(1) 
          | project v = print_0
          )
      | summarize maxv = max(v)
      | extend sumexist = (maxv > 1)
      );
  let allUserAgents = union isfuzzy=true
          (
          (datatable(exists: int, sumexist: bool)[1, false]
          | where toscalar(eps) > 1000
          | join (summarizationexist) on sumexist)
          | join (
              _Im_WebSession(starttime=todatetime(ago(2d)), endtime=bin(ago(timeframe), 1h), eventresult='Success')
              | where isnotempty(HttpUserAgent)
              | summarize UserAgentsSet =  make_set(HttpUserAgent) // This could contain upto 10,48,576 unique values
              | extend exists=int(1)
              )
              on exists
          | project-away exist*, maxv, sum*
          ),
          (
          (datatable(exists: int, sumexist: bool)[1, false]
          | where toscalar(eps) between (501 .. 1000)
          | join (summarizationexist) on sumexist)
          | join (
              _Im_WebSession(starttime=todatetime(ago(3d)), endtime=bin(ago(timeframe), 1h), eventresult='Success')
              | where isnotempty(HttpUserAgent)
              | summarize UserAgentsSet = make_set(HttpUserAgent) // This could contain upto 10,48,576 unique values
              | extend exists=int(1)
              )
              on exists
          | project-away exist*, maxv, sum*
          ),
          (
          (datatable(exists: int, sumexist: bool)[1, false]
          | where toscalar(eps) <= 500
          | join (summarizationexist) on sumexist)
          | join (
              _Im_WebSession(starttime=todatetime(ago(4d)), endtime=bin(ago(timeframe), 1h), eventresult='Success')
              | where isnotempty(HttpUserAgent)
              | summarize UserAgentsSet = make_set(HttpUserAgent) // This could contain upto 10,48,576 unique values
              | extend exists=int(1)
              )
              on exists
          | project-away exist*, maxv, sum*
          ),
          (
          WebSession_Summarized_SrcInfo_CL
          | where EventTime_t between (ago(14d) .. ago(timeframe))
              and isnotempty(HttpUserAgent_s)
              and EventResult_s =~ 'Success'
          | summarize UserAgentsSet = make_set(HttpUserAgent_s) // This could contain upto 10,48,576 unique values
          );
  _Im_WebSession (starttime=bin(ago(timeframe), 1h), eventresult='Success')
  | project
      SrcIpAddr,
      SrcUsername,
      SrcHostname,
      DstIpAddr,
      DstPortNumber,
      Url,
      HttpUserAgent,
      TimeGenerated
  | where isnotempty(HttpUserAgent) and HttpUserAgent !in~ (allUserAgents)
  | summarize
      EventCount=count(),
      EventStartTime=min(TimeGenerated),
      EventEndTime=max(TimeGenerated)
      by
      SrcIpAddr,
      SrcUsername,
      SrcHostname,
      DstIpAddr,
      Url,
      HttpUserAgent,
      DstPortNumber
  | extend Name = iif(SrcUsername contains "@", tostring(split(SrcUsername,'@',0)[0]),SrcUsername), UPNSuffix = iif(SrcUsername contains "@",tostring(split(SrcUsername,'@',1)[0]),"")  
description: |
    'This rule assists in detecting rare user agents, which may indicate web browsing activity by an unconventional process different from the usual ones. The rule specifically searches for UserAgent strings that have not been seen in the past 14 days. This query will perform better when run over summarized data'
severity: Medium
requiredDataConnectors: []
eventGroupingSettings:
  aggregationKind: AlertPerResult
tags:
- Schema: WebSession
  SchemaVersion: 0.2.6
triggerThreshold: 0
version: 1.0.1
customDetails:
  DstPortNumber: DstPortNumber
  EventStartTime: EventStartTime
  EventEndTime: EventEndTime
  EventCount: EventCount
  HttpUserAgent: HttpUserAgent
entityMappings:
- entityType: URL
  fieldMappings:
  - columnName: Url
    identifier: Url
- entityType: IP
  fieldMappings:
  - columnName: SrcIpAddr
    identifier: Address
- entityType: IP
  fieldMappings:
  - columnName: DstIpAddr
    identifier: Address
- entityType: Account
  fieldMappings:
  - columnName: Name
    identifier: Name
  - columnName: UPNSuffix
    identifier: UPNSuffix
- entityType: Host
  fieldMappings:
  - columnName: SrcHostname
    identifier: HostName
tactics:
- InitialAccess
alertDetailsOverride:
  alertDescriptionFormat: The user agent '{{HttpUserAgent}}' has not been observed in the past 14 days. Conduct research on the user agent string to determine if it is associated with a known legitimate bot or if it is potentially linked to malicious activity. The URL is associated with the IP address '{{DstIpAddr}}'.
  alertDisplayNameFormat: User '{{SrcUsername}}' with IP '{{SrcIpAddr}}' has been observed accessing URL '{{Url}}' using a rare user agent.
relevantTechniques:
- T1190
- T1133
triggerOperator: gt
name: Detect presence of uncommon user agents in web requests (ASIM Web Session)
id: 2d50d937-d7f2-4c05-b151-9af7f9ec747e
status: Available
kind: Scheduled
queryFrequency: 1h
queryPeriod: 14d
{
  "$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/2d50d937-d7f2-4c05-b151-9af7f9ec747e')]",
      "kind": "Scheduled",
      "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/2d50d937-d7f2-4c05-b151-9af7f9ec747e')]",
      "properties": {
        "alertDetailsOverride": {
          "alertDescriptionFormat": "The user agent '{{HttpUserAgent}}' has not been observed in the past 14 days. Conduct research on the user agent string to determine if it is associated with a known legitimate bot or if it is potentially linked to malicious activity. The URL is associated with the IP address '{{DstIpAddr}}'.",
          "alertDisplayNameFormat": "User '{{SrcUsername}}' with IP '{{SrcIpAddr}}' has been observed accessing URL '{{Url}}' using a rare user agent."
        },
        "alertRuleTemplateName": "2d50d937-d7f2-4c05-b151-9af7f9ec747e",
        "customDetails": {
          "DstPortNumber": "DstPortNumber",
          "EventCount": "EventCount",
          "EventEndTime": "EventEndTime",
          "EventStartTime": "EventStartTime",
          "HttpUserAgent": "HttpUserAgent"
        },
        "description": "'This rule assists in detecting rare user agents, which may indicate web browsing activity by an unconventional process different from the usual ones. The rule specifically searches for UserAgent strings that have not been seen in the past 14 days. This query will perform better when run over summarized data'\n",
        "displayName": "Detect presence of uncommon user agents in web requests (ASIM Web Session)",
        "enabled": true,
        "entityMappings": [
          {
            "entityType": "URL",
            "fieldMappings": [
              {
                "columnName": "Url",
                "identifier": "Url"
              }
            ]
          },
          {
            "entityType": "IP",
            "fieldMappings": [
              {
                "columnName": "SrcIpAddr",
                "identifier": "Address"
              }
            ]
          },
          {
            "entityType": "IP",
            "fieldMappings": [
              {
                "columnName": "DstIpAddr",
                "identifier": "Address"
              }
            ]
          },
          {
            "entityType": "Account",
            "fieldMappings": [
              {
                "columnName": "Name",
                "identifier": "Name"
              },
              {
                "columnName": "UPNSuffix",
                "identifier": "UPNSuffix"
              }
            ]
          },
          {
            "entityType": "Host",
            "fieldMappings": [
              {
                "columnName": "SrcHostname",
                "identifier": "HostName"
              }
            ]
          }
        ],
        "eventGroupingSettings": {
          "aggregationKind": "AlertPerResult"
        },
        "OriginalUri": "https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Web Session Essentials/Analytic Rules/RareUserAgentDetected.yaml",
        "query": "let lookBack = 14d;\nlet timeframe = 1h;\n// calculate avg. eps(events per second)\nlet eps = materialize(_Im_WebSession(starttime=ago(1d))\n    | project TimeGenerated\n    | summarize AvgPerSec = count() / 3600 by bin(TimeGenerated, 1h)\n    | summarize round(avg(AvgPerSec))\n    );\nlet summarizationexist  = (\n    union isfuzzy=true \n        (\n        WebSession_Summarized_SrcInfo_CL\n        | where EventTime_t > ago(1d) \n        | project v = int(2)\n        ),\n        (\n        print int(1) \n        | project v = print_0\n        )\n    | summarize maxv = max(v)\n    | extend sumexist = (maxv > 1)\n    );\nlet allUserAgents = union isfuzzy=true\n        (\n        (datatable(exists: int, sumexist: bool)[1, false]\n        | where toscalar(eps) > 1000\n        | join (summarizationexist) on sumexist)\n        | join (\n            _Im_WebSession(starttime=todatetime(ago(2d)), endtime=bin(ago(timeframe), 1h), eventresult='Success')\n            | where isnotempty(HttpUserAgent)\n            | summarize UserAgentsSet =  make_set(HttpUserAgent) // This could contain upto 10,48,576 unique values\n            | extend exists=int(1)\n            )\n            on exists\n        | project-away exist*, maxv, sum*\n        ),\n        (\n        (datatable(exists: int, sumexist: bool)[1, false]\n        | where toscalar(eps) between (501 .. 1000)\n        | join (summarizationexist) on sumexist)\n        | join (\n            _Im_WebSession(starttime=todatetime(ago(3d)), endtime=bin(ago(timeframe), 1h), eventresult='Success')\n            | where isnotempty(HttpUserAgent)\n            | summarize UserAgentsSet = make_set(HttpUserAgent) // This could contain upto 10,48,576 unique values\n            | extend exists=int(1)\n            )\n            on exists\n        | project-away exist*, maxv, sum*\n        ),\n        (\n        (datatable(exists: int, sumexist: bool)[1, false]\n        | where toscalar(eps) <= 500\n        | join (summarizationexist) on sumexist)\n        | join (\n            _Im_WebSession(starttime=todatetime(ago(4d)), endtime=bin(ago(timeframe), 1h), eventresult='Success')\n            | where isnotempty(HttpUserAgent)\n            | summarize UserAgentsSet = make_set(HttpUserAgent) // This could contain upto 10,48,576 unique values\n            | extend exists=int(1)\n            )\n            on exists\n        | project-away exist*, maxv, sum*\n        ),\n        (\n        WebSession_Summarized_SrcInfo_CL\n        | where EventTime_t between (ago(14d) .. ago(timeframe))\n            and isnotempty(HttpUserAgent_s)\n            and EventResult_s =~ 'Success'\n        | summarize UserAgentsSet = make_set(HttpUserAgent_s) // This could contain upto 10,48,576 unique values\n        );\n_Im_WebSession (starttime=bin(ago(timeframe), 1h), eventresult='Success')\n| project\n    SrcIpAddr,\n    SrcUsername,\n    SrcHostname,\n    DstIpAddr,\n    DstPortNumber,\n    Url,\n    HttpUserAgent,\n    TimeGenerated\n| where isnotempty(HttpUserAgent) and HttpUserAgent !in~ (allUserAgents)\n| summarize\n    EventCount=count(),\n    EventStartTime=min(TimeGenerated),\n    EventEndTime=max(TimeGenerated)\n    by\n    SrcIpAddr,\n    SrcUsername,\n    SrcHostname,\n    DstIpAddr,\n    Url,\n    HttpUserAgent,\n    DstPortNumber\n| extend Name = iif(SrcUsername contains \"@\", tostring(split(SrcUsername,'@',0)[0]),SrcUsername), UPNSuffix = iif(SrcUsername contains \"@\",tostring(split(SrcUsername,'@',1)[0]),\"\")\n",
        "queryFrequency": "PT1H",
        "queryPeriod": "P14D",
        "severity": "Medium",
        "status": "Available",
        "subTechniques": [],
        "suppressionDuration": "PT1H",
        "suppressionEnabled": false,
        "tactics": [
          "InitialAccess"
        ],
        "tags": [
          {
            "Schema": "WebSession",
            "SchemaVersion": "0.2.6"
          }
        ],
        "techniques": [
          "T1133",
          "T1190"
        ],
        "templateVersion": "1.0.1",
        "triggerOperator": "GreaterThan",
        "triggerThreshold": 0
      },
      "type": "Microsoft.OperationalInsights/workspaces/providers/alertRules"
    }
  ]
}