Detection rules › Kusto

Front Door Premium WAF - XSS Detection

Status
available
Severity
high
Time window
6h
Group by
action_s, clientIP_s, host_s
Source
github.com/Azure/Azure-Sentinel

'Identifies a match for an XSS attack in the Front Door Premium WAF logs. The threshold value in the query can be changed as per your infrastructure's requirements. References: https://owasp.org/www-project-top-ten/2017/A7_2017-Cross-Site_Scripting_(XSS)'

MITRE ATT&CK coverage

Rule body kusto

id: b7643904-5081-4920-917e-a559ddc3448f
name: Front Door Premium WAF - XSS Detection
description: | 
  'Identifies a match for an XSS attack in the Front Door Premium WAF logs. The threshold value in the query can be changed as per your infrastructure's requirements.
   References: https://owasp.org/www-project-top-ten/2017/A7_2017-Cross-Site_Scripting_(XSS)'
severity: High
status: Available
requiredDataConnectors: 
  - connectorId: WAF 
    dataTypes: 
      - AzureDiagnostics
queryFrequency: 6h 
queryPeriod: 6h 
triggerOperator: gt 
triggerThreshold: 0 
tactics: 
  - InitialAccess
  - Execution
relevantTechniques:
  - T1189
  - T1203
  - T0853
tags:
  - Cross Site Scripting
query:  |  
    let Threshold = 1;
    AzureDiagnostics
    | where Category =~ "FrontDoorWebApplicationFirewallLog"
    | where action_s =~ "AnomalyScoring"
    | where details_msg_s has "XSS"
    | parse details_data_s with MessageText "Matched Data:" MatchedData "AND " * "table_name FROM " TableName " " *
    | project trackingReference_s, host_s, requestUri_s, TimeGenerated, clientIP_s, details_matches_s, details_msg_s, details_data_s, TableName, MatchedData
    | join kind = inner(
    AzureDiagnostics
    | where Category =~ "FrontDoorWebApplicationFirewallLog"
    | where action_s =~ "Block") on trackingReference_s
    | summarize URI_s = make_set(requestUri_s,100), Table = make_set(TableName,100), StartTime = min(TimeGenerated), EndTime = max(TimeGenerated), TrackingReference = make_set(trackingReference_s,100), Matched_Data = make_set(MatchedData,100), Detail_Data = make_set(details_data_s,100), Detail_Message = make_set(details_msg_s,100), Total_TrackingReference = dcount(trackingReference_s) by clientIP_s, host_s, action_s
    | where Total_TrackingReference >= Threshold
# The Threshold value above can be changed as per your infrastructure's requirement 
entityMappings:
  - entityType: URL
    fieldMappings:
      - identifier: Url
        columnName: URI_s
  - entityType: IP
    fieldMappings:
      - identifier: Address
        columnName: clientIP_s 
version: 1.0.2
kind: Scheduled

Stages and Predicates

Parameters

let Threshold = 1;

Stage 1: source

AzureDiagnostics

Stage 2: where

| where Category =~ "FrontDoorWebApplicationFirewallLog"

Stage 3: where

| where action_s =~ "AnomalyScoring"

Stage 4: where

| where details_msg_s has "XSS"

Stage 5: parse

| parse details_data_s with MessageText "Matched Data:" MatchedData "AND " * "table_name FROM " TableName " " *

Stage 6: project

| project trackingReference_s, host_s, requestUri_s, TimeGenerated, clientIP_s, details_matches_s, details_msg_s, details_data_s, TableName, MatchedData

Stage 7: join

| join kind = inner(
AzureDiagnostics
| where Category =~ "FrontDoorWebApplicationFirewallLog"
| where action_s =~ "Block") on trackingReference_s

Stage 8: summarize

| summarize URI_s = make_set(requestUri_s,100), Table = make_set(TableName,100), StartTime = min(TimeGenerated), EndTime = max(TimeGenerated), TrackingReference = make_set(trackingReference_s,100), Matched_Data = make_set(MatchedData,100), Detail_Data = make_set(details_data_s,100), Detail_Message = make_set(details_msg_s,100), Total_TrackingReference = dcount(trackingReference_s) by clientIP_s, host_s, action_s
Threshold
ge 1

Stage 9: where

| where Total_TrackingReference >= 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
Categoryeq
  • FrontDoorWebApplicationFirewallLog
Total_TrackingReferencege
  • 1 transforms: cased
action_seq
  • AnomalyScoring
  • Block
details_msg_smatch
  • XSS transforms: term

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
Detail_Datasummarize
Detail_Messagesummarize
EndTimesummarize
Matched_Datasummarize
StartTimesummarize
Tablesummarize
Total_TrackingReferencesummarize
TrackingReferencesummarize
URI_ssummarize
action_ssummarize
clientIP_ssummarize
host_ssummarize