Detect presence of uncommon user agents in web requests ASIM Web Session
Id | 2d50d937-d7f2-4c05-b151-9af7f9ec747e |
Rulename | Detect presence of uncommon user agents in web requests (ASIM Web Session) |
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 |
Tactics | InitialAccess |
Techniques | T1190 T1133 |
Kind | Scheduled |
Query frequency | 1h |
Query period | 14d |
Trigger threshold | 0 |
Trigger operator | gt |
Source Uri | https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Web Session Essentials/Analytic Rules/RareUserAgentDetected.yaml |
Version | 1.0.1 |
Arm template | 2d50d937-d7f2-4c05-b151-9af7f9ec747e.json |
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]),"")
status: Available
triggerOperator: gt
triggerThreshold: 0
name: Detect presence of uncommon user agents in web requests (ASIM Web Session)
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.
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Web Session Essentials/Analytic Rules/RareUserAgentDetected.yaml
queryPeriod: 14d
severity: Medium
tags:
- SchemaVersion: 0.2.6
Schema: WebSession
eventGroupingSettings:
aggregationKind: AlertPerResult
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
queryFrequency: 1h
relevantTechniques:
- T1190
- T1133
requiredDataConnectors: []
kind: Scheduled
customDetails:
EventStartTime: EventStartTime
EventEndTime: EventEndTime
EventCount: EventCount
HttpUserAgent: HttpUserAgent
DstPortNumber: DstPortNumber
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'
tactics:
- InitialAccess
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]),"")
id: 2d50d937-d7f2-4c05-b151-9af7f9ec747e
version: 1.0.1
{
"$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"
}
]
}