Cloud
Azure WAF : valider une montée de version des règles managées avant Prevention
Un runbook de production pour qualifier une montée de version Azure WAF OWASP/CRS avec logs, faux positifs, mode Detection, diff de policy, validation applicative, décision de Prevention et rollback.
Une montée de version des règles managées Azure WAF semble souvent être une opération de maintenance : passer à un jeu OWASP/CRS plus récent, activer une nouvelle version sur Azure Application Gateway ou Azure Front Door, puis laisser la protection travailler. En production, ce changement peut modifier le score d’anomalie, déclencher de nouveaux ruleId, bloquer des payloads légitimes, ou au contraire donner l’impression que tout est sain parce que la policy reste en Detection.
Le cas d’usage est une application exposée en public avec une policy WAF gérée en IaC. L’équipe sécurité veut bénéficier des règles récentes. L’équipe applicative veut éviter un incident 403 sur un parcours critique. L’objectif du runbook est de décider quand la nouvelle version peut passer en Prevention, quand il faut rester en Detection, quand créer une exclusion ciblée, et quand rollbacker la policy.
Cadrer le changement de règles
Commencez par écrire le changement comme une décision d’exploitation, pas comme une simple mise à jour de version. La question n’est pas seulement “quelle version est disponible ?”, mais “quel trafic sera évalué différemment, avec quelle action, sur quels hostnames, et avec quel retour arrière ?”.
Surface
Azure Application Gateway WAF ou Azure Front Door WAF
Policy: waf-prod-public
Hostnames: api.example.com, portal.example.com
Current mode: Detection ou Prevention
Current managed rules: OWASP_3.2 ou Microsoft_DefaultRuleSet_2.x
Target managed rules: nouvelle version supportee
Decision attendue
Rester en Detection
Passer la nouvelle version en Prevention
Desactiver un ruleId precis
Ajouter une exclusion ciblee
Garder l'ancienne version
Rollbacker la policy apres incident
Preuves minimales
Logs WAF avant/apres
Parcours applicatifs critiques rejoues
RuleId nouveaux ou plus bruyants
Faux positifs qualifies
Diff IaC relisible
Plan de rollback teste Si ce cadrage n’existe pas, la montée de version risque d’être validée sur l’absence de bruit, pas sur une preuve de compatibilité.
Mesurer le bruit de la nouvelle version en Detection
Avant Prevention, faites tourner la nouvelle version en Detection quand votre surface le permet. L’objectif n’est pas de tout rendre silencieux. Il est d’identifier les nouveaux blocages potentiels, leur volume, leur chemin et leur impact métier.
let Window = 7d;
let Hostname = "api.example.com";
AzureDiagnostics
| where TimeGenerated > ago(Window)
| where Category in ("ApplicationGatewayFirewallLog", "FrontDoorWebApplicationFirewallLog")
| extend hostname = tostring(host_s)
| extend uri = tostring(requestUri_s)
| extend action = tostring(action_s)
| extend ruleSet = tostring(ruleSetType_s)
| extend ruleSetVersion = tostring(ruleSetVersion_s)
| extend ruleId = tostring(ruleId_s)
| extend message = tostring(message_s)
| extend clientIp = tostring(clientIp_s)
| where hostname == Hostname
| where action in ("Matched", "Detected", "Blocked")
| summarize hits=count(),
clients=dcount(clientIp),
paths=make_set(split(uri, "?")[0], 10),
messages=make_set(message, 5),
firstSeen=min(TimeGenerated),
lastSeen=max(TimeGenerated)
by ruleSet, ruleSetVersion, ruleId, action
| order by hits desc Adaptez les noms de champs à vos tables de diagnostic. Le point important est de comparer la version, le ruleId, l’action et le chemin. Un ruleId très bruyant sur un endpoint non critique n’appelle pas la même décision qu’un ruleId moyen sur un paiement, un login ou un webhook partenaire.
Comparer les chemins critiques, pas seulement les ruleId
Une montée de version peut générer un nouveau ruleId sans impact réel, ou un faible nombre de matchs sur un parcours essentiel. Classez donc les signaux par chemin applicatif.
let Window = 7d;
let CriticalPaths = dynamic(["/auth/login", "/api/orders", "/api/payment", "/webhooks/partner"]);
AzureDiagnostics
| where TimeGenerated > ago(Window)
| where Category in ("ApplicationGatewayFirewallLog", "FrontDoorWebApplicationFirewallLog")
| extend uri = tostring(requestUri_s)
| extend path = tostring(split(uri, "?")[0])
| extend action = tostring(action_s)
| extend ruleId = tostring(ruleId_s)
| extend transactionId = tostring(transactionId_g)
| where path in (CriticalPaths)
| summarize wafEvents=count(),
blocked=countif(action == "Blocked"),
detected=countif(action in ("Detected", "Matched")),
rules=make_set(ruleId, 20),
transactions=make_set(transactionId, 10)
by path, bin(TimeGenerated, 1d)
| order by TimeGenerated asc, path asc Cette lecture évite une erreur classique : accepter une nouvelle version parce que le volume global est faible, alors que le bruit restant se concentre sur un seul parcours à fort impact.
Qualifier faux positif, attaque ou dette applicative
Chaque nouveau signal doit être qualifié. Une requête détectée peut être une attaque réelle, un faux positif, un payload applicatif fragile, ou une intégration qui envoie des formats inattendus. Le WAF ne doit pas devenir le lieu où l’on masque toutes les dettes d’entrée.
Attaque probable
RuleId coherent avec le payload observe
Source, user-agent ou frequence suspects
Aucun parcours legitime connu
Decision: garder Prevention ou renforcer la regle
Faux positif cible
Payload legitime confirme par l'application
RuleId et match variable identifies
Chemin, methode, hostname et parametre stables
Decision: exclusion minimale ou custom rule plus precise
Dette applicative
Payload valide fonctionnellement mais trop ambigu
Champ libre accepte du contenu dangereux sans encodage clair
Plusieurs ruleId se declenchent sur le meme design
Decision: corriger l'application ou isoler temporairement avec expiration
Signal insuffisant
Logs incomplets, transaction absente, chemin non rejoue
Decision: rester en Detection et collecter plus de preuves Une exclusion large créée pendant la montée de version peut coûter plus cher que le maintien temporaire en Detection. Réduisez le périmètre avant de réduire la protection.
Relier le diff de policy à une validation applicative
La PR doit montrer exactement ce qui change : version du ruleset, mode, exclusions, custom rules, priorités et hostnames affectés. Elle doit aussi contenir un test reproductible.
HOST="api.example.com"
BASE_URL="https://$HOST"
CORRELATION_ID="waf-rules-upgrade-$(date +%Y%m%d%H%M%S)"
curl -sk -o /tmp/login-response.txt -w "%{http_code}\n" "$BASE_URL/auth/login" -H "x-correlation-id: $CORRELATION_ID-login" -H "content-type: application/json" --data @representative-login.json
curl -sk -o /tmp/webhook-response.txt -w "%{http_code}\n" "$BASE_URL/webhooks/partner" -H "x-correlation-id: $CORRELATION_ID-webhook" -H "content-type: application/json" --data @representative-webhook.json
echo "correlation_id=$CORRELATION_ID" Le test doit être lu avec les logs WAF et les logs applicatifs. Une réponse 200 ne suffit pas si le WAF a seulement détecté un signal qui deviendra bloquant au passage en Prevention.
Décider Detection, Prevention, exception ou rollback
La décision doit être explicite et réversible. Elle doit dire pourquoi la version est acceptable, ce qui reste surveillé, et comment revenir à l’état précédent.
Passer en Prevention
Les parcours critiques ont ete rejoues
Les nouveaux ruleId sont compris
Les faux positifs sont absents ou traites par exclusions ciblees
Les controles negatifs restent detectes ou bloques
Le rollback de policy est simple et teste
Rester en Detection
Signaux nouveaux non qualifies
Logs WAF ou applicatifs incomplets
Parcours critique non rejoue
Exclusion encore trop large
Fenetre de validation trop courte
Ajouter une exception ciblee
RuleId, match variable, selector, host et path identifies
Payload legitime confirme
Expiration ou revue planifiee
Controle de non-regression conserve
Rollbacker
403 legitimes apres Prevention
Hausse d'erreurs applicatives correlee au changement
Perte de visibilite sur les ruleId
Exclusion trop large introduite en urgence
Ancienne policy connue comme saine Le passage en Prevention ne doit pas être un acte de foi. C’est une bascule de comportement qui mérite les mêmes preuves qu’un changement de routage ou d’identité.
Valider après bascule
Après activation, gardez une fenêtre courte de surveillance renforcée. Comparez les transactions WAF, les erreurs applicatives, les parcours synthétiques, les tickets support et les signaux de sécurité.
Validation service
Parcours critiques sans hausse de 403 legitimes
Taux d'erreur applicatif stable
Webhooks et integrations externes confirmes
Probes synthetiques vertes avec correlation ID
Validation securite
RuleId attendus encore visibles
Controles negatifs toujours detectes ou bloques
Exclusions limitees au champ prevu
Mode et priorites conformes au diff valide
Rollback pret
Commit ou version de policy precedente identifie
Commande de retour testee en environnement non critique
Owner de decision disponible pendant la fenetre
Preuves conservees pour revue post-change Si la validation n’est pas concluante, revenez à l’état précédent avant de multiplier les exclusions. Une policy WAF instable finit par devenir illisible.
Conclusion
Une montée de version Azure WAF réussie ne se mesure pas à l’absence d’alerte pendant quelques minutes. Elle se mesure à la capacité de l’équipe à expliquer les nouveaux ruleId, qualifier les faux positifs, rejouer les chemins critiques, garder les contrôles négatifs, puis activer Prevention avec un rollback prêt.
La bonne décision peut être de passer en Prevention, de prolonger Detection, de cibler une exclusion, de corriger l’application ou de rollbacker. Le point important est que la décision reste fondée sur des preuves, pas sur l’espoir qu’un ruleset plus récent sera automatiquement compatible avec la production.