Detection rules › Kusto

App Gateway WAF - Scanner Detection

Status
available
Severity
high
Time window
6h
Group by
Action, ClientIp, TransactionId, Uri
Source
github.com/Azure/Azure-Sentinel

'Identifies a match for a Scanner detection user agent based attack in the App Gateway WAF logs. The threshold value in the query can be changed as per your infrastructure's requirements. References: https://owasp.org/www-community/Vulnerability_Scanning_Tools'

MITRE ATT&CK coverage

Rule body

id: 9b8dd8fd-f192-42eb-84f6-541920400a7a
name: App Gateway WAF - Scanner Detection 
description: | 
  'Identifies a match for a Scanner detection user agent based attack in the App Gateway WAF logs. The threshold value in the query can be changed as per your infrastructure's requirements.
  References: https://owasp.org/www-community/Vulnerability_Scanning_Tools'
severity: High 
status: Available 
requiredDataConnectors: 
  - connectorId: WAF
    dataTypes: 
      - AzureDiagnostics
queryFrequency: 6h 
queryPeriod: 6h 
triggerOperator: gt 
triggerThreshold: 0 
tactics: 
  - DefenseEvasion
  - Execution
  - InitialAccess
  - Reconnaissance
  - Discovery
relevantTechniques:
  - T1548
  - T1203
  - T1190
  - T1595
  - T1046
tags:
  - Scanner Detection
query:  | 
  let Threshold = 3;
  AGWFirewallLogs
  | where Action == "Matched"
  | where Message contains "Found User-Agent associated with security scanner"
  | project TransactionId, Hostname, RequestUri, TimeGenerated, ClientIp, Message, DetailedMessage, DetailedData
  | join kind = inner(
  AGWFirewallLogs
  | where Action == "Blocked"
  ) on TransactionId
  | extend Uri = strcat(Hostname,RequestUri)
  | summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated), TransactionID = make_set(TransactionId), Message = make_set(Message), Detail_Message = make_set(DetailedMessage), Detail_Data = make_set(DetailedData), Total_TransactionId = dcount(TransactionId) by ClientIp, Uri, Action
  | where Total_TransactionId >= Threshold
# The Threshold value above can be changed as per your infrastructure's requirement
entityMappings:
  - entityType: URL
    fieldMappings:
      - identifier: Url
        columnName: Uri
  - entityType: IP
    fieldMappings:
      - identifier: Address
        columnName: ClientIp 
version: 1.0.3
kind: Scheduled

Stages and Predicates

Parameters

let Threshold = 3;

Stage 1: source

AGWFirewallLogs

Stage 2: where

| where Action == "Matched"

Stage 3: where

| where Message contains "Found User-Agent associated with security scanner"

Stage 4: project

| project TransactionId, Hostname, RequestUri, TimeGenerated, ClientIp, Message, DetailedMessage, DetailedData

Stage 5: join

| join kind = inner(
AGWFirewallLogs
| where Action == "Blocked"
) on TransactionId

Stage 6: extend

| extend Uri = strcat(Hostname,RequestUri)

Stage 7: summarize

| summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated), TransactionID = make_set(TransactionId), Message = make_set(Message), Detail_Message = make_set(DetailedMessage), Detail_Data = make_set(DetailedData), Total_TransactionId = dcount(TransactionId) by ClientIp, Uri, Action

Stage 8: where

| where Total_TransactionId >= Threshold

Indicators

These rows show field, operator, and value matches.

Output fields

These fields are emitted when the rule matches.

FieldSource
Actionsummarize
ClientIpsummarize
Detail_Datasummarize
Detail_Messagesummarize
EndTimesummarize
Messagesummarize
StartTimesummarize
Total_TransactionIdsummarize
TransactionIDsummarize
Urisummarize