Skip to content

Commit 7df6cc0

Browse files
Network - 26881 - Default Ruleset is enabled in Application Gateway WAF (#1005)
* initial commit * removed rule state check as per updated doc * code formatting * added default ruleset type check * resolved aleks comments
1 parent 8d7f173 commit 7df6cc0

2 files changed

Lines changed: 176 additions & 0 deletions

File tree

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
Azure Application Gateway Web Application Firewall (WAF) provides centralized protection for web applications through managed rulesets that contain pre-configured detection signatures for known attack patterns.
2+
3+
The Microsoft Default Ruleset and OWASP Core Rule Set are continuously updated managed rulesets that protect against the most common and dangerous web vulnerabilities without requiring security expertise to configure.
4+
5+
When no managed ruleset is enabled, the WAF policy provides no protection against known attack patterns, effectively operating as a pass-through despite being deployed.
6+
7+
Threat actors routinely scan for unprotected web applications and exploit well-documented vulnerabilities using automated toolkits; without managed rules, attackers can execute SQL injection to extract or modify database contents, perform cross-site scripting to hijack user sessions and steal credentials, exploit local file inclusion to read sensitive configuration files, and leverage command injection to gain shell access on backend servers.
8+
9+
These attack techniques have known signatures that managed rulesets detect and block, but an empty or disabled ruleset configuration means the WAF cannot recognize these patterns and will allow malicious requests to reach backend applications unimpeded.
10+
11+
12+
**Remediation action**
13+
14+
- [What is Azure Web Application Firewall on Azure Application Gateway?](https://learn.microsoft.com/en-us/azure/web-application-firewall/ag/ag-overview) - Overview of WAF capabilities on Application Gateway including managed rulesets
15+
- [Web Application Firewall CRS rule groups and rules](https://learn.microsoft.com/en-us/azure/web-application-firewall/ag/application-gateway-crs-rulegroups-rules) - Detailed documentation of available rulesets and rule groups
16+
- [Create Web Application Firewall policies for Application Gateway](https://learn.microsoft.com/en-us/azure/web-application-firewall/ag/create-waf-policy-ag) - Step-by-step guidance on creating and configuring WAF policies with managed rulesets
17+
18+
19+
<!--- Results --->
20+
%TestResult%
Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
<#
2+
.SYNOPSIS
3+
Validates that the default managed ruleset is enabled in Application Gateway WAF.
4+
5+
.DESCRIPTION
6+
This test checks if all Azure Application Gateway WAF policies attached to Application Gateways
7+
are enabled and running in Prevention mode, and have a default managed ruleset configured
8+
(ruleSetType of Microsoft_DefaultRuleSet or OWASP). A policy fails if it is disabled or
9+
running in Detection mode. Without an active WAF policy in Prevention mode, applications are
10+
left unprotected against common web attacks including SQL injection, cross-site scripting,
11+
and other OWASP Top 10 vulnerabilities.
12+
13+
.NOTES
14+
Test ID: 26881
15+
Category: Azure Network Security
16+
Required API: Azure Resource Graph - ApplicationGatewayWebApplicationFirewallPolicies
17+
#>
18+
19+
function Test-Assessment-26881 {
20+
[ZtTest(
21+
Category = 'Azure Network Security',
22+
ImplementationCost = 'Low',
23+
MinimumLicense = ('Azure WAF'),
24+
Pillar = 'Network',
25+
RiskLevel = 'High',
26+
SfiPillar = 'Protect networks',
27+
TenantType = ('Workforce'),
28+
TestId = 26881,
29+
Title = 'Default Ruleset is enabled in Application Gateway WAF',
30+
UserImpact = 'Low'
31+
)]
32+
[CmdletBinding()]
33+
param()
34+
35+
#region Data Collection
36+
Write-PSFMessage '🟦 Start' -Tag Test -Level VeryVerbose
37+
38+
$activity = 'Checking Application Gateway WAF default ruleset configuration'
39+
40+
# Check if connected to Azure
41+
Write-ZtProgress -Activity $activity -Status 'Checking Azure connection'
42+
43+
$azContext = Get-AzContext -ErrorAction SilentlyContinue
44+
if (-not $azContext) {
45+
Write-PSFMessage 'Not connected to Azure.' -Level Warning
46+
Add-ZtTestResultDetail -SkippedBecause NotConnectedAzure
47+
return
48+
}
49+
50+
Write-ZtProgress -Activity $activity -Status 'Querying Azure Resource Graph'
51+
52+
# Query all Application Gateway WAF policies attached to Application Gateways using Azure Resource Graph
53+
$argQuery = @"
54+
resources
55+
| where type =~ 'microsoft.network/applicationgatewaywebapplicationfirewallpolicies'
56+
| where coalesce(array_length(properties.applicationGateways), 0) >= 1
57+
| join kind=leftouter (
58+
resourcecontainers
59+
| where type =~ 'microsoft.resources/subscriptions'
60+
| project subscriptionName=name, subscriptionId)
61+
on subscriptionId
62+
| project
63+
PolicyName = name,
64+
PolicyId = id,
65+
SubscriptionName = subscriptionName,
66+
SubscriptionId = subscriptionId,
67+
EnabledState = tostring(properties.policySettings.state),
68+
Mode = tostring(properties.policySettings.mode),
69+
ManagedRuleSets = properties.managedRules.managedRuleSets
70+
"@
71+
72+
$policies = @()
73+
try {
74+
$policies = @(Invoke-ZtAzureResourceGraphRequest -Query $argQuery)
75+
Write-PSFMessage "ARG Query returned $($policies.Count) records" -Tag Test -Level VeryVerbose
76+
}
77+
catch {
78+
Write-PSFMessage "Azure Resource Graph query failed: $($_.Exception.Message)" -Tag Test -Level Warning
79+
Add-ZtTestResultDetail -SkippedBecause NotSupported
80+
return
81+
}
82+
#endregion Data Collection
83+
84+
#region Assessment Logic
85+
$passed = $false
86+
87+
# Skip test if no policies found
88+
if ($policies.Count -eq 0) {
89+
Write-PSFMessage 'No Application Gateway WAF policies found attached to Application Gateways.' -Tag Test -Level Verbose
90+
Add-ZtTestResultDetail -SkippedBecause NotApplicable -Result 'No Application Gateway WAF policies found attached to Application Gateways.'
91+
return
92+
}
93+
94+
# Fail if any policy is not enabled, not in Prevention mode, or missing a default managed ruleset
95+
$failingPolicies = $policies | Where-Object {
96+
$_.EnabledState -ne 'Enabled' -or
97+
$_.Mode -ne 'Prevention' -or
98+
($_.ManagedRuleSets | Where-Object { $_.ruleSetType -eq 'Microsoft_DefaultRuleSet' -or $_.ruleSetType -eq 'OWASP' }).Count -eq 0
99+
}
100+
101+
$passed = $failingPolicies.Count -eq 0
102+
103+
if ($passed) {
104+
$testResultMarkdown = "✅ All Application Gateway WAF policies attached to Application Gateways are enabled, running in Prevention mode, and have a Default Ruleset (Microsoft_DefaultRuleSet or OWASP) assigned.`n`n%TestResult%"
105+
}
106+
else {
107+
$testResultMarkdown = "❌ One or more Application Gateway WAF policies attached to Application Gateways are disabled or running in Detection mode, leaving applications vulnerable to common web exploits and OWASP Top 10 attacks.`n`n%TestResult%"
108+
}
109+
#endregion Assessment Logic
110+
111+
#region Report Generation
112+
$mdInfo = ''
113+
114+
$reportTitle = 'Application Gateway WAF policies'
115+
$portalLink = 'https://portal.azure.com/#browse/Microsoft.Network%2FapplicationGatewayWebApplicationFirewallPolicies'
116+
117+
$tableRows = ''
118+
foreach ($policy in $policies | Sort-Object SubscriptionName, PolicyName) {
119+
$policyLink = "https://portal.azure.com/#resource$($policy.PolicyId)"
120+
$subLink = "https://portal.azure.com/#resource/subscriptions/$($policy.SubscriptionId)"
121+
$policyMd = "[$(Get-SafeMarkdown $policy.PolicyName)]($policyLink)"
122+
$subMd = "[$(Get-SafeMarkdown $policy.SubscriptionName)]($subLink)"
123+
124+
$defaultRuleSet = $policy.ManagedRuleSets | Where-Object { $_.ruleSetType -eq 'Microsoft_DefaultRuleSet' -or $_.ruleSetType -eq 'OWASP' }
125+
$enabledStateDisplay = if ($policy.EnabledState -eq 'Enabled') { '✅ Enabled' } else { '❌ Disabled' }
126+
$modeDisplay = if ($policy.Mode -eq 'Prevention') { '✅ Prevention' } else { '❌ Detection' }
127+
$defaultRuleSetType = $defaultRuleSet.ruleSetType
128+
$versionDisplay = if ($defaultRuleSet.ruleSetVersion) { $defaultRuleSet.ruleSetVersion } else { 'N/A' }
129+
$statusDisplay = if ($policy.EnabledState -eq 'Enabled' -and $policy.Mode -eq 'Prevention' -and $defaultRuleSet) { '' } else { '' }
130+
131+
$tableRows += "| $policyMd | $subMd | $enabledStateDisplay | $modeDisplay | $defaultRuleSetType | $versionDisplay | $statusDisplay |`n"
132+
}
133+
134+
$formatTemplate = @'
135+
136+
## [{0}]({1})
137+
138+
| Policy name | Subscription name | Policy state | Mode | Default ruleset type | Ruleset version | Status |
139+
| :---------- | :---------------- | :----------- | :--- | :------------------- | :-------------- | :----- |
140+
{2}
141+
142+
'@
143+
144+
$mdInfo = $formatTemplate -f $reportTitle, $portalLink, $tableRows
145+
$testResultMarkdown = $testResultMarkdown -replace '%TestResult%', $mdInfo
146+
#endregion Report Generation
147+
148+
$params = @{
149+
TestId = '26881'
150+
Title = 'Default Ruleset is enabled in Application Gateway WAF'
151+
Status = $passed
152+
Result = $testResultMarkdown
153+
}
154+
155+
Add-ZtTestResultDetail @params
156+
}

0 commit comments

Comments
 (0)