Implementing and Securing OWASP Juice Shop with AWS WAF
This project demonstrates AWS security engineering through the implementation and optimization of OWASP Juice Shop with WAF protection. The implementation follows an approach to deploy, test, and optimize security controls using Infrastructure as Code, automated testing, real-time analytics, and emergency response capabilities.
Our primary objectives include:
- Deploy security infrastructure using Infrastructure as Code
- Implement WAF protection with AWS WAF v2 and managed rule sets
- Build real-time security analytics
- Create automated CI/CD security pipeline with guardrails and compliance scanning
- Develop emergency response capabilities with sub-30-second threat mitigation
Tools
- AWS ECS Fargate - Container orchestration and application hosting
- AWS Application Load Balancer - Traffic distribution and SSL termination
- AWS WAF v2 - Web application firewall and edge protection
- Terraform - Infrastructure as Code automation and configuration management
- Amazon Kinesis Data Firehose - Real-time data streaming to S3
- Amazon Athena - Serverless SQL analytics for WAF logs
- Amazon S3 - Log storage and data lake functionality
- Amazon CloudWatch - Real-time monitoring and dashboard visualization
- GitHub Actions - CI/CD pipeline automation
- tfsec - Static security analysis for Terraform
- Checkov - Infrastructure security scanning
Phase 1: Infrastructure Deployment
Step 1: Terraform Infrastructure Setup
The deployment establishes a multi-layered architecture using Infrastructure as Code. The implementation creates scalable, secure, and maintainable infrastructure components.
git clone https://github.com/ToluGIT/aws-waf-takeithome.git
cd aws-waf-takeithome
terraform init
terraform plan -var-file="terraform.tfvars"
terraform apply -var-file="terraform.tfvars"
Review the terraform.tfvars
file for parameters such as allowed_cidr_blocks
that can be modified according to specific requirements.
Step 2: WAF Module Implementation
The WAF implementation follows a modular design pattern, creating reusable components for security rules and configurations:
# terraform/modules/edge_waf/main.tf
resource "aws_wafv2_web_acl" "main" {
name = var.waf_name
scope = "CLOUDFRONT"
default_action {
allow {}
}
# AWS Managed Rules - Common Rule Set
rule {
name = "AWSManagedRulesCommonRuleSet"
priority = 1
override_action {
none {}
}
statement {
managed_rule_group_statement {
name = "AWSManagedRulesCommonRuleSet"
vendor_name = "AWS"
}
}
visibility_config {
cloudwatch_metrics_enabled = true
metric_name = "CommonRuleSetMetric"
sampled_requests_enabled = true
}
}
Important: If attaching to an ALB/ECS, set WAF scope = REGIONAL in the same region. If using CloudFront, scope = CLOUDFRONT and create/manage it in us-east-1.
Step 3: ECS Infrastructure Verification
The ECS service deployment confirms proper multi-AZ distribution, healthy task status, and Application Load Balancer connectivity:
Step 4: Application Verification and Baseline Testing
Application verification confirms successful deployment and establishes baseline functionality before security testing:
Phase 2: Security Testing and Analysis
Step 1: Security Testing Framework Development
The testing combines positive tests (legitimate traffic) with negative tests (attack vectors).
Positive Test Cases (Expected to Pass):
basic_homepage
: GET /products_page
: GET /#/productslogin_page
: GET /#/loginlegitimate_search
: GET /rest/products/search?q=apple
Negative Test Cases (Expected to Block):
juice_shop_sqli
: GET /rest/products/search?q=’ OR 1=1—classic_sqli_union
: GET /rest/products/search?q=apple’ UNION SELECT * FROM users—xss_script_tag
: GET /rest/products/search?q=path_traversal
: GET /../../etc/passwd
Step 2: Initial Security Assessment
Manual testing of path traversal functionality reveals WAF blocking:
Step 3: Automated Testing Execution
Execute security testing using the automated framework:
# Install Python dependencies
pip3 install -r requirements.txt
python3 scripts/smoke_test.py --url $(terraform output -raw juice_shop_url)
The testing framework implementation:
import requests
import json
from datetime import datetime
class SecurityTester:
def __init__(self, base_url):
self.base_url = base_url
self.results = {"positive": [], "negative": []}
def test_positive_cases(self):
"""traffic that should be allowed"""
positive_tests = [
{"name": "Homepage Access", "method": "GET", "path": "/"},
{"name": "Product Listing", "method": "GET", "path": "/rest/products"},
{"name": "User Login", "method": "POST", "path": "/rest/user/login",
"data": {"email": "test@test.com", "password": "test123"}},
{"name": "Product Search", "method": "GET", "path": "/rest/products/search?q=apple"}
]
def test_negative_cases(self):
"""attacks that should be blocked"""
attack_tests = [
{"name": "SQL Injection - Classic", "payload": "' OR 1=1--"},
{"name": "SQL Injection - Juice Shop", "payload": "')) OR true--"},
{"name": "XSS - Script Tag", "payload": "<script>alert('xss')</script>"},
{"name": "Command Injection", "payload": "; cat /etc/passwd"},
{"name": "Path Traversal", "payload": "../../../../../etc/passwd"},
{"name": "Remote File Inclusion", "payload": "http://evil.com/shell.php"}
]
Step 4: Initial Results Analysis
The initial testing revealed security gaps with 50% effectiveness:
Positive Tests: 4/4 passed (All legitimate traffic allowed)
Negative Tests: 3/10 passed (Only 3 attacks blocked)
GAPS IDENTIFIED:
Path traversal attacks: NOT BLOCKED
Command injection: NOT BLOCKED
Large headers: NOT BLOCKED
Step 5: WAF Configuration Optimization
Root cause analysis identified that managed rules apply their vendor action unless you override. Start new rules in Count for safe tuning, then switch to Block. The configuration fix enables proper attack blocking:
# terraform/modules/edge_waf/main.tf - Remove rule overrides
resource "aws_wafv2_web_acl" "main" {
# ... existing configuration ...
rule {
name = "AWSManagedRulesSQLiRuleSet"
priority = 2
# override_action { none {} } means "no override" - let managed rules apply their vendor action
override_action {
none {}
}
statement {
managed_rule_group_statement {
name = "AWSManagedRulesSQLiRuleSet"
vendor_name = "AWS"
}
}
}
}
Step 6: Security Effectiveness Validation
After tuning, 100% of our test suite was blocked:
Which demonstrates the importance of configuration validation in security effectiveness measurement.
Phase 3: Security Analytics Pipeline
Step 1: Athena Database Configuration
Navigate to Amazon Athena and launch the query editor to establish the analytics foundation:
CREATE DATABASE IF NOT EXISTS waf_analytics;
Step 2: Query Results Location Setup
Configure S3 results location for Athena query processing. Set the query results location to the existing WAF logs bucket:
s3://juice-shop-waf-logs-xxxxxx/athena-results/
Step 3: External Table Creation
Create Athena external table for WAF log analysis. Modify the create_table.sql
query with the correct S3 bucket location:
-- athena/queries/create_table.sql
LOCATION 's3://juice-shop-waf-logs-2od5y8gt/'
'storage.location.template'='s3://juice-shop-waf-logs-2od5y8gt/year=${year}/month=${month}/day=${day}/hour=${hour}/'
Retrieve the S3 bucket name using:
terraform output s3_waf_logs_bucket
Step 4: Security KPI Analysis
Execute KPI metrics queries to generate security analytics:
The simple_kpi_metrics_single.sql
query returns CORE_METRICS and TOP_ATTACK_VECTORS views for the last 24 hours
Step 5: Real-Time Monitoring Implementation
Configure CloudWatch dashboard and WAF console monitoring for visibility:
CloudWatch WAF Dashboard:
- Navigate: CloudWatch → Dashboards → select the WAF dashboard
- Terraform provisions dashboard named
juice-shop-waf-dashboard
- Panels include: Allowed vs Blocked requests, BlockedRequests by rule
WAF Console Monitoring:
- Navigate: WAF → Web ACLs →
juice-shop-web-acl
→ Traffic Overview
Note: WAF logs to S3 via Firehose buffer (approximately 5 minutes or 5 MB). Expect short delays before data appears in Athena.
Phase 4: CI/CD Security Pipeline
Step 1: GitHub Actions Workflow Implementation
The PR-based GitHub Actions pipeline (.github/workflows/edge-ci.yml
) enforces security guardrails and produces deployable plans with approval gates:
Workflow Components:
- Change Detection: Executes only when Terraform, scripts, or workflow files change
- Security Scans: tfsec and Checkov analyze terraform/ directory and upload SARIF results
- Terraform Planning: Initializes Terraform, executes
terraform plan
, and posts summary to PR comments - Cost Analysis: Infracost calculates cost deltas (soft-fail for demonstration)
- Manual Approval Gate: Environment
production-approval
requires approval before apply - Gated Apply: Post-approval execution of
terraform apply -auto-approve
The pipeline integrates static security analysis tools:
- tfsec: Terraform static security analysis with SARIF output
- Checkov: Infrastructure security scanning with policy enforcement
- GitHub Security Tab: Automated security findings integration
Phase 5: Emergency Response with Sub-30 Second Threat Mitigation
Step 1: Emergency Blocking Script Development
The emergency response automation (scripts/push_block.py
) enables rapid threat mitigation through programmatic WAF rule deployment:
# scripts/push_block.py - Emergency response automation
import boto3
import json
import sys
import ipaddress
from datetime import datetime, timezone
class EmergencyWAFBlocker:
def __init__(self, web_acl_name, web_acl_id, scope='CLOUDFRONT'):
self.waf_client = boto3.client('wafv2')
self.web_acl_name = web_acl_name
self.web_acl_id = web_acl_id
self.scope = scope
def validate_ip(self, ip_input):
"""Validate IP address or CIDR range"""
try:
# Handle both single IPs and CIDR ranges
ipaddress.ip_network(ip_input, strict=False)
return True
except ValueError:
return False
def get_web_acl_lock_token(self):
"""Get current lock token for WAF updates"""
try:
response = self.waf_client.get_web_acl(
Name=self.web_acl_name,
Scope=self.scope,
Id=self.web_acl_id
)
return response['LockToken'], response['WebACL']
except Exception as e:
raise Exception(f"Failed to get WAF lock token: {str(e)}")
def create_ip_block_rule(self, ip_address, rule_name=None, dry_run=True):
"""Create IP blocking rule"""
# Validate IP address
if not self.validate_ip(ip_address):
raise ValueError(f"Invalid IP address or CIDR: {ip_address}")
# Generate rule name if not provided
if not rule_name:
timestamp = datetime.now(timezone.utc).strftime("%Y%m%d_%H%M%S")
clean_ip = ip_address.replace('.', '_').replace('/', '_')
rule_name = f"EmergencyBlock_IP_{clean_ip}_{timestamp}"
# Prepare the new rule
new_rule = {
'Name': rule_name,
'Priority': 10, # High priority for emergency rules
'Statement': {
'IPSetReferenceStatement': {
'ARN': f'arn:aws:wafv2:us-east-1:{boto3.client("sts").get_caller_identity()["Account"]}:global/ipset/{rule_name}_ipset/{rule_name}'
}
},
'Action': {
'Block': {}
},
'VisibilityConfig': {
'SampledRequestsEnabled': True,
'CloudWatchMetricsEnabled': True,
'MetricName': rule_name
}
}
Step 2: Emergency Response Testing and Validation
Execute testing of emergency blocking capabilities:
# Test IP blocking (dry-run mode)
python scripts/push_block.py --ip 192.168.1.100/32 --web-acl-id $(terraform output waf_web_acl_arn) --dry-run
# Test CIDR range blocking (dry-run mode)
python scripts/push_block.py --ip 10.0.0.0/24 --web-acl-id $(terraform output waf_web_acl_arn) --dry-run
# Test URI pattern blocking (dry-run mode)
python scripts/push_block.py --uri "/admin/*" $(terraform output waf_web_acl_arn) --dry-run
Step 3: IP Address Verification and Testing
Verify current IP address using AWS service:
curl https://checkip.amazonaws.com
Step 4: Dry Run Emergency Blocking
Execute dry run test to validate blocking functionality:
python scripts/push_block.py --ip x.x.x.x/32 --web-acl-id $(terraform output waf_web_acl_arn) --dry-run
Step 5: Production Emergency Blocking Execution
Execute emergency blocking without dry-run flag:
python scripts/push_block.py --ip x.x.x.x/32 --web-acl-id $(terraform output waf_web_acl_arn)
Results demonstrate sub-30-second response times:
Step 6: Verification of Rule Enforcement
Confirm rule enforcement through AWS WAF Console:
Verify blocking effectiveness through application access testing:
Conclusion
Summary of Achievements
This project demonstrates implementation of security infrastructure with measurable results and operational excellence.
Infrastructure Automation: Complete environment deployment using Infrastructure as Code with modular, reusable components adaptable across different applications and environments.
Evidence-Based Security Optimization: Improvement from 50% to 100% security effectiveness through iterative testing, analysis, and rule refinement based on actual attack patterns rather than theoretical threats.
Operational Resilience: Emergency response capabilities with sub-30-second deployment times, safety controls, and detailed audit logging enabling rapid threat mitigation without operational risk.
Lessons Learned
Configuration Validation is Critical: The difference between 50% and 100% security effectiveness resulted from a single configuration parameter. Managed rules apply their vendor action unless you override - proper configuration ensures expected blocking behavior.
Measurement Enables Optimization: Quantifiable security metrics provide the foundation for systematic improvement and evidence-based decision making in security engineering.
Automation Reduces Risk: Emergency response automation eliminates manual processes during critical incidents, reducing response time from minutes to seconds while maintaining safety controls.