Introduction to AWS WAF

AWS WAF (Web Application Firewall) is a security service that helps protect your web applications from common web exploits that could affect application availability, compromise security, or consume excessive resources. AWS WAF gives you control over which traffic to allow or block to your web applications by defining customizable web security rules.

Key Concepts

  1. Web ACLs (Web Access Control Lists):

    • A Web ACL is a set of rules that define the conditions under which web requests are allowed or blocked.
    • Each Web ACL can be associated with one or more AWS resources, such as Amazon CloudFront distributions, Application Load Balancers, or API Gateway stages.
  2. Rules:

    • Rules are the building blocks of a Web ACL. They define the conditions that incoming web requests must meet to be allowed or blocked.
    • Rules can be based on IP addresses, HTTP headers, HTTP body, URI strings, SQL injection, cross-site scripting (XSS), and more.
  3. Rule Groups:

    • Rule Groups are collections of rules that you can reuse across multiple Web ACLs.
    • AWS provides managed rule groups that are maintained and updated by AWS.
  4. Conditions:

    • Conditions specify the criteria that web requests must meet to trigger a rule. Conditions can include IP match conditions, string match conditions, regex match conditions, and more.

Setting Up AWS WAF

Step 1: Create a Web ACL

  1. Navigate to the AWS WAF Console:

    • Open the AWS Management Console and navigate to the AWS WAF service.
  2. Create a Web ACL:

    • Click on "Create web ACL."
    • Provide a name for your Web ACL and select the AWS resource to associate it with (e.g., CloudFront distribution, Application Load Balancer, or API Gateway).
  3. Add Rules:

    • Add rules to your Web ACL by selecting from predefined rule groups or creating custom rules.
    • Define the conditions for each rule and specify whether to allow or block requests that match the conditions.
  4. Review and Create:

    • Review your Web ACL configuration and click "Create."

Step 2: Associate the Web ACL with AWS Resources

  1. Select Resources:

    • In the Web ACL configuration, select the AWS resources (e.g., CloudFront distributions, Application Load Balancers) that you want to protect with the Web ACL.
  2. Apply the Web ACL:

    • Apply the Web ACL to the selected resources.

Practical Example

Let's create a simple Web ACL that blocks requests from a specific IP address.

import boto3

# Initialize a session using Amazon WAF
client = boto3.client('waf')

# Create a Web ACL
response = client.create_web_acl(
    Name='example-web-acl',
    MetricName='exampleWebACL',
    DefaultAction={'Type': 'ALLOW'},
    ChangeToken='string',  # Obtain this from get_change_token() API call
    Tags=[
        {
            'Key': 'Name',
            'Value': 'example-web-acl'
        },
    ]
)

web_acl_id = response['WebACL']['WebACLId']

# Create an IP set
response = client.create_ip_set(
    Name='example-ip-set',
    ChangeToken='string',  # Obtain this from get_change_token() API call
    Tags=[
        {
            'Key': 'Name',
            'Value': 'example-ip-set'
        },
    ]
)

ip_set_id = response['IPSet']['IPSetId']

# Update the IP set with the IP address to block
response = client.update_ip_set(
    IPSetId=ip_set_id,
    ChangeToken='string',  # Obtain this from get_change_token() API call
    Updates=[
        {
            'Action': 'INSERT',
            'IPSetDescriptor': {
                'Type': 'IPV4',
                'Value': '192.0.2.44/32'
            }
        },
    ]
)

# Create a rule to block the IP address
response = client.create_rule(
    Name='block-ip-rule',
    MetricName='blockIPRule',
    ChangeToken='string',  # Obtain this from get_change_token() API call
    Tags=[
        {
            'Key': 'Name',
            'Value': 'block-ip-rule'
        },
    ]
)

rule_id = response['Rule']['RuleId']

# Update the rule with the IP set
response = client.update_rule(
    RuleId=rule_id,
    ChangeToken='string',  # Obtain this from get_change_token() API call
    Updates=[
        {
            'Action': 'INSERT',
            'Predicate': {
                'Negated': False,
                'Type': 'IPMatch',
                'DataId': ip_set_id
            }
        },
    ]
)

# Associate the rule with the Web ACL
response = client.update_web_acl(
    WebACLId=web_acl_id,
    ChangeToken='string',  # Obtain this from get_change_token() API call
    Updates=[
        {
            'Action': 'INSERT',
            'ActivatedRule': {
                'Priority': 1,
                'RuleId': rule_id,
                'Action': {
                    'Type': 'BLOCK'
                }
            }
        },
    ]
)

Practical Exercise

Exercise: Create a Web ACL to Block SQL Injection Attacks

  1. Create a Web ACL:

    • Name: sql-injection-web-acl
    • Default Action: ALLOW
  2. Create a Rule:

    • Name: block-sql-injection
    • Condition: SQL injection match condition
  3. Associate the Rule with the Web ACL:

    • Action: BLOCK
  4. Apply the Web ACL to an AWS Resource:

    • Resource: Select an existing CloudFront distribution or Application Load Balancer.

Solution:

import boto3

# Initialize a session using Amazon WAF
client = boto3.client('waf')

# Create a Web ACL
response = client.create_web_acl(
    Name='sql-injection-web-acl',
    MetricName='sqlInjectionWebACL',
    DefaultAction={'Type': 'ALLOW'},
    ChangeToken='string',  # Obtain this from get_change_token() API call
    Tags=[
        {
            'Key': 'Name',
            'Value': 'sql-injection-web-acl'
        },
    ]
)

web_acl_id = response['WebACL']['WebACLId']

# Create a SQL injection match condition
response = client.create_sql_injection_match_set(
    Name='sql-injection-match-set',
    ChangeToken='string',  # Obtain this from get_change_token() API call
    Tags=[
        {
            'Key': 'Name',
            'Value': 'sql-injection-match-set'
        },
    ]
)

sql_injection_match_set_id = response['SqlInjectionMatchSet']['SqlInjectionMatchSetId']

# Update the SQL injection match set with a condition
response = client.update_sql_injection_match_set(
    SqlInjectionMatchSetId=sql_injection_match_set_id,
    ChangeToken='string',  # Obtain this from get_change_token() API call
    Updates=[
        {
            'Action': 'INSERT',
            'SqlInjectionMatchTuple': {
                'FieldToMatch': {
                    'Type': 'QUERY_STRING'
                },
                'TextTransformation': 'URL_DECODE'
            }
        },
    ]
)

# Create a rule to block SQL injection
response = client.create_rule(
    Name='block-sql-injection',
    MetricName='blockSQLInjection',
    ChangeToken='string',  # Obtain this from get_change_token() API call
    Tags=[
        {
            'Key': 'Name',
            'Value': 'block-sql-injection'
        },
    ]
)

rule_id = response['Rule']['RuleId']

# Update the rule with the SQL injection match set
response = client.update_rule(
    RuleId=rule_id,
    ChangeToken='string',  # Obtain this from get_change_token() API call
    Updates=[
        {
            'Action': 'INSERT',
            'Predicate': {
                'Negated': False,
                'Type': 'SqlInjectionMatch',
                'DataId': sql_injection_match_set_id
            }
        },
    ]
)

# Associate the rule with the Web ACL
response = client.update_web_acl(
    WebACLId=web_acl_id,
    ChangeToken='string',  # Obtain this from get_change_token() API call
    Updates=[
        {
            'Action': 'INSERT',
            'ActivatedRule': {
                'Priority': 1,
                'RuleId': rule_id,
                'Action': {
                    'Type': 'BLOCK'
                }
            }
        },
    ]
)

Common Mistakes and Tips

  • Change Tokens: Always ensure you have the latest change token before making updates. Use the get_change_token() API call to retrieve it.
  • Rule Priority: When adding multiple rules to a Web ACL, ensure that the priority is set correctly to avoid unintended blocking or allowing of requests.
  • Testing: Always test your Web ACLs in a staging environment before applying them to production to avoid accidental blocking of legitimate traffic.

Conclusion

In this section, you learned about AWS WAF and how to set up a Web ACL to protect your web applications from common web exploits. You also practiced creating a Web ACL to block SQL injection attacks. Understanding and implementing AWS WAF is crucial for maintaining the security and availability of your web applications. In the next module, we will explore monitoring and management tools in AWS to help you keep track of your resources and their performance.

© Copyright 2024. All rights reserved