Detection rules › Kusto

Detect instances of multiple client errors occurring within a brief period of time (ASIM Web Session)

Status
available
Severity
medium
Time window
5m
Group by
SrcHostname, SrcIpAddr, SrcUsername
Source
github.com/Azure/Azure-Sentinel

'This detection mechanism identifies situations where multiple client errors originate from a single source within a limited time frame.'

MITRE ATT&CK coverage

Rule body kusto

id: faa40333-1e8b-40cc-a003-51ae41fa886f
name: Detect instances of multiple client errors occurring within a brief period of time (ASIM Web Session)
description: |
  'This detection mechanism identifies situations where multiple client errors originate from a single source within a limited time frame.'
severity: Medium
status: Available 
tags:
  - Schema: WebSession
    SchemaVersion: 0.2.6
requiredDataConnectors: []
queryFrequency: 1h
queryPeriod: 1h
triggerOperator: gt
triggerThreshold: 0
tactics:
  - InitialAccess
  - CommandAndControl
relevantTechniques:
  - T1190
  - T1133
  - T1071
query: |
  // HTTP response status codes indicate whether a specific HTTP request has been successfully completed.
  // Please refer this for more details: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status
  let threshold = 100; // You can set threshold value that suits your environment
  _Im_WebSession(starttime=ago(1h))
  | where toint(EventResultDetails) between (400 .. 499)
  | summarize
      TotalErrorCount = count(),
      EventStartTime = min(TimeGenerated),
      EventEndTime = max(TimeGenerated),
      URLs=make_set(Url, 100),
      EventResultDetailsSet=make_set(EventResultDetails,10)
      by SrcIpAddr, bin(TimeGenerated, 5m), SrcUsername, SrcHostname
  | where TotalErrorCount > 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: Account
    fieldMappings:
      - identifier: Name
        columnName: Name
      - identifier: UPNSuffix
        columnName: UPNSuffix
  - entityType: Host
    fieldMappings:
      - identifier: HostName
        columnName: SrcHostname
eventGroupingSettings:
  aggregationKind: AlertPerResult
customDetails:
  TotalErrorCount: TotalErrorCount
  ErrorThreshold: Threshold
  RequestURLs: URLs
  EventResultSet: EventResultDetailsSet
  EventStartTime: EventStartTime
  EventEndTime: EventEndTime
alertDetailsOverride:
  alertDisplayNameFormat: "High number of client errors originated by user '{{SrcUsername}}' from IP address '{{SrcIpAddr}}'"
  alertDescriptionFormat: "The client has made a total of '{{TotalErrorCount}}' requests to URLs '{{URLs}}', 
                            which have resulted in client errors. A sudden surge in HTTP code errors, especially in the form of client-side errors like 400 or 401, could indicate malicious activity, such as attackers attempting to exploit vulnerabilities or perform unauthorized actions. For detailed information regarding the specific errors encountered, please refer to the following link:
                            https://developer.mozilla.org/en-US/docs/Web/HTTP/Status."
version: 1.0.0
kind: Scheduled

Stages and Predicates

Parameters

let threshold = 100;

Stage 1: source

_Im_WebSession(starttime=ago(1h))

Stage 2: where

| where toint(EventResultDetails) between (400 .. 499)

Stage 3: summarize

| summarize
    TotalErrorCount = count(),
    EventStartTime = min(TimeGenerated),
    EventEndTime = max(TimeGenerated),
    URLs=make_set(Url, 100),
    EventResultDetailsSet=make_set(EventResultDetails,10)
    by SrcIpAddr, bin(TimeGenerated, 5m), SrcUsername, SrcHostname
Threshold
gt 100

Stage 4: where

| where TotalErrorCount > threshold

Stage 5: 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.

FieldKindValues
TotalErrorCountgt
  • 100 transforms: cased

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.

FieldSource
EventEndTimesummarize
EventResultDetailsSetsummarize
EventStartTimesummarize
SrcHostnamesummarize
SrcIpAddrsummarize
SrcUsernamesummarize
TotalErrorCountsummarize
URLssummarize
Nameextend
Thresholdextend
UPNSuffixextend