Cloud
WAF et KQL : identifier un faux positif avant de créer une exclusion
Méthode d’analyse KQL pour qualifier un blocage Azure WAF, distinguer attaque, bruit et faux positif applicatif, puis documenter la décision avant toute exclusion.
Un faux positif WAF ne se déclare pas parce qu’un utilisateur est bloqué. Il se démontre. Une requête peut être légitime du point de vue métier et rester dangereuse du point de vue technique. À l’inverse, une règle OWASP peut réagir à un contenu normal pour l’application : payload JSON riche, texte contenant des mots réservés SQL, paramètres encodés, chemins avec caractères spéciaux ou upload de fichier.
Le scénario traité ici part d’un blocage Azure WAF Application Gateway identifié dans Log Analytics. L’objectif est de qualifier le blocage avant de créer une exclusion. La bonne sortie de cette analyse n’est pas toujours une règle modifiée. Cela peut être une correction applicative, une validation frontend, une normalisation d’URL, une règle custom ou une exclusion très ciblée.
Cas fil rouge : le champ commentaire d’un partenaire
On reprend l’incident du portail partenaire. Le champ comment accepte du texte libre, car les partenaires y collent parfois des extraits de requêtes, des noms de colonnes ou des messages d’erreur. Depuis la dernière livraison, plusieurs soumissions vers /partner/comment sont bloquées par la règle 942100, alors que les utilisateurs authentifiés suivent un parcours normal.
Le but de l’analyse est concret : décider si le champ comment déclenche réellement un faux positif SQLi, ou si le formulaire accepte un contenu qui devrait être validé autrement. La réponse doit dire quoi faire ensuite : corriger l’application, limiter le champ, créer une exclusion ciblée, ou garder le blocage.
Isoler l’événement de référence
Commencer par un événement précis. Il faut une heure, une source, une URI, une règle et un message. Sans événement de référence, l’analyse reste trop générale.
let incidentTime = datetime(2026-05-26 14:32:00);
AzureDiagnostics
| where TimeGenerated between ((incidentTime - 10m) .. (incidentTime + 10m))
| where Category == "ApplicationGatewayFirewallLog"
| where action_s =~ "Blocked"
| project TimeGenerated,
clientIp_s,
hostname_s,
requestUri_s,
ruleId_s,
ruleSetType_s,
ruleSetVersion_s,
message_s,
details_message_s,
details_data_s
| order by TimeGenerated asc L’événement doit être conservé dans le ticket ou la note de changement. C’est la base de la discussion avec l’équipe applicative ou sécurité.
Mesurer le volume et la portée
Un faux positif réel se manifeste souvent sur un endpoint connu, avec un parcours utilisateur identifié. Un balayage hostile se manifeste plutôt par beaucoup d’URI, de sources ou de signatures. Cette distinction n’est pas absolue, mais le volume aide.
let rule = "942100";
AzureDiagnostics
| where TimeGenerated > ago(7d)
| where Category == "ApplicationGatewayFirewallLog"
| where ruleId_s == rule
| summarize events=count(),
clients=dcount(clientIp_s),
uris=dcount(requestUri_s),
sampleUri=any(requestUri_s),
sampleMessage=any(message_s)
by bin(TimeGenerated, 1d), hostname_s
| order by TimeGenerated desc Si la règle apparaît soudainement après une mise en production, il faut comparer avec le changement applicatif. Si elle apparaît sur des centaines d’URI depuis des sources variées, l’hypothèse attaque ou scan doit rester prioritaire.
Chercher le paramètre ou la zone qui déclenche
Les détails du log peuvent indiquer la partie de la requête impliquée : argument, cookie, header, corps ou autre champ selon le format disponible. L’objectif est d’identifier précisément ce que l’exclusion toucherait.
AzureDiagnostics
| where TimeGenerated > ago(24h)
| where Category == "ApplicationGatewayFirewallLog"
| where action_s =~ "Blocked"
| where ruleId_s == "942100"
| project TimeGenerated,
requestUri_s,
clientIp_s,
message_s,
details_message_s,
details_data_s
| order by TimeGenerated desc Si le champ déclencheur est un header standard, un paramètre métier connu ou une zone d’upload, l’exclusion peut parfois être ciblée. Si le déclencheur est large ou mal identifié, désactiver une règle entière est rarement défendable.
Comparer avec les logs applicatifs
Le WAF voit la requête à l’entrée. L’application voit ce qui passe vraiment. Pour qualifier un faux positif, il faut comparer avec les logs applicatifs lorsque c’est possible : utilisateur authentifié, endpoint, payload attendu, validation backend, code de réponse sur les requêtes autorisées.
Preuves à rassembler
Evénement WAF avec ruleId et action
Endpoint applicatif concerné
Paramètre, header ou zone suspecte
Parcours utilisateur attendu
Changement applicatif récent éventuel
Avis de l'équipe applicative
Décision sécurité : corriger, exclure, désactiver ou surveiller Dans le cas du champ comment, l’équipe applicative peut confirmer que l’utilisateur est authentifié, que le commentaire n’est jamais exécuté, que le backend applique une longueur maximale et que la valeur est stockée comme texte. Si ces preuves manquent, l’exclusion est prématurée : il faut d’abord durcir ou clarifier le comportement applicatif.
Décider avec une matrice simple
La décision doit être proportionnée. Une règle peut rester active avec une exclusion par paramètre. Une règle peut être désactivée temporairement sur une route si le risque est maîtrisé. Une requête peut aussi rester bloquée si elle révèle une faiblesse applicative.
Cas observé
Une règle unique bloque un paramètre métier connu sur un endpoint précis
Décision probable
Exclusion par règle et par variable, limitée au strict nécessaire
Cas observé
Plusieurs règles SQLi/XSS se déclenchent sur de nombreuses URI
Décision probable
Pas d'exclusion globale, investigation sécurité prioritaire
Cas observé
Une route d'upload déclenche des règles sur le corps de requête
Décision probable
Revoir limite, inspection, validation applicative et exclusion ciblée si justifiée Le niveau de granularité est essentiel. Plus l’exclusion est large, plus elle retire de protection.
Conclusion
Identifier un faux positif WAF demande plus qu’un ruleId. Il faut une preuve temporelle, un volume, une portée, un champ déclencheur et une compréhension applicative. KQL sert à construire cette preuve avant que la configuration ne soit modifiée.
La bonne question n’est pas seulement : quelle règle bloque ? C’est : que protège cette règle, quelle partie de la requête la déclenche, est-ce attendu pour l’application, et peut-on réduire l’exception au minimum ? Une exclusion bien documentée est un contrôle. Une exclusion créée dans l’urgence devient vite une dette de sécurité.