PRACTITIONER GUIDE
Practitioner Guide12 min read

WAF Custom Rule Writing and False Positive Tuning: AWS WAF, ModSecurity, and Managed Rule Optimization

Count mode
AWS WAF mode that logs rule matches without blocking, used to measure false positive rates before switching a new rule to Block mode in production
Paranoia 1
OWASP Core Rule Set paranoia level that activates the foundational detection rules with the lowest false positive rate; levels 2-4 add more aggressive detection with progressively higher false positive risk
Rate-based
AWS WAF rule type that triggers after a source IP or header value exceeds a configurable request count within a 5-minute window, blocking credential stuffing and scraping without writing signature rules
ScopeDownStatement
AWS WAF managed rule group parameter that restricts a rule's scope to specific URI paths or request characteristics, reducing false positives from managed rules that match legitimate application traffic

SponsoredRetool

Retool's new app builder is where AI-generated code ships safely

Building apps with AI is easy. Getting them to production safely is another story.

Start building for free today

A WAF deployed in block mode with managed rule groups and no tuning will block somewhere between 0.1% and 5% of legitimate application traffic on day one, depending on the application's traffic patterns and the managed rules chosen. Most WAF deployments stay in count mode indefinitely rather than dealing with the false positive reduction work required to switch to block mode safely. This is the worst outcome — the WAF consumes budget and generates noise without actually blocking any attacks.

The path from count mode to block mode runs through WAF log analysis. The logs show exactly which rule blocked which request, what the request looked like, and how frequently the pattern appears. Armed with that data, scope-down statements or rule exclusions can be written that preserve blocking for attack traffic while allowing legitimate requests. Done systematically over two to four weeks, the false positive rate can typically be reduced from 1-5% to under 0.01%, at which point switching to block mode is a defensible operational decision.

Rule authoring: custom rules for application-specific attack patterns

Managed rule groups cover generic attack patterns that apply across all web applications. Custom rules cover attack patterns specific to your application's endpoints, data models, and threat landscape. The highest-value custom rules are typically rate-based rules targeting authentication endpoints, geo-blocking rules for regions with no legitimate user base, and string-match rules targeting known-bad patterns in your specific application context that managed rules miss because they are too application-specific.

Build custom rules for API endpoints using request inspection at the JSON body level

AWS WAF can inspect JSON request bodies for custom rule matching using the JsonBody field match type, which decodes and inspects JSON structure rather than treating the body as a raw string. A custom rule that blocks API requests with an unexpected field in the JSON body can use a ByteMatchStatement with FieldToMatch: JsonBody matching a specific JSON path expression against a list of expected field names. This is more precise than string matching against the raw request body, which generates false positives when legitimate JSON values happen to contain attack signature strings. Configure the JSON body inspection with MATCH_PATTERN to specify which JSON keys to inspect rather than evaluating the entire body, which also reduces WAF processing cost for large JSON payloads.

Write rate-based rules with compound conditions to target abusive traffic patterns specifically

A rate-based rule that simply counts all requests from an IP is too broad for applications with legitimate high-volume API consumers. Write compound rate-based rules that count only specific request patterns: a rule that counts POST requests to /api/v1/auth with a missing or suspicious User-Agent header targets credential stuffing tools without counting legitimate API traffic. In AWS WAF, compound rate-based rules use the Scope-down statement field to add AND conditions to the rate counter — only requests matching the scope-down conditions increment the counter for that IP. This precision allows you to set a low rate limit (10 per 5 minutes) on the credential stuffing pattern without affecting legitimate API clients that make hundreds of requests per minute to other endpoints.

Tuning workflow: moving from count mode to block mode safely

The transition from count mode to block mode is a multi-week process that requires systematic false positive identification and remediation before each rule group is switched. Starting with the rule group that has the lowest false positive rate and switching it to block mode first — typically the IP reputation rule group — builds operational confidence in the tuning process before tackling the higher-volume Core Rule Set and Known Bad Inputs groups. Each rule group switch should be treated as a production change with monitoring and a rollback plan.

Use Athena queries against WAF logs to calculate the false positive rate for each managed rule group

Before switching any managed rule group from count to block, calculate the false positive rate by identifying counted (not blocked) requests that match your own application's traffic fingerprints. Query the WAF logs with Athena: SELECT terminatingruleid, COUNT(*) as matched, COUNT_IF(httprequest.headers LIKE '%yourdomain.com%') as likely_internal FROM waf_logs WHERE action='COUNT' GROUP BY terminatingruleid ORDER BY matched DESC. Requests with your application's known user agents, referrer headers, or source IP ranges in the counted traffic are likely false positive matches. Calculate false_positive_rate as likely_internal divided by matched for each rule group. A rate above 1% warrants scope-down tuning before switching to block mode; a rate below 0.1% means the rule group is ready to switch.

Implement a phased block mode rollout by switching one managed rule group at a time with 48-hour monitoring between switches

Switch managed rule groups from count to block in order of ascending false positive rate, with 48 hours of monitoring between each switch to catch any blocked legitimate traffic before it accumulates into a significant user impact. Start with the IP Reputation List (lowest false positive rate, highest signal-to-noise), then the Known Bad Inputs rule group, then the Core Rule Set at paranoia level 1. After each switch, configure a CloudWatch alarm on the BlockedRequests metric for the switched rule group and monitor for unexpected spikes. Set up a runbook that documents how to switch a rule group back to count mode within five minutes if a spike indicates a false positive emergency. The phased approach means that at any given time only one rule group is newly in block mode and is the primary suspect if new user-reported blocking issues emerge.

Free daily briefing

Briefings like this, every morning before 9am.

Threat intel, active CVEs, and campaign alerts, distilled for practitioners. 50,000+ subscribers. No noise.

The bottom line

WAF false positive tuning is the practice that separates a WAF that operates in count mode indefinitely from a WAF that actually blocks attacks in production. Enable WAF logging to S3 and query with Athena to calculate the false positive rate per rule group before switching any rule to block mode. Use ScopeDownStatements to restrict managed rules to URIs where they are relevant, and ExcludedRules to disable specific managed rule IDs that generate false positives application-wide. Write custom rate-based rules with compound conditions that target credential stuffing and scraping patterns precisely. Follow a phased rollout from count to block mode, starting with the highest-confidence rule groups and monitoring for 48 hours between each switch. The entire tuning process from initial deployment to full block mode coverage takes two to four weeks and results in a WAF that blocks real attacks without generating the false positives that cause teams to abandon block mode permanently.

Frequently asked questions

How do I write a custom AWS WAF rule to block a specific attack pattern?

Write a custom AWS WAF rule using the WAF console's rule builder or in JSON using the AWS CLI. A rule that blocks requests containing a specific malicious user agent string uses a ByteMatchStatement with FieldToMatch: SingleHeader name: user-agent, PositionalConstraint: CONTAINS, and SearchString: the string to match. A rule that blocks SQL injection patterns in query strings uses a SqliMatchStatement with FieldToMatch: QueryString and TextTransformations: [URL_DECODE, LOWERCASE] to normalize the input before evaluation. In the rule builder, set the Action to Block for rules you are confident about and to Count for rules you are testing. Assign a numeric Priority to each rule — lower numbers are evaluated first — and place your most specific custom rules at higher priority than the managed rule groups so custom allow rules can override managed rule blocks. Test the rule in Count mode for 24-48 hours, check the CloudWatch metrics for the rule's SampledCount, and review the WAF logs to confirm the rule is matching only intended traffic before switching to Block.

How do I analyze AWS WAF logs to identify false positives?

Analyze AWS WAF logs for false positives by enabling full WAF logging to S3 and querying the logs with Amazon Athena. Enable logging in the WAF console under Logging and metrics, set the destination to an S3 bucket, and enable log filtering to capture blocked and counted requests. Create an Athena table over the S3 log location using the WAF log schema, then query for blocked requests that match your application's legitimate traffic patterns: SELECT terminatingRuleid, httprequest.uri, httprequest.httpmethod, COUNT(*) as count FROM waf_logs WHERE action='BLOCK' GROUP BY terminatingRuleid, httprequest.uri, httprequest.httpmethod ORDER BY count DESC. High-count blocks on specific URIs from your application identify false positive candidates. For each false positive, note the terminatingRuleid (the rule that blocked the request), the URI, and the request characteristics that triggered the match. This information is what you need to write a scope-down statement or rule exclusion that preserves blocking for attack traffic while allowing your legitimate requests.

How do I add exclusions to AWS WAF managed rule groups to stop false positives?

Add exclusions to AWS WAF managed rule groups using two approaches: ExcludedRules (which disables a specific rule entirely within the rule group) and ScopeDownStatement (which restricts the rule group to apply only to specific request characteristics). Use ExcludedRules when a specific managed rule generates false positives across your entire application — in the AWS WAF console, edit the managed rule group and select the specific rule IDs to exclude based on the terminatingRuleid in your WAF logs. Use ScopeDownStatement when a managed rule group generates false positives only on specific URI paths: configure the scope-down to apply the rule group only to requests matching specific URIs (e.g., apply the SQL injection rule group only to /api/* paths but not to /admin/search which is an internal tool that intentionally sends SQL-like strings). ScopeDownStatement is preferable to ExcludedRules because it maintains protection for the rest of the application while preventing false positives on specific paths.

How do I write a rate-based WAF rule to block credential stuffing attacks?

Write a rate-based AWS WAF rule that blocks IPs exceeding a threshold of login attempts within a 5-minute window. In the rule builder, select RateBasedStatement, set Aggregate key type to IP, and set the Rate limit to the maximum legitimate login attempts per 5 minutes from a single IP for your application (typically 10-20 for a login endpoint). Narrow the rule to the login endpoint using a nested ByteMatchStatement with AND logic that requires the URI to match /auth/login or /api/v1/login and the HTTP method to be POST, so the rate counter only increments on actual login attempts rather than all traffic from the IP. Set the action to Block with a custom 429 response body so that blocked clients receive a meaningful error rather than a generic block page. Add an IPSetReferenceStatement that allows your known monitoring and synthetic testing IPs to bypass the rate limit, preventing false positives from automated health checks that target the login endpoint.

How do I tune ModSecurity Core Rule Set false positives?

Tune ModSecurity Core Rule Set false positives by running CRS in detection-only mode first (SecRuleEngine DetectionOnly), collecting false positive logs for two to four weeks, then adding exclusion rules for confirmed false positive patterns before switching to prevention mode (SecRuleEngine On). In detection mode, ModSecurity logs rule matches with rule IDs in the error_log or modsec_audit.log without blocking requests. For each logged rule ID that matched legitimate traffic, write an exclusion rule using SecRuleUpdateTargetById to remove the specific argument that caused the false positive: SecRuleUpdateTargetById 942100 !ARGS:search_query removes the search_query parameter from SQL injection rule 942100 checking, which stops the false positive on your search endpoint without disabling SQL injection checking for other parameters. For endpoints that generate many false positives (admin panels, rich text editors, API endpoints accepting JSON), write a SecRule that matches the specific URI and uses the ctl:ruleRemoveById action to disable specific CRS rules only for requests to that path.

How do I write an AWS WAF rule to block malicious bots while allowing legitimate crawlers?

Block malicious bots while allowing legitimate crawlers using a combination of AWS WAF managed rules and custom rules. Enable the AWS Managed Rule Group Bot Control, which maintains an up-to-date list of verified bot identifiers and classifies bots as verified (Google, Bing, legitimate crawlers) versus unverified (scrapers, attack tools). Configure the Bot Control rule group in targeted mode rather than common mode for lower false positive rates. Add a custom rule that blocks requests with user agents matching known scraper patterns using a RegexMatchStatement: create a RegexPatternSet containing patterns like python-requests/, scrapy/, curl/ (without version suffixes that legitimate monitoring uses), and Wget/ combined with AND logic requiring that the request does not match the verified bot allowlist. Add a geo-match condition to block traffic from geographic regions with no legitimate user base for your application. Test all bot blocking rules in Count mode for 48 hours before switching to Block to verify that automated monitoring tools, synthetic testing services, and legitimate API consumers are not caught by the rules.

How do I measure the effectiveness of my WAF rule changes?

Measure WAF rule effectiveness using CloudWatch metrics combined with WAF log analysis. In CloudWatch, view the AllowedRequests, BlockedRequests, and CountedRequests metrics per rule to see the volume of traffic each rule is processing. Track the block rate as BlockedRequests divided by (AllowedRequests + BlockedRequests) before and after rule changes — a rule tuning change that reduces the block rate from 5% to 0.3% while maintaining the same CountedRequests volume suggests the false positive rate was reduced without losing detection coverage. For detecting whether your WAF is missing real attacks, review the allowed requests for attack patterns using Athena queries against the WAF logs: SELECT httprequest.uri, httprequest.httpmethod, httprequest.httpversion FROM waf_logs WHERE action='ALLOW' AND httprequest.uri LIKE '%union%select%' to find SQL injection attempts that bypassed the WAF. Track WAF tuning changes in a changelog with before/after metrics so you can correlate rule changes with application error rates and security event rates over time.

Sources & references

  1. AWS WAF Developer Guide
  2. OWASP ModSecurity Core Rule Set
  3. AWS WAF Managed Rule Groups
  4. AWS WAF Log Analysis with Athena

Free resources

25
Free download

Critical CVE Reference Card 2025–2026

25 actively exploited vulnerabilities with CVSS scores, exploit status, and patch availability. Print it, pin it, share it with your SOC team.

No spam. Unsubscribe anytime.

Free download

Ransomware Incident Response Playbook

Step-by-step 24-hour IR checklist covering detection, containment, eradication, and recovery. Built for SOC teams, IR leads, and CISOs.

No spam. Unsubscribe anytime.

Free newsletter

Get threat intel before your inbox does.

50,000+ security professionals read Decryption Digest for early warnings on zero-days, ransomware, and nation-state campaigns. Free, daily, no spam.

Unsubscribe anytime. We never sell your data.

Eric Bang
Author

Founder & Cybersecurity Evangelist, Decryption Digest

Cybersecurity professional with expertise in threat intelligence, vulnerability research, and enterprise security. Covers zero-days, ransomware, and nation-state operations for 50,000+ security professionals every morning.

Black Hat Giveaway

Win a $2,495 Black Hat pass.

Full-access to Black Hat USA 2026 in Las Vegas. Subscribe free to enter.

Joins Decryption Digest daily briefing. Unsubscribe anytime.

Giveaway: Black Hat USA 2026 Full-Access Pass ($2,495 value)

Details →
Daily Briefing

Subscribe to enter the giveaway

Every subscriber is automatically entered. You also get daily threat intel every morning: zero-days, ransomware, and nation-state campaigns. Free. No spam.

Already subscribed? You're already entered.

Giveaway

Win a $2,495 Black Hat USA 2026 pass.