Skip to content

Commit fb58e39

Browse files
authored
Network - 27024 - HTTP DDoS protection rule set is enabled in Azure Front Door WAF (#1448)
2 parents ddf5f32 + e886006 commit fb58e39

2 files changed

Lines changed: 182 additions & 0 deletions

File tree

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
Azure Front Door Web Application Firewall (WAF) offers the Microsoft HTTP DDoS ruleset, a managed rule set that provides automated layer 7 protection against volumetric HTTP-based attacks at Microsoft's global edge network. Threat actors increasingly bypass network-layer DDoS defenses by generating HTTP floods, slowloris-style connection exhaustion, and high-frequency requests from distributed botnets that resemble legitimate traffic just enough to defeat static IP allow/block lists and fixed-threshold rate limiting rules. The HTTP DDoS ruleset closes this gap by continuously baselining normal request volume for each Azure Front Door profile and learning both a global profile-level threshold and a per-client-IP threshold; once a profile-wide surge indicates an attack, the ruleset throttles the specific IP addresses driving the anomaly without requiring administrators to pre-configure static limits. The ruleset's two rules — 500100, which detects anomalous request rates across the profile, and 500110, which applies stricter thresholds to traffic that Microsoft Threat Intelligence classifies as bot activity — are evaluated before any custom rules or other managed rule sets, so volumetric abuse is throttled at the edge before it can exhaust origin compute, database connections, or application threads. Without this ruleset enabled, an attacker can sustain a high-rate HTTP flood or coordinated bot swarm against an Azure Front Door-fronted application until backend capacity is exhausted, denying service to legitimate users, because the fixed-threshold controls available elsewhere in the WAF policy do not adapt to attack conditions in real time.
2+
3+
**Remediation action**
4+
5+
- [HTTP DDoS Ruleset (Preview) - Front Door WAF](https://learn.microsoft.com/en-us/azure/web-application-firewall/afds/http-ddos-ruleset)
6+
- [What is Azure Web Application Firewall on Azure Front Door?](https://learn.microsoft.com/en-us/azure/web-application-firewall/afds/afds-overview)
7+
- [Create a Web Application Firewall policy for Azure Front Door using the Azure portal](https://learn.microsoft.com/en-us/azure/web-application-firewall/afds/waf-front-door-create-portal)
8+
- [Azure DDoS Protection overview](https://learn.microsoft.com/en-us/azure/ddos-protection/ddos-protection-overview)
9+
10+
<!--- Results --->
11+
%TestResult%
Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
<#
2+
.SYNOPSIS
3+
Validates that the HTTP DDoS protection rule set is enabled in Azure Front Door WAF.
4+
5+
.DESCRIPTION
6+
This test queries Azure Resource Graph for Azure Front Door Premium WAF policies that are attached to an Azure Front Door and evaluates whether the Microsoft_HTTPDDoSRuleSet is configured and has at least one of its rules enabled.
7+
8+
.NOTES
9+
Test ID: 27024
10+
Category: Azure Network Security
11+
Required API: Azure Resource Graph - FrontDoorWebApplicationFirewallPolicies
12+
#>
13+
14+
function Test-Assessment-27024 {
15+
[ZtTest(
16+
Category = 'Azure Network Security',
17+
ImplementationCost = 'Low',
18+
MinimumLicense = ('Consumption-based: Azure WAF on Azure Front Door Premium'),
19+
Service = ('Azure'),
20+
Pillar = 'Network',
21+
RiskLevel = 'High',
22+
SfiPillar = 'Protect networks',
23+
TenantType = ('Workforce'),
24+
TestId = 27024,
25+
Title = 'HTTP DDoS protection rule set is enabled in Azure Front Door WAF',
26+
UserImpact = 'Low'
27+
)]
28+
[CmdletBinding()]
29+
param()
30+
31+
#region Data Collection
32+
Write-PSFMessage '🟦 Start' -Tag Test -Level VeryVerbose
33+
34+
$activity = 'Evaluating Azure Front Door WAF HTTP DDoS protection configuration'
35+
Write-ZtProgress -Activity $activity -Status 'Querying Azure Front Door WAF policies'
36+
37+
# Q1: Query attached Premium Azure Front Door WAF policies and their managed rule sets.
38+
$argQuery = @"
39+
resources
40+
| where type =~ 'microsoft.network/frontdoorwebapplicationfirewallpolicies'
41+
| where tostring(sku.name) =~ 'Premium_AzureFrontDoor'
42+
| where array_length(properties.frontendEndpointLinks) > 0 or array_length(properties.securityPolicyLinks) > 0
43+
| join kind=leftouter (
44+
resourcecontainers
45+
| where type =~ 'microsoft.resources/subscriptions'
46+
| project subscriptionId, SubscriptionName = name
47+
) on subscriptionId
48+
| project
49+
PolicyName = name,
50+
PolicyId = id,
51+
SubscriptionName,
52+
SubscriptionId = subscriptionId,
53+
EnabledState = tostring(properties.policySettings.enabledState),
54+
WafMode = tostring(properties.policySettings.mode),
55+
ManagedRuleSets = properties.managedRules.managedRuleSets
56+
"@
57+
58+
$rawPolicies = @()
59+
try {
60+
$rawPolicies = @(Invoke-ZtAzureResourceGraphRequest -Query $argQuery | Where-Object { $null -ne $_ })
61+
Write-PSFMessage "ARG query returned $($rawPolicies.Count) Azure Front Door Premium WAF policy(ies)." -Tag Test -Level VeryVerbose
62+
}
63+
catch {
64+
Write-PSFMessage "Azure Resource Graph query failed: $($_.Exception.Message)" -Tag Test -Level Warning
65+
Add-ZtTestResultDetail -SkippedBecause NotSupported
66+
return
67+
}
68+
#endregion Data Collection
69+
70+
#region Assessment Logic
71+
if ($rawPolicies.Count -eq 0) {
72+
Write-PSFMessage 'No attached Azure Front Door Premium WAF policies found.' -Tag Test -Level Verbose
73+
Add-ZtTestResultDetail -SkippedBecause NotApplicable -Result 'No attached Azure Front Door Premium WAF policies found.'
74+
return
75+
}
76+
77+
$policies = foreach ($policy in $rawPolicies) {
78+
$httpDdosRuleSet = @($policy.ManagedRuleSets | Where-Object { $_.ruleSetType -eq 'Microsoft_HTTPDDoSRuleSet' } | Select-Object -First 1)
79+
$hasHttpDdosRuleSet = $httpDdosRuleSet.Count -gt 0
80+
$ruleOverrides = @()
81+
82+
if ($hasHttpDdosRuleSet) {
83+
# Unlisted rules retain their default enabled state, so both documented rules must be explicitly disabled.
84+
foreach ($ruleGroupOverride in @($httpDdosRuleSet[0].ruleGroupOverrides)) {
85+
$ruleOverrides += @(@($ruleGroupOverride.rules) | Where-Object { $null -ne $_ })
86+
}
87+
}
88+
89+
$disabledRuleIds = @($ruleOverrides | Where-Object {
90+
$_.ruleId -in @('500100', '500110') -and $_.enabledState -eq 'Disabled'
91+
} | Select-Object -ExpandProperty ruleId -Unique)
92+
$bothHttpDdosRulesDisabled = $disabledRuleIds.Count -eq 2
93+
94+
$httpDdosRulesetState = if (-not $hasHttpDdosRuleSet) {
95+
'Not Configured'
96+
}
97+
elseif ($bothHttpDdosRulesDisabled) {
98+
'Disabled'
99+
}
100+
else {
101+
'Enabled'
102+
}
103+
104+
$isCompliant = $policy.EnabledState -eq 'Enabled' -and
105+
$policy.WafMode -eq 'Prevention' -and
106+
$httpDdosRulesetState -eq 'Enabled'
107+
108+
[PSCustomObject]@{
109+
PolicyName = $policy.PolicyName
110+
PolicyId = $policy.PolicyId
111+
SubscriptionName = $policy.SubscriptionName
112+
SubscriptionId = $policy.SubscriptionId
113+
EnabledState = $policy.EnabledState
114+
WafMode = $policy.WafMode
115+
HttpDdosRulesetState = $httpDdosRulesetState
116+
HttpDdosRulesetVersion = if ($hasHttpDdosRuleSet) { $httpDdosRuleSet[0].ruleSetVersion } else { $null }
117+
IsCompliant = $isCompliant
118+
}
119+
}
120+
121+
$failedItems = @($policies | Where-Object { -not $_.IsCompliant })
122+
$passed = $failedItems.Count -eq 0
123+
124+
if ($passed) {
125+
$testResultMarkdown = "✅ All Azure Front Door Premium WAF policies attached to Azure Front Door are enabled, running in Prevention mode, and have the HTTP DDoS ruleset (Microsoft_HTTPDDoSRuleSet) with at least one rule enabled.`n`n%TestResult%"
126+
}
127+
else {
128+
$testResultMarkdown = "❌ One or more Azure Front Door Premium WAF policies attached to Azure Front Door are disabled, running in Detection mode, do not have the HTTP DDoS ruleset configured, or have all HTTP DDoS ruleset rules disabled, leaving applications vulnerable to volumetric HTTP-based attacks at the edge.`n`n%TestResult%"
129+
}
130+
#endregion Assessment Logic
131+
132+
#region Report Generation
133+
$portalWafBrowseLink = 'https://portal.azure.com/#browse/Microsoft.Network%2FfrontdoorWebApplicationFirewallPolicies'
134+
$portalResourceBaseLink = 'https://portal.azure.com/#resource'
135+
$portalSubscriptionBaseLink = 'https://portal.azure.com/#resource/subscriptions'
136+
$reportTitle = 'Azure Front Door WAF policies'
137+
138+
$tableRows = ''
139+
foreach ($policy in ($policies | Sort-Object SubscriptionName, PolicyName)) {
140+
$policyLink = "[$(Get-SafeMarkdown $policy.PolicyName)]($portalResourceBaseLink$($policy.PolicyId))"
141+
$subscriptionLink = "[$(Get-SafeMarkdown $policy.SubscriptionName)]($portalSubscriptionBaseLink/$($policy.SubscriptionId)/overview)"
142+
$enabledStateDisplay = if ($policy.EnabledState -eq 'Enabled') { '✅ Enabled' } else { '❌ Disabled' }
143+
$wafModeDisplay = if ($policy.WafMode -eq 'Prevention') { '✅ Prevention' } else { "$($policy.WafMode)" }
144+
$httpDdosRulesetDisplay = if ($policy.HttpDdosRulesetState -eq 'Enabled') { '✅ Enabled' } elseif ($policy.HttpDdosRulesetState -eq 'Disabled') { '❌ Disabled' } else { '❌ Not Configured' }
145+
$rulesetVersionDisplay = if ($policy.HttpDdosRulesetVersion) { $policy.HttpDdosRulesetVersion } else { 'N/A' }
146+
$statusDisplay = if ($policy.IsCompliant) { '✅ Pass' } else { '❌ Fail' }
147+
148+
$tableRows += "| $policyLink | $subscriptionLink | $enabledStateDisplay | $wafModeDisplay | $httpDdosRulesetDisplay | $rulesetVersionDisplay | $statusDisplay |`n"
149+
}
150+
151+
$formatTemplate = @'
152+
## [{0}]({1})
153+
154+
| Policy name | Subscription name | Enabled state | WAF mode | HTTP DDoS ruleset | Ruleset version | Status |
155+
| :---------- | :---------------- | :------------ | :------- | :---------------- | :-------------- | :----- |
156+
{2}
157+
'@
158+
159+
$mdInfo = $formatTemplate -f $reportTitle, $portalWafBrowseLink, $tableRows
160+
$testResultMarkdown = $testResultMarkdown -replace '%TestResult%', $mdInfo
161+
#endregion Report Generation
162+
163+
$params = @{
164+
TestId = '27024'
165+
Title = 'HTTP DDoS protection rule set is enabled in Azure Front Door WAF'
166+
Status = $passed
167+
Result = $testResultMarkdown
168+
}
169+
170+
Add-ZtTestResultDetail @params
171+
}

0 commit comments

Comments
 (0)