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
-
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.
-
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.
-
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.
-
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
-
Navigate to the AWS WAF Console:
- Open the AWS Management Console and navigate to the AWS WAF service.
-
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).
-
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.
-
Review and Create:
- Review your Web ACL configuration and click "Create."
Step 2: Associate the Web ACL with AWS Resources
-
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.
-
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
-
Create a Web ACL:
- Name:
sql-injection-web-acl
- Default Action:
ALLOW
- Name:
-
Create a Rule:
- Name:
block-sql-injection
- Condition: SQL injection match condition
- Name:
-
Associate the Rule with the Web ACL:
- Action:
BLOCK
- Action:
-
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.