- Introduction
- AWS WAF Architecture and Core Components
- OWASP Top 10 Protection Implementation
- Advanced Rule Customization and Tuning
- Monitoring and Alerting Implementation
- Conclusion
Introduction
Web application attacks continue to evolve at an unprecedented pace, with automated tools making it easier than ever for attackers to exploit common vulnerabilities. According to recent industry research, 94% of applications have at least one high-severity security flaw, and web application attacks account for over 43% of all data breaches in 2024.
Traditional approaches using nginx and ModSecurity, while effective, require significant infrastructure management, patching, and scaling considerations. AWS Web Application Firewall (WAF) integrated with CloudFront provides a cloud-native solution that addresses these challenges while offering superior performance, automatic scaling, and reduced operational overhead.
This comprehensive guide demonstrates how to implement enterprise-grade application protection using AWS WAF and CloudFront to defend against SQL injection, cross-site scripting (XSS), and the complete OWASP Top 10 vulnerability categories.
Current Landscape Statistics
- 94% of applications contain at least one high-severity security vulnerability (Veracode, 2024)
- 43% of data breaches involve web application attacks (Verizon DBIR, 2024)
- $4.88M average cost of a data breach involving web applications (IBM, 2024)
- 73% reduction in attack traffic when AWS WAF is properly configured (AWS Security Report, 2024)
- 99.95% availability SLA provided by CloudFront global edge network
AWS WAF Architecture and Core Components
Understanding AWS WAF v2 Architecture
AWS WAF v2 provides a robust, scalable web application firewall that integrates seamlessly with CloudFront, Application Load Balancer (ALB), and API Gateway. Unlike traditional solutions, AWS WAF operates at the edge through CloudFront’s global network, providing protection before traffic reaches your origin servers.
graph TB
A[User Request] --> B[CloudFront Edge Location]
B --> C[AWS WAF Rules Evaluation]
C --> D{Request Allowed?}
D -->|Yes| E[Origin Server]
D -->|No| F[Block/Rate Limit Response]
C --> G[CloudWatch Logging]
C --> H[AWS WAF Metrics]
Key AWS WAF Components
Web ACLs (Access Control Lists): Container for rules and rule groups that define the filtering logic Rules: Define conditions for inspecting web requests (IP addresses, HTTP headers, URI strings, SQL code, XSS scripts) Rule Groups: Collections of rules that can be reused across multiple Web ACLs IP Sets: Collections of IP addresses and IP address ranges for efficient IP-based filtering Regex Pattern Sets: Regular expression patterns for advanced string matching
OWASP Top 10 Protection Implementation
Core Rule Groups Configuration
AWS provides managed rule groups that specifically target OWASP Top 10 vulnerabilities. Here’s a comprehensive CloudFormation template that implements complete protection:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
AWSTemplateFormatVersion: '2010-09-09'
Description: 'AWS WAF with CloudFront - OWASP Top 10 Protection'
Parameters:
ApplicationName:
Type: String
Description: Name of the application for resource naming
Default: 'secure-webapp'
OriginDomainName:
Type: String
Description: Origin server domain name
AllowedCountries:
Type: CommaDelimitedList
Description: List of allowed country codes
Default: 'US,CA,GB'
Resources:
# AWS WAF Web ACL with OWASP Top 10 Protection
WebApplicationFirewall:
Type: AWS::WAFv2::WebACL
Properties:
Name: !Sub '${ApplicationName}-waf-acl'
Scope: CLOUDFRONT
DefaultAction:
Allow: {}
Description: 'WAF ACL for OWASP Top 10 protection'
Rules:
# 1. Rate limiting to prevent brute force attacks
- Name: RateLimitRule
Priority: 1
Statement:
RateBasedStatement:
Limit: 2000
AggregateKeyType: IP
Action:
Block: {}
VisibilityConfig:
SampledRequestsEnabled: true
CloudWatchMetricsEnabled: true
MetricName: !Sub '${ApplicationName}-rate-limit'
# 2. Geographic blocking
- Name: GeoBlockRule
Priority: 2
Statement:
NotStatement:
Statement:
GeoMatchStatement:
CountryCodes: !Ref AllowedCountries
Action:
Block: {}
VisibilityConfig:
SampledRequestsEnabled: true
CloudWatchMetricsEnabled: true
MetricName: !Sub '${ApplicationName}-geo-block'
# 3. AWS Managed Rule - Core Rule Set (CRS)
- Name: AWSManagedRulesCommonRuleSet
Priority: 3
OverrideAction:
None: {}
Statement:
ManagedRuleGroupStatement:
VendorName: AWS
Name: AWSManagedRulesCommonRuleSet
# Exclude specific rules if needed
ExcludedRules: []
VisibilityConfig:
SampledRequestsEnabled: true
CloudWatchMetricsEnabled: true
MetricName: !Sub '${ApplicationName}-common-ruleset'
# 4. SQL Injection Protection
- Name: AWSManagedRulesSQLiRuleSet
Priority: 4
OverrideAction:
None: {}
Statement:
ManagedRuleGroupStatement:
VendorName: AWS
Name: AWSManagedRulesSQLiRuleSet
VisibilityConfig:
SampledRequestsEnabled: true
CloudWatchMetricsEnabled: true
MetricName: !Sub '${ApplicationName}-sqli-protection'
# 5. Cross-Site Scripting (XSS) Protection
- Name: AWSManagedRulesKnownBadInputsRuleSet
Priority: 5
OverrideAction:
None: {}
Statement:
ManagedRuleGroupStatement:
VendorName: AWS
Name: AWSManagedRulesKnownBadInputsRuleSet
VisibilityConfig:
SampledRequestsEnabled: true
CloudWatchMetricsEnabled: true
MetricName: !Sub '${ApplicationName}-xss-protection'
# 6. Linux Operating System Protection
- Name: AWSManagedRulesLinuxRuleSet
Priority: 6
OverrideAction:
None: {}
Statement:
ManagedRuleGroupStatement:
VendorName: AWS
Name: AWSManagedRulesLinuxRuleSet
VisibilityConfig:
SampledRequestsEnabled: true
CloudWatchMetricsEnabled: true
MetricName: !Sub '${ApplicationName}-linux-protection'
# 7. Anonymous IP List
- Name: AWSManagedRulesAnonymousIpList
Priority: 7
OverrideAction:
None: {}
Statement:
ManagedRuleGroupStatement:
VendorName: AWS
Name: AWSManagedRulesAnonymousIpList
VisibilityConfig:
SampledRequestsEnabled: true
CloudWatchMetricsEnabled: true
MetricName: !Sub '${ApplicationName}-anonymous-ip'
# 8. Amazon IP Reputation List
- Name: AWSManagedRulesAmazonIpReputationList
Priority: 8
OverrideAction:
None: {}
Statement:
ManagedRuleGroupStatement:
VendorName: AWS
Name: AWSManagedRulesAmazonIpReputationList
VisibilityConfig:
SampledRequestsEnabled: true
CloudWatchMetricsEnabled: true
MetricName: !Sub '${ApplicationName}-ip-reputation'
VisibilityConfig:
SampledRequestsEnabled: true
CloudWatchMetricsEnabled: true
MetricName: !Sub '${ApplicationName}-waf-acl'
# CloudFront Distribution with WAF Integration
CloudFrontDistribution:
Type: AWS::CloudFront::Distribution
Properties:
DistributionConfig:
Enabled: true
Comment: !Sub 'CloudFront distribution for ${ApplicationName} with WAF protection'
# Web ACL Association
WebACLId: !GetAtt WebApplicationFirewall.Arn
# Origin Configuration
Origins:
- Id: !Sub '${ApplicationName}-origin'
DomainName: !Ref OriginDomainName
CustomOriginConfig:
HTTPPort: 80
HTTPSPort: 443
OriginProtocolPolicy: https-only
OriginSSLProtocols:
- TLSv1.2
- TLSv1.3
OriginReadTimeout: 30
OriginKeepaliveTimeout: 5
# Default Cache Behavior
DefaultCacheBehavior:
TargetOriginId: !Sub '${ApplicationName}-origin'
ViewerProtocolPolicy: redirect-to-https
AllowedMethods:
- GET
- HEAD
- OPTIONS
- PUT
- POST
- PATCH
- DELETE
CachedMethods:
- GET
- HEAD
Compress: true
# Security Headers
ResponseHeadersPolicyId: !Ref SecurityHeadersPolicy
# Caching Configuration
CachePolicyId: 4135ea2d-6df8-44a3-9df3-4b5a84be39ad # CachingDisabled for dynamic content
OriginRequestPolicyId: 88a5eaf4-2fd4-4709-b370-b4c650ea3fcf # CORS-S3Origin
# Additional Security Configuration
PriceClass: PriceClass_All # Global edge locations for maximum protection
ViewerCertificate:
AcmCertificateArn: !Ref SSLCertificate
SslSupportMethod: sni-only
MinimumProtocolVersion: TLSv1.2_2021
# Logging Configuration
Logging:
Bucket: !GetAtt LoggingBucket.DomainName
Prefix: 'cloudfront-logs/'
IncludeCookies: false
# Security Headers Response Policy
SecurityHeadersPolicy:
Type: AWS::CloudFront::ResponseHeadersPolicy
Properties:
ResponseHeadersPolicyConfig:
Name: !Sub '${ApplicationName}-security-headers'
SecurityHeadersConfig:
StrictTransportSecurity:
AccessControlMaxAgeSec: 31536000
IncludeSubdomains: true
Override: false
ContentTypeOptions:
Override: false
FrameOptions:
FrameOption: DENY
Override: false
XSSProtection:
ModeBlock: true
Protection: true
Override: false
CustomHeadersConfig:
Items:
- Header: 'Content-Security-Policy'
Value: "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self'; connect-src 'self'; frame-ancestors 'none';"
Override: false
# S3 Bucket for CloudFront Logs
LoggingBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Sub '${ApplicationName}-cloudfront-logs-${AWS::AccountId}'
PublicAccessBlockConfiguration:
BlockPublicAcls: true
BlockPublicPolicy: true
IgnorePublicAcls: true
RestrictPublicBuckets: true
BucketEncryption:
ServerSideEncryptionConfiguration:
- ServerSideEncryptionByDefault:
SSEAlgorithm: AES256
LifecycleConfiguration:
Rules:
- Id: DeleteOldLogs
Status: Enabled
ExpirationInDays: 90
# SSL Certificate (assumes certificate is already created)
SSLCertificate:
Type: AWS::CertificateManager::Certificate
Properties:
DomainName: !Ref OriginDomainName
ValidationMethod: DNS
DomainValidationOptions:
- DomainName: !Ref OriginDomainName
HostedZoneId: !Ref HostedZoneId # You'll need to provide this
Outputs:
WebACLId:
Description: 'AWS WAF Web ACL ID'
Value: !GetAtt WebApplicationFirewall.Arn
Export:
Name: !Sub '${ApplicationName}-waf-acl-id'
CloudFrontDomainName:
Description: 'CloudFront Distribution Domain Name'
Value: !GetAtt CloudFrontDistribution.DomainName
Export:
Name: !Sub '${ApplicationName}-cloudfront-domain'
CloudFrontDistributionId:
Description: 'CloudFront Distribution ID'
Value: !Ref CloudFrontDistribution
Export:
Name: !Sub '${ApplicationName}-cloudfront-id'
Advanced Rule Customization and Tuning
Custom SQL Injection Detection
While AWS managed rules provide excellent baseline protection, you may need custom rules for application-specific SQL injection patterns:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# Custom SQL Injection Rule Example
CustomSQLiRule:
Type: AWS::WAFv2::WebACL
Properties:
Rules:
- Name: CustomSQLInjectionRule
Priority: 10
Statement:
OrStatement:
Statements:
# Detect SQL keywords in query parameters
- ByteMatchStatement:
SearchString: 'union select'
FieldToMatch:
AllQueryArguments: {}
TextTransformations:
- Priority: 1
Type: URL_DECODE
- Priority: 2
Type: LOWERCASE
PositionalConstraint: CONTAINS
# Detect SQL comments
- ByteMatchStatement:
SearchString: '--'
FieldToMatch:
AllQueryArguments: {}
TextTransformations:
- Priority: 1
Type: URL_DECODE
PositionalConstraint: CONTAINS
# Detect SQL functions
- RegexMatchStatement:
RegexString: '(?i)(concat|substring|ascii|char|user|database|version)\s*\('
FieldToMatch:
AllQueryArguments: {}
TextTransformations:
- Priority: 1
Type: URL_DECODE
- Priority: 2
Type: HTML_ENTITY_DECODE
Action:
Block: {}
VisibilityConfig:
SampledRequestsEnabled: true
CloudWatchMetricsEnabled: true
MetricName: 'custom-sqli-rule'
Advanced XSS Protection
Implement sophisticated XSS detection that goes beyond standard patterns:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# Advanced XSS Detection Rules
AdvancedXSSRules:
- Name: XSSPatternDetection
Priority: 11
Statement:
OrStatement:
Statements:
# JavaScript event handlers
- RegexMatchStatement:
RegexString: '(?i)on(load|error|click|mouse|focus|blur|change|submit|reset|select|resize|scroll)='
FieldToMatch:
Body: {}
TextTransformations:
- Priority: 1
Type: URL_DECODE
- Priority: 2
Type: HTML_ENTITY_DECODE
# Script tag variations
- RegexMatchStatement:
RegexString: '(?i)<script[^>]*>.*?</script>'
FieldToMatch:
Body: {}
TextTransformations:
- Priority: 1
Type: URL_DECODE
- Priority: 2
Type: HTML_ENTITY_DECODE
# JavaScript pseudo protocol
- ByteMatchStatement:
SearchString: 'javascript:'
FieldToMatch:
AllQueryArguments: {}
TextTransformations:
- Priority: 1
Type: URL_DECODE
- Priority: 2
Type: LOWERCASE
PositionalConstraint: CONTAINS
Action:
Block: {}
VisibilityConfig:
SampledRequestsEnabled: true
CloudWatchMetricsEnabled: true
MetricName: 'advanced-xss-protection'
Monitoring and Alerting Implementation
CloudWatch Dashboard for WAF Metrics
Create comprehensive monitoring to track attack patterns and rule effectiveness:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
import boto3
import json
from datetime import datetime, timedelta
def create_waf_dashboard(dashboard_name, web_acl_name, cloudfront_distribution_id):
"""
Create CloudWatch Dashboard for AWS WAF monitoring
"""
cloudwatch = boto3.client('cloudwatch')
dashboard_body = {
"widgets": [
{
"type": "metric",
"x": 0, "y": 0,
"width": 12, "height": 6,
"properties": {
"metrics": [
["AWS/WAFV2", "AllowedRequests", "WebACL", web_acl_name, "Region", "CloudFront", "Rule", "ALL"],
[".", "BlockedRequests", ".", ".", ".", ".", ".", "."]
],
"view": "timeSeries",
"stacked": False,
"region": "us-east-1",
"title": "WAF Request Overview",
"period": 300
}
},
{
"type": "metric",
"x": 12, "y": 0,
"width": 12, "height": 6,
"properties": {
"metrics": [
["AWS/WAFV2", "BlockedRequests", "WebACL", web_acl_name, "Region", "CloudFront", "Rule", "RateLimitRule"],
[".", ".", ".", ".", ".", ".", ".", "CustomSQLInjectionRule"],
[".", ".", ".", ".", ".", ".", ".", "AdvancedXSSRule"]
],
"view": "timeSeries",
"stacked": True,
"region": "us-east-1",
"title": "Blocked Requests by Rule Type",
"period": 300
}
},
{
"type": "metric",
"x": 0, "y": 6,
"width": 24, "height": 6,
"properties": {
"metrics": [
["AWS/CloudFront", "Requests", "DistributionId", cloudfront_distribution_id],
[".", "BytesDownloaded", ".", "."],
[".", "4xxErrorRate", ".", "."],
[".", "5xxErrorRate", ".", "."]
],
"view": "timeSeries",
"stacked": False,
"region": "us-east-1",
"title": "CloudFront Performance Metrics",
"period": 300
}
}
]
}
response = cloudwatch.put_dashboard(
DashboardName=dashboard_name,
DashboardBody=json.dumps(dashboard_body)
)
return response
def create_waf_alarms(web_acl_name, sns_topic_arn):
"""
Create CloudWatch Alarms for critical WAF events
"""
cloudwatch = boto3.client('cloudwatch')
# High rate of blocked requests alarm
blocked_requests_alarm = cloudwatch.put_metric_alarm(
AlarmName=f'{web_acl_name}-high-blocked-requests',
ComparisonOperator='GreaterThanThreshold',
EvaluationPeriods=2,
MetricName='BlockedRequests',
Namespace='AWS/WAFV2',
Period=300,
Statistic='Sum',
Threshold=1000.0,
ActionsEnabled=True,
AlarmActions=[sns_topic_arn],
AlarmDescription='Alert when blocked requests exceed threshold',
Dimensions=[
{
'Name': 'WebACL',
'Value': web_acl_name
},
{
'Name': 'Region',
'Value': 'CloudFront'
}
]
)
# SQL injection attack alarm
sqli_alarm = cloudwatch.put_metric_alarm(
AlarmName=f'{web_acl_name}-sqli-attack',
ComparisonOperator='GreaterThanThreshold',
EvaluationPeriods=1,
MetricName='BlockedRequests',
Namespace='AWS/WAFV2',
Period=300,
Statistic='Sum',
Threshold=50.0,
ActionsEnabled=True,
AlarmActions=[sns_topic_arn],
AlarmDescription='Alert on SQL injection attack patterns',
Dimensions=[
{
'Name': 'WebACL',
'Value': web_acl_name
},
{
'Name': 'Rule',
'Value': 'CustomSQLInjectionRule'
}
]
)
return blocked_requests_alarm, sqli_alarm
# Usage example
if __name__ == "__main__":
dashboard_response = create_waf_dashboard(
dashboard_name="WAF-Security-Dashboard",
web_acl_name="secure-webapp-waf-acl",
cloudfront_distribution_id="E1234567890123"
)
sns_topic = "arn:aws:sns:us-east-1:123456789012:security-alerts"
alarms = create_waf_alarms("secure-webapp-waf-acl", sns_topic)
print("Dashboard and alarms created successfully")
Conclusion
AWS WAF integrated with CloudFront provides enterprise-grade web application security that scales automatically and requires minimal operational overhead compared to traditional solutions. By implementing the comprehensive protection strategy outlined in this guide, organizations can effectively defend against OWASP Top 10 vulnerabilities while maintaining high performance and availability.
The cloud-native approach eliminates the complexity of managing infrastructure, patching security software, and scaling protection during attack scenarios. With proper monitoring, alerting, and automated response mechanisms in place, AWS WAF becomes a cornerstone of a robust DevSecOps security strategy.
The combination of AWS managed rules, custom threat detection, and automated response provides multilayered protection that evolves with emerging threats while maintaining the agility required for modern application deployment.
For personalized guidance on implementing AWS WAF and CloudFront security in your DevSecOps environment, connect with Jon Price on LinkedIn.