Detection rules › Kusto
Identify instances where a single source is observed using multiple user agents (ASIM Web Session)
'This detection mechanism identifies requests originating from a single source within a brief time period that exhibit multiple user agents. Such behavior could indicate unusual web browsing activities performed by unconventional processes'
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Initial Access | T1133 External Remote Services, T1190 Exploit Public-Facing Application |
| Credential Access | T1528 Steal Application Access Token |
Rule body kusto
id: 813ccf3b-0321-4622-b0bc-63518fd14454
name: Identify instances where a single source is observed using multiple user agents (ASIM Web Session)
description: |
'This detection mechanism identifies requests originating from a single source within a brief time period that exhibit multiple user agents. Such behavior could indicate unusual web browsing activities performed by unconventional processes'
severity: Medium
status: Available
tags:
- Schema: WebSession
SchemaVersion: 0.2.6
requiredDataConnectors: []
queryFrequency: 1h
queryPeriod: 1h
triggerOperator: gt
triggerThreshold: 0
tactics:
- InitialAccess
- CredentialAccess
relevantTechniques:
- T1190
- T1133
- T1528
query: |
let threshold = 5; // Please update threshold limit as per your environment
_Im_WebSession(starttime=ago(1h), eventresult="Success")
| where isnotempty(HttpUserAgent)
| summarize
EventCount=count(),
UserAgentList=make_set(HttpUserAgent, 100),
URL_List = make_set(Url, 100),
DestinationIPList = make_set(DstIpAddr, 100)
by SrcIpAddr, SrcUsername, SrcHostname, bin(TimeGenerated, 5min)
| extend UserAgentCount = array_length(UserAgentList)
| where UserAgentCount > threshold
| extend Name = iif(SrcUsername contains "@", tostring(split(SrcUsername,'@',0)[0]),SrcUsername), UPNSuffix = iif(SrcUsername contains "@",tostring(split(SrcUsername,'@',1)[0]),""), Threshold=threshold
entityMappings:
- entityType: IP
fieldMappings:
- identifier: Address
columnName: SrcIpAddr
- entityType: Host
fieldMappings:
- identifier: HostName
columnName: SrcHostname
- entityType: Account
fieldMappings:
- identifier: Name
columnName: Name
- identifier: UPNSuffix
columnName: UPNSuffix
eventGroupingSettings:
aggregationKind: AlertPerResult
customDetails:
UserAgentCount: UserAgentCount
UserAgentArray: UserAgentList
UserAgentThreshold: Threshold
URLs: URL_List
DestinationIPList: DestinationIPList
alertDetailsOverride:
alertDisplayNameFormat: "User '{{SrcUsername}}' with IP '{{SrcIpAddr}}' has been observed using high number of User Agents within short timeframe"
alertDescriptionFormat: "The system has detected high User Agent count of '{{UserAgentCount}}' originating from '{{SrcUsername}}'. Further investigation is necessary to determine the reason behind the detection of multiple user agents associated with the SrcIpAddr in this incident. User Agent list include: '{{UserAgentList}}'"
version: 1.0.1
kind: Scheduled
Stages and Predicates
Parameters
let threshold = 5;
Stage 1: source
_Im_WebSession(starttime=ago(1h), eventresult="Success")
Stage 2: where
| where isnotempty(HttpUserAgent)
Stage 3: summarize
| summarize
EventCount=count(),
UserAgentList=make_set(HttpUserAgent, 100),
URL_List = make_set(Url, 100),
DestinationIPList = make_set(DstIpAddr, 100)
by SrcIpAddr, SrcUsername, SrcHostname, bin(TimeGenerated, 5min)
Stage 4: extend
| extend UserAgentCount = array_length(UserAgentList)
Stage 5: where
| where UserAgentCount > threshold
Stage 6: extend
| extend Name = iif(SrcUsername contains "@", tostring(split(SrcUsername,'@',0)[0]),SrcUsername), UPNSuffix = iif(SrcUsername contains "@",tostring(split(SrcUsername,'@',1)[0]),""), Threshold=threshold
Indicators
Each row is a field, operator, and value that the rule matches. The corpus column counts how many other rules in the catalog look for the same combination: high numbers point to widely-used, community-vetted indicators. Blank or 1 shows that the indicator is specific to this rule.
| Field | Kind | Values |
|---|---|---|
HttpUserAgent | is_not_null | |
UserAgentCount | gt |
|
Output fields
Fields the rule emits when it matches. Chronicle authors list these in the outcome block; they appear on the detection and $risk_score drives alerting. Sentinel / Defender XDR rules build them up through project / summarize / extend stages. Sentinel maps these into alert fields via entityMappings and customDetails; Defender XDR custom detections surface them as alert fields directly.
| Field | Source |
|---|---|
DestinationIPList | summarize |
EventCount | summarize |
SrcHostname | summarize |
SrcIpAddr | summarize |
SrcUsername | summarize |
URL_List | summarize |
UserAgentList | summarize |
UserAgentCount | extend |
Name | extend |
Threshold | extend |
UPNSuffix | extend |