AWS Security Blog

How to Use AWS CloudFormation to Automate Your AWS WAF Configuration with Example Rules and Match Conditions

Note from July 4, 2017: The solution in this post has been integrated into AWS WAF Security Automations, and AWS maintains up-to-date solution code in the companion GitHub repository.

 

AWS WAF is a web application firewall that integrates closely with Amazon CloudFront (AWS’s content delivery network [CDN]). AWS WAF gives you control to allow or block traffic to your web applications by, for example, creating custom rules that block common attack patterns.

We recently announced AWS CloudFormation support for all current features of AWS WAF. This enables you to leverage CloudFormation templates to configure, customize, and test AWS WAF settings across all your web applications. Using CloudFormation templates can help you reduce the time required to configure AWS WAF. In this blog post, I will show you how to use CloudFormation to automate your AWS WAF configuration with example rules and match conditions.

AWS WAF overview

If you are not familiar with AWS WAF configurations, let me try to catch you up quickly. AWS WAF consists of three main components: a web access control list (web ACL), rules, and filters (also known as a match set). A web ACL is associated with a given CloudFront distribution. Each web ACL is a collection of one or more rules, and each rule can have one or more match conditionswhich are composed of one or more filters. The filters inspect components of the request (such as its headers or URI) to match for certain match conditions.

Solution overview

The solution in this blog post uses AWS CloudFormation in an automated fashion to provision, update, and optionally delete the components that form the AWS WAF solution. The CloudFormation template will deploy the following rules and conditions as part of this solution:

  • A manual IP rule that contains an empty IP match set that must be updated manually with IP addresses to be blocked.
  • An auto IP rule that contains an empty IP match condition for optionally implementing an automated AWS Lambda function, such as is shown in How to Import IP Address Reputation Lists to Automatically Update AWS WAF IP Blacklists and How to Use AWS WAF to Block IP Addresses That Generate Bad Requests.
  • A SQL injection rule and condition to match SQL injection-like patterns in URI, query string, and body.
  • A cross-site scripting rule and condition to match Xss-like patterns in URI and query string.
  • A size-constraint rule and condition to match requests with URI or query string >= 8192 bytes which may assist in mitigating against buffer overflow type attacks.
  • ByteHeader rules and conditions (split into two sets) to match user agents that include spiders for non–English-speaking countries that are commonly blocked in a robots.txt file, such as sogou, baidu, and etaospider, and tools that you might choose to monitor use of, such as wget and cURL. Note that the WordPress user agent is included because it is used commonly by compromised systems in reflective attacks against non–WordPress sites.
  • ByteUri rules and conditions (split into two sets) to match request strings containing install, update.php, wp-config.php, and internal functions including $password, $user_id, and $session.
  • A whitelist IP condition (empty) is included and added as an exception to the ByteURIRule2 rule as an example of how to block unwanted user agents, unless they match a list of known good IP addresses.

All example rules configured by the template as part of the solution will count requests that match the rules for you to test with your web application. This template makes use of CloudFormation to provide a modular, manageable method of creating and updating nested stacks. A nested stack aligns with CloudFormation best practices to separate common components for reuse and ensure you do not reach the template body size limit, which is currently 51,200 bytes. All rules and conditions in this CloudFormation template are referenced with a resource reference number internal to the stack for each resource (for example, ByteBodyCondition1), so you can easily duplicate and extend each component. As with any example CloudFormation template, you can edit and reuse the template to suit your needs.

The following architecture diagram shows the overview of this solution, which consists of a single web ACL and multiple rules with match conditions:

Architecture diagram of the solution in this post

Descriptions of key details in the preceding diagram are as follows:

  1. Requests are resolved by DNS to CloudFront, configured with Web ACL to filter all requests.
  2. AWS WAF Web ACL evaluates each request with configured rules containing conditions.
  3. If a request matches a block condition, the request results in returning an HTTP 403 error (forbidden) to the client computer. If a request matches a count rule, the requests are served.
  4. The origin configured in CloudFront serves allowed or counted requests.

Deploying the solution

Prerequisites

The following deployment steps assume that you already have a CloudFront distribution that you use to deliver content for your web applications. If you do not already have a CloudFront distribution, see Creating or Updating a Web Distribution Using the CloudFront Console. This solution also uses CloudFormation to simplify the provisioning process. For more information, see What is AWS CloudFormation?

Step 1: Create the example configuration CloudFormation stack

  1. To start the wizard that creates a CloudFormation stack, choose the link for the region in which you want to create AWS resources:
  1. If you are not already signed in to the AWS Management Console, sign in when prompted.
  2. On the Select Template page, choose Next.
  3. On the Specify Details page, specify the following values:
    • Stack name – You can use the default name AWSWafSample, or you can change the name. The stack name cannot contain spaces and must be unique within your AWS account.
    • WAF Web ACL Name – Specify a name for the web ACL that CloudFormation will create. The name that you specify is also used as a prefix for the match conditions and rules that CloudFormation will create, so you can easily find all of the related objects.
    • Action For All Rules – Specify the action for all rules. The default of COUNT will pass all requests and monitor, and BLOCK will block all requests that match.
    • White List CIDR – Specify a single IP range that will be allowed to bypass all rules in CIDR notation. Note that only /8, /16, /24, and /32 are accepted. For a single IP you would enter x.x.x.x/32, for example.
    • Max Size of URI – Select from the list an acceptable size limit for the URI of a request.
    • Max Size of Query String – Select from the list an acceptable size limit for the query string of a request.
  1. Choose Next.
  2. (Optional) On the Options page, enter tags and advanced settings, or leave the fields blank. Choose Next.
  3. On the Review page, review the configuration and then choose Create. CloudFormation then creates the AWS WAF resources.

Step 2: Update your CloudFront distribution settings

After CloudFormation creates the AWS WAF stack, associate the CloudFront distribution with the new AWS WAF web ACL.

To associate your CloudFront distribution with AWS WAF:

  1. Open the CloudFront console.
  2. In the top pane of the console, select the distribution for which you want AWS WAF to monitor requests. (If you do not already have a distribution, see Getting Started with CloudFront.)
  3. In the Distribution Settings pane, choose the General tab, and then choose Edit.
  4. In the AWS WAF Web ACL list, choose the web ACL that CloudFormation created for you in Step 1.
  5. Choose Yes, Edit to save your changes.

Step 3: (Optional) Delete your CloudFormation stack

If you want to delete the CloudFormation stack created in the previous steps (including example rules and match conditions):

  1. Open the CloudFormation console.
  2. Select the check box for the stack; the default name is AWSWafSample
  3. Choose Delete Stack from the Actions drop-down menu.
  4. Choose Yes, Delete to confirm.
  5. To track the progress of the stack deletion, select the check box for the stack, and choose the Events tab in the bottom pane.

Testing the solution

After creating the example CloudFormation stack (Step 1) and associating the AWS WAF web ACL with a CloudFront distribution (Step 2), you can monitor the web requests and determine if the rules require modification to suit your web application.

In the AWS WAF console, you can view a sample of the requests that CloudFront has forwarded to AWS WAF for inspection. For each sampled request, you can view detailed information about the request, such as the originating IP address and the headers included in the request. You can also view which rule the request matched, and whether the rule is configured to allow or block requests.

To view a sample of the web requests that CloudFront has forwarded to AWS WAF:

  1. Sign in to the AWS WAF console.
  2. In the navigation pane, click the name of the web ACL for which you want to view requests.
  3. In the right pane, choose the Requests tab. The Sampled requests table displays the following values for each request:
    • Source IP – Either the IP address that the request originated from or, if the viewer used an HTTP proxy or a load balancer to send the request, the IP address of the proxy or load balancer.
    • URI – The part of a URL that identifies a resource (for example, /images/daily-ad.jpg).
    • Matches rule – The first rule in the web ACL for which the web request matched all of the match conditions. If a web request does not match all of the conditions in any rule in the web ACL, the value of Matches rule is Default. Note that when a web request matches all of the conditions in a rule and the action for that rule is Count, AWS WAF continues inspecting the web request based on subsequent rules in the web ACL. In this case, a web request could appear twice in the list of sampled requests: once for the rule that has an action of Count, and again for a subsequent rule or the default action.
    • Action – Whether the action for the corresponding rule is Allow, Block, or Count.
    • Time – The time when AWS WAF received the request from CloudFront.
  1. To refresh the list of sample requests, choose Get new samples.

You may also want to analyze your CloudFront or web application log files for bots, scrapers, or generally unwanted behavior, and modify the rules and match conditions to block them. For further information about CloudFront logs, see Access Logs.

Finally, to enforce blocking of malicious requests for all rules:

  1. Open the CloudFormation console.
  2. Select the check box for the master stack. The default name is AWSWafSample.
  3. Choose Update Stack from the Actions drop-down menu.
  4. Choose Use Current Template and Next.
  5. Choose BLOCK for Actions for All Rules.
  6. Accept changes and choose Next.
  7. To track the progress of the stack update, select the check box for the stack, and choose the Events tab in the bottom pane.

A zipped version of the CloudFormation templates for the example stack and other AWS WAF example solutions are available in our GitHub repository: aws-waf-sample repository. For a solution that combines this and other AWS WAF automation solutions into a deployable CloudFormation template, see AWS WAF Security Automations.

Summary

This blog post has shown you how to use CloudFormation to automate the configuration of a basic set of rules and match conditions to get started with AWS WAF. If you would like to see more sample rule sets for a specific platform or application, or if you have a comment about this blog post, submit a comment in the “Comments” section below. If you have questions about this blog post, please start a new thread on the AWS WAF forum.

– Ben