Rule Examples
Looking for which NSM policy each NSM rule belongs in?
The recommended design shows how these NSM rules combine into NSM policies, with the priority, scope, and business need for each.
Overview
This section describes the configuration of each NSM rule that the NSM policies in AWS WAF Recommended Design contain.
NSM firewall configuration rules
WAF logging
Sends WAF logs from every in-scope web ACL to a central log destination.
The following example sends WAF logs to an Amazon S3 bucket.
{
"LoggingConfiguration": {
"LogDestinationConfigs": [
"aws-waf-logs-111111111111-us-east-1"
],
"LogType": "WAF_LOGS",
"LogScope": "CUSTOMER"
}
}
The following example sends WAF logs to an Amazon Data Firehose delivery stream.
{
"LoggingConfiguration": {
"LogDestinationConfigs": [
"arn:aws:firehose:us-east-1:111111111111:deliverystream/aws-waf-logs-central"
],
"LogType": "WAF_LOGS",
"LogScope": "CUSTOMER"
}
}
The following example redacts the authorization and cookie headers from logs, and keeps only the logs for requests that a WAF rule blocked or counted.
{
"LoggingConfiguration": {
"LogDestinationConfigs": [
"arn:aws:firehose:us-east-1:111111111111:deliverystream/aws-waf-logs-central"
],
"LogType": "WAF_LOGS",
"LogScope": "CUSTOMER",
"RedactedFields": [
{
"SingleHeader": {
"Name": "authorization"
}
},
{
"SingleHeader": {
"Name": "cookie"
}
}
],
"LoggingFilter": {
"Filters": [
{
"Behavior": "KEEP",
"Requirement": "MEETS_ANY",
"Conditions": [
{
"ActionCondition": {
"Action": "BLOCK"
}
},
{
"ActionCondition": {
"Action": "COUNT"
}
}
]
}
],
"DefaultBehavior": "DROP"
}
}
}
Default action
Sets the web ACL default action for requests that no WAF rule blocks.
Token domains
Sets the token domains that AWS WAF accepts for CAPTCHA and Challenge tokens.
Visibility configuration
Turns on Amazon CloudWatch metrics and sampled requests for the web ACL.
{
"VisibilityConfig": {
"SampledRequestsEnabled": true,
"CloudWatchMetricsEnabled": true,
"MetricName": "nsm-web-acl"
}
}
Managed rule group NSM rules
Anti-DDoS
Adds the Anti-DDoS AMR rule group (AWSManagedRulesAntiDDoSRuleSet) with every WAF rule in count mode.
{
"Name": "AWS-AWSManagedRulesAntiDDoSRuleSet",
"Statement": {
"ManagedRuleGroupStatement": {
"VendorName": "AWS",
"Name": "AWSManagedRulesAntiDDoSRuleSet",
"ManagedRuleGroupConfigs": [
{
"AWSManagedRulesAntiDDoSRuleSet": {
"ClientSideActionConfig": {
"Challenge": {
"UsageOfAction": "ENABLED",
"Sensitivity": "HIGH",
"ExemptUriRegularExpressions": [
{
"RegexString": "\\/api\\/|\\.(acc|avi|css|gif|jpe?g|js|mp[34]|ogg|otf|pdf|png|tiff?|ttf|webm|webp|woff2?)$"
}
]
}
},
"SensitivityToBlock": "LOW"
}
}
]
}
},
"OverrideAction": {
"Count": {}
},
"VisibilityConfig": {
"SampledRequestsEnabled": true,
"CloudWatchMetricsEnabled": true,
"MetricName": "AWS-AWSManagedRulesAntiDDoSRuleSet"
}
}
Amazon IP reputation list
Adds the Amazon IP reputation list AMR rule group (AWSManagedRulesAmazonIpReputationList) with every WAF rule in count mode.
{
"Name": "AWS-AWSManagedRulesAmazonIpReputationList",
"Statement": {
"ManagedRuleGroupStatement": {
"VendorName": "AWS",
"Name": "AWSManagedRulesAmazonIpReputationList"
}
},
"OverrideAction": {
"Count": {}
},
"VisibilityConfig": {
"SampledRequestsEnabled": true,
"CloudWatchMetricsEnabled": true,
"MetricName": "AWS-AWSManagedRulesAmazonIpReputationList"
}
}
Anonymous IP list
Adds the anonymous IP list AMR rule group (AWSManagedRulesAnonymousIpList) with every WAF rule in count mode.
{
"Name": "AWS-AWSManagedRulesAnonymousIpList",
"Statement": {
"ManagedRuleGroupStatement": {
"VendorName": "AWS",
"Name": "AWSManagedRulesAnonymousIpList"
}
},
"OverrideAction": {
"Count": {}
},
"VisibilityConfig": {
"SampledRequestsEnabled": true,
"CloudWatchMetricsEnabled": true,
"MetricName": "AWS-AWSManagedRulesAnonymousIpList"
}
}
Core Rule Set
Adds the Core Rule Set AMR rule group (AWSManagedRulesCommonRuleSet) with every WAF rule in count mode.
{
"Name": "AWS-AWSManagedRulesCommonRuleSet",
"Statement": {
"ManagedRuleGroupStatement": {
"VendorName": "AWS",
"Name": "AWSManagedRulesCommonRuleSet"
}
},
"OverrideAction": {
"Count": {}
},
"VisibilityConfig": {
"SampledRequestsEnabled": true,
"CloudWatchMetricsEnabled": true,
"MetricName": "AWS-AWSManagedRulesCommonRuleSet"
}
}
Known Bad Inputs
Adds the Known Bad Inputs AMR rule group (AWSManagedRulesKnownBadInputsRuleSet) with every WAF rule in count mode.
{
"Name": "AWS-AWSManagedRulesKnownBadInputsRuleSet",
"Statement": {
"ManagedRuleGroupStatement": {
"VendorName": "AWS",
"Name": "AWSManagedRulesKnownBadInputsRuleSet"
}
},
"OverrideAction": {
"Count": {}
},
"VisibilityConfig": {
"SampledRequestsEnabled": true,
"CloudWatchMetricsEnabled": true,
"MetricName": "AWS-AWSManagedRulesKnownBadInputsRuleSet"
}
}
Use-case AMRs
Adds one use-case AMR rule group, such as WordPress, SQL database, Linux, POSIX, Windows, or PHP, with every WAF rule in count mode.
The following example uses the WordPress AMR rule group. The other use-case AMRs use the same structure with their own rule group names.
{
"Name": "AWS-AWSManagedRulesWordPressRuleSet",
"Statement": {
"ManagedRuleGroupStatement": {
"VendorName": "AWS",
"Name": "AWSManagedRulesWordPressRuleSet"
}
},
"OverrideAction": {
"Count": {}
},
"VisibilityConfig": {
"SampledRequestsEnabled": true,
"CloudWatchMetricsEnabled": true,
"MetricName": "AWS-AWSManagedRulesWordPressRuleSet"
}
}
Partner managed rule groups
Adds an AWS Marketplace partner managed rule group.
{
"Name": "ExampleVendor-ExampleRuleGroup",
"Statement": {
"ManagedRuleGroupStatement": {
"VendorName": "ExampleVendor",
"Name": "ExampleRuleGroup"
}
},
"OverrideAction": {
"None": {}
},
"VisibilityConfig": {
"SampledRequestsEnabled": true,
"CloudWatchMetricsEnabled": true,
"MetricName": "ExampleVendor-ExampleRuleGroup"
}
}
Bot Control
Adds the Bot Control AMR rule group (AWSManagedRulesBotControlRuleSet) with a scope-down statement and every WAF rule in count mode.
{
"Name": "AWS-AWSManagedRulesBotControlRuleSet",
"Statement": {
"ManagedRuleGroupStatement": {
"VendorName": "AWS",
"Name": "AWSManagedRulesBotControlRuleSet",
"ManagedRuleGroupConfigs": [
{
"AWSManagedRulesBotControlRuleSet": {
"InspectionLevel": "COMMON"
}
}
],
"ScopeDownStatement": {
"NotStatement": {
"Statement": {
"ByteMatchStatement": {
"FieldToMatch": {
"UriPath": {}
},
"PositionalConstraint": "STARTS_WITH",
"SearchString": "/static/",
"TextTransformations": [
{
"Priority": 0,
"Type": "NONE"
}
]
}
}
}
}
}
},
"OverrideAction": {
"Count": {}
},
"VisibilityConfig": {
"SampledRequestsEnabled": true,
"CloudWatchMetricsEnabled": true,
"MetricName": "AWS-AWSManagedRulesBotControlRuleSet"
}
}
Account Takeover Prevention
Adds the Account Takeover Prevention (ATP) AMR rule group (AWSManagedRulesATPRuleSet), scoped down to an application's login page, with every WAF rule in count mode.
{
"Name": "AWS-AWSManagedRulesATPRuleSet",
"Statement": {
"ManagedRuleGroupStatement": {
"VendorName": "AWS",
"Name": "AWSManagedRulesATPRuleSet",
"ManagedRuleGroupConfigs": [
{
"AWSManagedRulesATPRuleSet": {
"LoginPath": "/api/login",
"RequestInspection": {
"PayloadType": "JSON",
"UsernameField": {
"Identifier": "/username"
},
"PasswordField": {
"Identifier": "/password"
}
},
"EnableRegexInPath": false
}
}
],
"ScopeDownStatement": {
"ByteMatchStatement": {
"FieldToMatch": {
"UriPath": {}
},
"PositionalConstraint": "STARTS_WITH",
"SearchString": "/api/login",
"TextTransformations": [
{
"Priority": 0,
"Type": "NONE"
}
]
}
}
}
},
"OverrideAction": {
"Count": {}
},
"VisibilityConfig": {
"SampledRequestsEnabled": true,
"CloudWatchMetricsEnabled": true,
"MetricName": "AWS-AWSManagedRulesATPRuleSet"
}
}
Account Creation Fraud Prevention
Adds the Account Creation Fraud Prevention (ACFP) AMR rule group (AWSManagedRulesACFPRuleSet), scoped down to an application's sign-up page, with every WAF rule in count mode.
{
"Name": "AWS-AWSManagedRulesACFPRuleSet",
"Statement": {
"ManagedRuleGroupStatement": {
"VendorName": "AWS",
"Name": "AWSManagedRulesACFPRuleSet",
"ManagedRuleGroupConfigs": [
{
"AWSManagedRulesACFPRuleSet": {
"CreationPath": "/api/signup",
"RegistrationPagePath": "/signup",
"RequestInspection": {
"PayloadType": "JSON",
"UsernameField": {
"Identifier": "/username"
},
"PasswordField": {
"Identifier": "/password"
},
"EmailField": {
"Identifier": "/email"
}
},
"EnableRegexInPath": false
}
}
],
"ScopeDownStatement": {
"ByteMatchStatement": {
"FieldToMatch": {
"UriPath": {}
},
"PositionalConstraint": "STARTS_WITH",
"SearchString": "/api/signup",
"TextTransformations": [
{
"Priority": 0,
"Type": "NONE"
}
]
}
}
}
},
"OverrideAction": {
"Count": {}
},
"VisibilityConfig": {
"SampledRequestsEnabled": true,
"CloudWatchMetricsEnabled": true,
"MetricName": "AWS-AWSManagedRulesACFPRuleSet"
}
}
Custom NSM rules
IP allow list
Allows requests from trusted addresses, with one IP set for IPv4 and one for IPv6 combined in an OR statement in a single WAF rule.
{
"Name": "IP-allow-list",
"Statement": {
"OrStatement": {
"Statements": [
{
"IPSetReferenceStatement": {
"ARN": "arn:aws:wafv2:us-east-1:111111111111:global/ipset/trusted-ips-v4/a1b2c3d4-5678-90ab-cdef-EXAMPLE22222"
}
},
{
"IPSetReferenceStatement": {
"ARN": "arn:aws:wafv2:us-east-1:111111111111:global/ipset/trusted-ips-v6/a1b2c3d4-5678-90ab-cdef-EXAMPLE33333"
}
}
]
}
},
"Action": {
"Allow": {}
},
"VisibilityConfig": {
"SampledRequestsEnabled": true,
"CloudWatchMetricsEnabled": true,
"MetricName": "IP-allow-list"
}
}
IP block list
Blocks requests from addresses that you don't want to reach your applications, such as addresses from threat intelligence, with one IP set for IPv4 and one for IPv6 combined in an OR statement in a single WAF rule.
{
"Name": "IP-block-list",
"Statement": {
"OrStatement": {
"Statements": [
{
"IPSetReferenceStatement": {
"ARN": "arn:aws:wafv2:us-east-1:111111111111:global/ipset/blocked-ips-v4/a1b2c3d4-5678-90ab-cdef-EXAMPLE44444"
}
},
{
"IPSetReferenceStatement": {
"ARN": "arn:aws:wafv2:us-east-1:111111111111:global/ipset/blocked-ips-v6/a1b2c3d4-5678-90ab-cdef-EXAMPLE55555"
}
}
]
}
},
"Action": {
"Block": {}
},
"VisibilityConfig": {
"SampledRequestsEnabled": true,
"CloudWatchMetricsEnabled": true,
"MetricName": "IP-block-list"
}
}
Geo blocking
Blocks requests from a list of blocked countries, or from every country that isn't on an allowed list.
The following example blocks every country that isn't on an allowed list.
{
"Name": "Geo-block-not-allowed-countries",
"Statement": {
"NotStatement": {
"Statement": {
"GeoMatchStatement": {
"CountryCodes": [
"US",
"CA"
]
}
}
}
},
"Action": {
"Block": {}
},
"VisibilityConfig": {
"SampledRequestsEnabled": true,
"CloudWatchMetricsEnabled": true,
"MetricName": "Geo-block-not-allowed-countries"
}
}
Blanket rate limit
Blocks clients, usually by IP address, that exceed a high request rate across all requests.
{
"Name": "Rate-limit-blanket",
"Statement": {
"RateBasedStatement": {
"Limit": 2000,
"EvaluationWindowSec": 300,
"AggregateKeyType": "IP"
}
},
"Action": {
"Block": {}
},
"VisibilityConfig": {
"SampledRequestsEnabled": true,
"CloudWatchMetricsEnabled": true,
"MetricName": "Rate-limit-blanket"
}
}
Scoped rate limits
Block clients that exceed a lower request rate for a specific HTTP method or URI.
{
"Name": "Rate-limit-login",
"Statement": {
"RateBasedStatement": {
"Limit": 100,
"EvaluationWindowSec": 300,
"AggregateKeyType": "IP",
"ScopeDownStatement": {
"ByteMatchStatement": {
"FieldToMatch": {
"UriPath": {}
},
"PositionalConstraint": "STARTS_WITH",
"SearchString": "/api/login",
"TextTransformations": [
{
"Priority": 0,
"Type": "NONE"
}
]
}
}
}
},
"Action": {
"Block": {}
},
"VisibilityConfig": {
"SampledRequestsEnabled": true,
"CloudWatchMetricsEnabled": true,
"MetricName": "Rate-limit-login"
}
}
Application exceptions
Add an exception label to requests that one application needs to exempt from one WAF rule in an AMR rule group. The following example exempts App1's /custom-feature/ path from the Core Rule Set CrossSiteScripting_Body WAF rule.
{
"Name": "App1-AMR-exception",
"Statement": {
"AndStatement": {
"Statements": [
{
"ByteMatchStatement": {
"FieldToMatch": {
"SingleHeader": {
"Name": "host"
}
},
"PositionalConstraint": "EXACTLY",
"SearchString": "app1.example.com",
"TextTransformations": [
{
"Priority": 0,
"Type": "LOWERCASE"
}
]
}
},
{
"ByteMatchStatement": {
"FieldToMatch": {
"UriPath": {}
},
"PositionalConstraint": "STARTS_WITH",
"SearchString": "/custom-feature/",
"TextTransformations": [
{
"Priority": 0,
"Type": "NONE"
}
]
}
}
]
}
},
"Action": {
"Count": {}
},
"RuleLabels": [
{
"Name": "exception:core-rule-set:CrossSiteScripting_Body"
}
],
"VisibilityConfig": {
"SampledRequestsEnabled": true,
"CloudWatchMetricsEnabled": true,
"MetricName": "App1-AMR-exception"
}
}
Application-specific protections
Add protections that only one application needs.
The following example blocks requests to an administration path that App1 doesn't expose publicly.
{
"Name": "App1-block-admin-path",
"Statement": {
"ByteMatchStatement": {
"FieldToMatch": {
"UriPath": {}
},
"PositionalConstraint": "STARTS_WITH",
"SearchString": "/admin/",
"TextTransformations": [
{
"Priority": 0,
"Type": "NONE"
}
]
}
},
"Action": {
"Block": {}
},
"VisibilityConfig": {
"SampledRequestsEnabled": true,
"CloudWatchMetricsEnabled": true,
"MetricName": "App1-block-admin-path"
}
}
AMR block with exceptions
Blocks requests that carry one AMR label, unless the request also carries the matching exception label. Create one NSM rule like this for each unique label that the AMR rule groups add, so that an exception for one AMR WAF rule never exempts a request from another.
The following example blocks requests that the Core Rule Set CrossSiteScripting_Body WAF rule labeled, unless they carry the exception:core-rule-set:CrossSiteScripting_Body label.
{
"Name": "Block-CRS-CrossSiteScripting_Body-unless-excepted",
"Statement": {
"AndStatement": {
"Statements": [
{
"LabelMatchStatement": {
"Scope": "LABEL",
"Key": "awswaf:managed:aws:core-rule-set:CrossSiteScripting_Body"
}
},
{
"NotStatement": {
"Statement": {
"LabelMatchStatement": {
"Scope": "LABEL",
"Key": "exception:core-rule-set:CrossSiteScripting_Body"
}
}
}
}
]
}
},
"Action": {
"Block": {}
},
"VisibilityConfig": {
"SampledRequestsEnabled": true,
"CloudWatchMetricsEnabled": true,
"MetricName": "Block-CRS-CrossSiteScripting_Body-unless-excepted"
}
}