Mettre à niveau la version de l’ensemble de règles CRS ou DRS

S’applique à : ✔️ Application Gateway V2

L’ensemble de règles par défaut géré par Azure dans Azure Application Gateway Web Application Firewall (WAF) protège les applications web contre les vulnérabilités et les attaques courantes, y compris les 10 principaux types d’attaques OWASP. L’ensemble de règles par défaut incorpore également les règles de collecte Microsoft Threat Intelligence. Exécutez toujours la dernière version de l’ensemble de règles, qui inclut les mises à jour de sécurité les plus récentes, les améliorations des règles et les correctifs.

Le jeu de règles par défaut géré par Azure (DRS) est la dernière génération d’ensembles de règles dans Azure WAF, en remplaçant toutes les versions précédentes de l’ensemble de règles de base (CRS). Parmi les versions de DRS, utilisez toujours la version la plus élevée disponible (DRS 2.2) pour vous assurer que vous disposez des protections les plus up-to-date.

Cet article fournit des exemples PowerShell pour mettre à niveau votre stratégie WAF Azure vers DRS 2.2 à partir de CRS 3.0, CRS 3.1, CRS 3.2 ou DRS 2.1.

Note

Les extraits de code PowerShell sont des exemples uniquement. Remplacez tous les espaces réservés par des valeurs de votre environnement.

Prerequisites

Considérations clés lors de la mise à niveau

Lors de la mise à niveau de votre version de l’ensemble de règles Azure WAF, veillez à :

  • Conservez les personnalisations existantes : conserves vos remplacements d’action de règle, vos remplacements d’état de règle (activé ou désactivé) ainsi que les exclusions.

  • Supprimer les personnalisations des règles supprimées : n’effectuez pas de remplacements ou d’exclusions pour les règles qui n’existent plus dans DRS 2.2. Le report d’un remplacement pour une règle que DRS 2.2 ne contient pas fait échouer la mise à jour de la stratégie avec une erreur telle que The override Rule '<id>' is unknown for RuleGroup '<group>'.

  • Tenez compte de la valeur de référence du niveau de paranoïa : DRS 2.2 fonctionne par défaut au niveau de paranoïa 1 (PL1), et toutes les règles PL2 sont désactivées par défaut. Dans CRS 3.2 et DRS 2.1, les règles PL2 étaient actives. Toutes les règles PL2 que vous avez précédemment personnalisées sont désactivées par défaut dans DRS 2.2 jusqu’à ce que vous les réactivez explicitement.

  • Validez les nouvelles règles en toute sécurité : les nouvelles règles activées par défaut (PL1) sont initialement définies sur le mode journal. Vous pouvez donc surveiller leur impact et les ajuster avant d’activer le blocage.

Préparer votre environnement et vos variables

  1. Définissez le contexte de votre abonnement, groupe de ressources et stratégie WAF Azure sélectionnés.

    Import-Module Az.Network
    Set-AzContext -SubscriptionId "<subscription_id>"
    $resourceGroupName = "<resource_group>"
    $wafPolicyName = "<policy_name>"
    
  2. Obtenez l’objet de stratégie WAF et récupérez ses définitions. Le jeu de règles géré actuel peut être de type CRS (OWASP) ou DRS (Microsoft_DefaultRuleSet).

    $wafPolicy = Get-AzApplicationGatewayFirewallPolicy `
        -Name $wafPolicyName `
        -ResourceGroupName $resourceGroupName
    
    $currentExclusions = $wafPolicy.ManagedRules.Exclusions
    $currentManagedRuleset = $wafPolicy.ManagedRules.ManagedRuleSets |
        Where-Object { $_.RuleSetType -eq "OWASP" -or $_.RuleSetType -eq "Microsoft_DefaultRuleSet" }
    $currentVersion = $currentManagedRuleset.RuleSetVersion
    

Conserver les personnalisations existantes

  1. Ne reportez une dérogation ou une exclusion que si la règle existe toujours dans DRS 2.2. La fonction suivante valide un ID de règle par rapport à l’ensemble complet de règles DRS 2.2 et retourne $true pour toute règle supprimée (y compris les règles héritées et inactives telles que 920460, 942130et 920250). L’utilisation d’une liste d’autorisation d’identifiants de règles valides évite d’avoir à effectuer une maintenance règle par règle et empêche l’échec de la mise à jour de la politique en raison d’une règle inconnue.

    function Test-RuleIsRemovedFromDRS22 {
        param (
            [string]$RuleId,
            [string]$CurrentRulesetVersion  # Retained for compatibility; not used
        )
    
        # Complete set of rule IDs that exist in DRS 2.2.
        # Any override or exclusion for a rule NOT in this set is dropped during migration.
        $drs22RuleIds = @(
            "200002","200003",
            "911100",
            "920100","920120","920121","920160","920170","920171","920180","920181","920190","920200","920201","920210","920220","920230","920240","920260","920270","920271","920280","920290","920300","920310","920311","920320","920330","920340","920341","920350","920420","920430","920440","920450","920470","920480","920500","920530","920620",
            "921110","921120","921130","921140","921150","921151","921160","921190","921200","921422",
            "930100","930110","930120","930130",
            "931100","931110","931120","931130",
            "932100","932105","932110","932115","932120","932130","932140","932150","932160","932170","932171","932180",
            "933100","933110","933120","933130","933140","933150","933151","933160","933170","933180","933200","933210",
            "934100",
            "941100","941101","941110","941120","941130","941140","941150","941160","941170","941180","941190","941200","941210","941220","941230","941240","941250","941260","941270","941280","941290","941300","941310","941320","941330","941340","941350","941360","941370","941380",
            "942100","942110","942120","942140","942150","942160","942170","942180","942190","942200","942210","942220","942230","942240","942250","942260","942270","942280","942290","942300","942310","942320","942330","942340","942350","942360","942361","942370","942380","942390","942400","942410","942430","942440","942450","942470","942480","942500","942510",
            "943100","943110","943120",
            "944100","944110","944120","944130","944200","944210","944240","944250",
            "99005002","99005003","99005004","99005005","99005006",
            "99030001","99030002","99030003","99030004","99030005","99030006",
            "99031001","99031002","99031003","99031004","99031005","99031006",
            "99001001","99001002","99001003","99001004","99001005","99001006","99001007","99001008","99001009","99001010","99001011","99001012","99001013","99001014","99001015","99001016","99001017","99001018",
            "99032001","99032002"
        )
    
        return -not ($drs22RuleIds -contains $RuleId)
    }
    
  2. Lors de la création d’objets de remplacement, utilisez les noms de groupe DRS 2.2. La fonction suivante associe les anciens noms de groupes CRS aux groupes DRS. Les noms de groupes sources DRS qui ne se trouvent pas dans la carte (par exemple, lors de la mise à niveau à partir de DRS 2.1) sont retournés inchangés :

    function Get-DrsRuleGroupName {
        param (
            [Parameter(Mandatory = $true)]
            [string]$SourceGroupName
        )
        $groupMap = @{
            "REQUEST-930-APPLICATION-ATTACK-LFI"             = "LFI"
            "REQUEST-931-APPLICATION-ATTACK-RFI"             = "RFI"
            "REQUEST-932-APPLICATION-ATTACK-RCE"             = "RCE"
            "REQUEST-933-APPLICATION-ATTACK-PHP"             = "PHP"
            "REQUEST-941-APPLICATION-ATTACK-XSS"             = "XSS"
            "REQUEST-942-APPLICATION-ATTACK-SQLI"            = "SQLI"
            "REQUEST-943-APPLICATION-ATTACK-SESSION-FIXATION" = "FIX"
            "REQUEST-944-APPLICATION-ATTACK-JAVA"            = "JAVA"
            "REQUEST-921-PROTOCOL-ATTACK"                    = "PROTOCOL-ATTACK"
            "REQUEST-911-METHOD-ENFORCEMENT"                 = "METHOD-ENFORCEMENT"
            "REQUEST-920-PROTOCOL-ENFORCEMENT"               = "PROTOCOL-ENFORCEMENT"
            "REQUEST-913-SCANNER-DETECTION"                  = $null  # No direct mapping
            "Known-CVEs"                                     = "MS-ThreatIntel-CVEs"
            "General"                                        = "General"
        }
        if ($groupMap.ContainsKey($SourceGroupName)) {
            return $groupMap[$SourceGroupName]
        } else {
            return $SourceGroupName  # No known mapping; pass through (DRS source group names)
        }
    }
    
  3. Utilisez le code PowerShell suivant pour définir les remplacements des règles, dupliquer les remplacements à partir de la version existante de l’ensemble de règles :

    $groupOverrides = @()
    foreach ($group in $currentManagedRuleset.RuleGroupOverrides) {
        $mappedGroupName = Get-DrsRuleGroupName $group.RuleGroupName
        if (-not $mappedGroupName) { continue }  # Skip groups with no DRS equivalent
        foreach ($existingRule in $group.Rules) {
            if (-not (Test-RuleIsRemovedFromDRS22 $existingRule.RuleId $currentVersion)) {
                $existingGroup = $groupOverrides | Where-Object { $_.RuleGroupName -eq $mappedGroupName }
                if ($existingGroup) {
                    if (-not ($existingGroup.Rules | Where-Object { $_.RuleId -eq $existingRule.RuleId })) {
                        $existingGroup.Rules.Add($existingRule)
                    }
                } else {
                    $newGroup = New-AzApplicationGatewayFirewallPolicyManagedRuleGroupOverride `
                        -RuleGroupName $mappedGroupName `
                        -Rule @($existingRule)
                    $groupOverrides += $newGroup
                }
            }
        }
    }
    
  4. Utilisez le code PowerShell suivant pour dupliquer vos exclusions existantes et les appliquer à DRS 2.2 :

    # Create new exclusion objects
    $newRuleSetExclusions = @()
    
    if ($currentExclusions -ne $null -and $currentExclusions.Count -gt 0) {
        foreach ($exclusion in $currentExclusions) {
            $newExclusion = New-AzApplicationGatewayFirewallPolicyExclusion `
                -MatchVariable $exclusion.MatchVariable `
                -SelectorMatchOperator $exclusion.SelectorMatchOperator `
                -Selector $exclusion.Selector
    
            # Migrate scopes: RuleSet, RuleGroup, or individual Rules
            if ($exclusion.ExclusionManagedRuleSets) {
                foreach ($scope in $exclusion.ExclusionManagedRuleSets) {
                    # Create RuleGroup objects from existing RuleGroups
                    $ruleGroups = @()
                    foreach ($group in $scope.RuleGroups) {
                        $drsGroupName = Get-DrsRuleGroupName $group.RuleGroupName
                        if ($drsGroupName) {
                            $exclusionRules = @()
                            foreach ($rule in $group.Rules) {
                                if (-not (Test-RuleIsRemovedFromDRS22 $rule.RuleId $currentVersion)) {
                                    $exclusionRules += New-AzApplicationGatewayFirewallPolicyExclusionManagedRule `
                                        -RuleId $rule.RuleId
                                }
                            }
                            if ($exclusionRules -ne $null -and $exclusionRules.Count -gt 0) {
                                $ruleGroups += New-AzApplicationGatewayFirewallPolicyExclusionManagedRuleGroup `
                                    -Name $drsGroupName `
                                    -Rule $exclusionRules
                            } else {
                                $ruleGroups += New-AzApplicationGatewayFirewallPolicyExclusionManagedRuleGroup `
                                    -Name $drsGroupName
                            }
                        }
                    }
    
                    # Create the ManagedRuleSet scope object with the updated RuleGroups
                    if ($ruleGroups.Count -gt 0) {
                        $newRuleSetScope = New-AzApplicationGatewayFirewallPolicyExclusionManagedRuleSet `
                            -Type "Microsoft_DefaultRuleSet" `
                            -Version "2.2" `
                            -RuleGroup $ruleGroups
    
                        # Add to the new exclusion object
                        $newExclusion.ExclusionManagedRuleSets += $newRuleSetScope
                    }
                }
            }
    
            if (-not $newExclusion.ExclusionManagedRuleSets) {
                $newExclusion.ExclusionManagedRuleSets = @()
            }
    
            $newRuleSetExclusions += $newExclusion
        }
    }
    

Valider les nouvelles règles en toute sécurité

Lorsque vous effectuez une mise à niveau, les nouvelles règles DRS 2.2 qui appartiennent à Paranoia Level 1 sont activées par défaut. Si votre WAF est en mode Prévention, définissez d’abord ces nouvelles règles en mode journalisation afin de pouvoir examiner les journaux avant d’activer le blocage.

Les règles qui appartiennent à Paranoia Level 2 sont désactivées par défaut dans DRS 2.2 et ne bloquent pas le trafic, de sorte qu’elles ne nécessitent pas cette étape. Si vous souhaitez utiliser le Niveau de paranoïa 2, activez explicitement les règles PL2 pertinentes et suivez la même approche de validation dans le journal.

  1. Utilisez la définition qui correspond à la version à partir de laquelle vous effectuez la mise à niveau. Chaque définition répertorie les règles introduites et activées par défaut dans DRS 2.2 par rapport à cette version.

    # Added and enabled by default in DRS 2.2 compared to CRS 3.0
    $rulesAddedInThisVersionByGroup = @{
        "General"              = @("200002", "200003")
        "PROTOCOL-ENFORCEMENT" = @("920171", "920181", "920470", "920480", "920500", "920530", "920620")
        "PROTOCOL-ATTACK"      = @("921190", "921200")
        "RCE"                  = @("932180")
        "PHP"                  = @("933200", "933210")
        "NODEJS"               = @("934100")
        "XSS"                  = @("941360", "941370")
        "SQLI"                 = @("942500")
        "JAVA"                 = @("944100", "944110", "944120", "944130")
        "MS-ThreatIntel-CVEs"  = @("99001018")
        "MS-ThreatIntel-XSS"   = @("99032001")
    }
    
    # Added and enabled by default in DRS 2.2 compared to CRS 3.1
    $rulesAddedInThisVersionByGroup = @{
        "General"              = @("200002", "200003")
        "PROTOCOL-ENFORCEMENT" = @("920181", "920500", "920530", "920620")
        "PROTOCOL-ATTACK"      = @("921190", "921200")
        "PHP"                  = @("933200", "933210")
        "NODEJS"               = @("934100")
        "XSS"                  = @("941360", "941370")
        "SQLI"                 = @("942500")
        "MS-ThreatIntel-CVEs"  = @("99001018")
        "MS-ThreatIntel-XSS"   = @("99032001")
    }
    
    # Added and enabled by default in DRS 2.2 compared to CRS 3.2
    $rulesAddedInThisVersionByGroup = @{
        "PROTOCOL-ENFORCEMENT" = @("920181", "920500", "920530", "920620")
        "PROTOCOL-ATTACK"      = @("921190", "921200")
        "NODEJS"               = @("934100")
        "XSS"                  = @("941370")
        "MS-ThreatIntel-CVEs"  = @("99001018")
        "MS-ThreatIntel-XSS"   = @("99032001")
    }
    
    # Added and enabled by default in DRS 2.2 compared to DRS 2.1
    $rulesAddedInThisVersionByGroup = @{
        "PROTOCOL-ENFORCEMENT" = @("920530", "920620")
        "MS-ThreatIntel-XSS"   = @("99032001")
    }
    
  2. Utilisez le code PowerShell suivant pour ajouter les dérogations des nouvelles règles à l’objet existant $groupOverrides défini précédemment :

    foreach ($groupName in $rulesAddedInThisVersionByGroup.Keys) {
        $ruleOverrides = @()
        foreach ($ruleId in $rulesAddedInThisVersionByGroup[$groupName]) {
            $existingGroup = $groupOverrides | Where-Object { $_.RuleGroupName -eq $groupName }
            $alreadyExists = $false
            if ($existingGroup) {
                $alreadyExists = $existingGroup.Rules | Where-Object { $_.RuleId -eq $ruleId }
            }
            if (-not $alreadyExists) {
                $ruleOverrides += New-AzApplicationGatewayFirewallPolicyManagedRuleOverride `
                    -RuleId $ruleId `
                    -Action "Log" `
                    -State "Enabled"
            }
        }
        # Only create or update the group override if we added rules to it
        if ($ruleOverrides.Count -gt 0) {
            $existingGroup = $groupOverrides | Where-Object { $_.RuleGroupName -eq $groupName }
            if ($existingGroup) {
                foreach ($ruleOverride in $ruleOverrides) {
                    $existingGroup.Rules.Add($ruleOverride)
                }
            } else {
                $groupOverrides += New-AzApplicationGatewayFirewallPolicyManagedRuleGroupOverride `
                    -RuleGroupName $groupName `
                    -Rule $ruleOverrides
            }
        }
    }
    

Appliquer des personnalisations et une mise à niveau

Définissez votre objet de stratégie Azure WAF mis à jour en y intégrant les remplacements de règles et les exclusions dupliqués et mis à jour :

$managedRuleSet = New-AzApplicationGatewayFirewallPolicyManagedRuleSet `
    -RuleSetType "Microsoft_DefaultRuleSet" `
    -RuleSetVersion "2.2" `
    -RuleGroupOverride $groupOverrides

# Replace the existing CRS (OWASP) or DRS (Microsoft_DefaultRuleSet) managed rule set
for ($i = 0; $i -lt $wafPolicy.ManagedRules.ManagedRuleSets.Count; $i++) {
    if ($wafPolicy.ManagedRules.ManagedRuleSets[$i].RuleSetType -eq "OWASP" -or
        $wafPolicy.ManagedRules.ManagedRuleSets[$i].RuleSetType -eq "Microsoft_DefaultRuleSet") {
        $wafPolicy.ManagedRules.ManagedRuleSets[$i] = $managedRuleSet
        break
    }
}

# Assign the migrated exclusions to the policy
$wafPolicy.ManagedRules.Exclusions = $newRuleSetExclusions

# Apply the updated WAF policy
Set-AzApplicationGatewayFirewallPolicy -InputObject $wafPolicy