↳ Source GitHubRègle analytiqueMedium

A potentially malicious web request was executed against a web server

Description

'Detects unobstructed Web Application Firewall (WAF) activity in sessions where the WAF blocked incoming requests by computing the ratio between blocked requests and unobstructed WAF requests in these sessions (BlockvsSuccessRatio metric). A high ratio value for a given client IP and hostname calls for further investigation of the WAF data in that session, due to the significantly high number of blocked requests and a few unobstructed logs that may be malicious but have passed undetected through the WAF. The successCode variable defines what the detection thinks is a successful status code and should be altered to fit the environment.'
Type de règle
Scheduled
Version
1.0.6
Statut déclaré
Available
Fréquence
1d
Période analysée
1d
Déclenchement
gt 0

Couverture MITRE déclarée

Sources déclarées

Métadonnées du fichier source. Aucune dépendance déduite du KQL.

Connecteurs

Types de données

Requête KQL

Requête originale, sans modification.

let queryperiod = 1d;
let mode = dynamic(['Blocked', 'Detected']);
let successCode = dynamic(['200', '101','204', '400','504','304','401','500']);
let sessionBin = 30m;
AGWFirewallLogs
| where TimeGenerated > ago(queryperiod)
| where Action  in (mode)
| sort by Hostname asc, ClientIp asc, TimeGenerated asc
| extend SessionBlockedStarted = row_window_session(TimeGenerated, queryperiod, 10m, ((ClientIp != prev(ClientIp)) or (Hostname != prev(Hostname))))
| summarize SessionBlockedEnded = max(TimeGenerated), SessionBlockedCount = count() by Hostname, ClientIp, SessionBlockedStarted
| extend TimeKey = range(bin(SessionBlockedStarted, sessionBin), bin(SessionBlockedEnded, sessionBin), sessionBin)
| mv-expand TimeKey to typeof(datetime)
| join kind = inner(
    AGWAccessLogs
    | where TimeGenerated > ago(queryperiod)
    | where  (isempty(HttpStatus) or HttpStatus in (successCode))
    | extend TimeKey = bin(TimeGenerated, sessionBin)
    | extend Hostname = coalesce(Host,OriginalHost)
    | extend ClientIp = tostring(ClientIp)
) on TimeKey, Hostname, ClientIp
| where TimeGenerated between (SessionBlockedStarted..SessionBlockedEnded)
| extend
    OriginalRequestUriWithArgs = column_ifexists("OriginalRequestUriWithArgs", ""),
    ServerStatus = column_ifexists("ServerStatus", "")
| summarize
    SuccessfulAccessCount = count(),
    UserAgents = make_set(UserAgent, 250),
    RequestURIs = make_set(RequestUri, 250),
    OriginalRequestURIs = make_set(OriginalRequestUriWithArgs, 250),
    SuccessCodes = make_set(HttpStatus, 250),
    SuccessCodes_BackendServer = make_set(ServerStatus, 250),
    take_any(SessionBlockedEnded, SessionBlockedCount)
    by Hostname, ClientIp, SessionBlockedStarted 
| where SessionBlockedCount > SuccessfulAccessCount
| extend BlockvsSuccessRatio = SessionBlockedCount/toreal(SuccessfulAccessCount)
| sort by BlockvsSuccessRatio desc, SessionBlockedStarted asc
| project-reorder SessionBlockedStarted, SessionBlockedEnded, Hostname, ClientIp, SessionBlockedCount, SuccessfulAccessCount, BlockvsSuccessRatio, SuccessCodes, RequestURIs, OriginalRequestURIs, UserAgents

Entités déclarées

IP

Contenus associés

Liens établis à partir des identifiants déclarés et des manifests des solutions.

Traçabilité de la source

GitHub

Les valeurs affichées proviennent des fichiers du dépôt Azure/Azure-Sentinel. Elles décrivent le modèle publié, pas la configuration de votre workspace.

Identifiant source
46ac55ae-47b8-414a-8f94-89ccd1962178
Autres fichiers source 3Solutions/Azure Web Application Firewall (WAF)/Analytic Rules/MaliciousWAFSessions.yamlsource ↗Detections/AzureDiagnostics/MaliciousWAFSessions.yamlmigration-note ↗Solutions/Azure Web Application Firewall (WAF)/Data/Solution_AzureWAF.jsonsolution-membership ↗
GSTEP / SUIVI DU CATALOGUE

Ajouté au catalogue : 16 sept. 2026 · 05:49 UTC
Dernier changement observé : 16 sept. 2026 · 05:49 UTC

Dates de synchronisation GSTEP, distinctes des dates de publication du contenu source.