AWS Builder Center
Filtering and Blocking Web Attacks with AWS WAF: SQL Injection, XSS, and Custom Security Rules

Filtering and Blocking Web Attacks with AWS WAF: SQL Injection, XSS, and Custom Security Rules

The lab focused on a deliberately vulnerable OWASP Juice Shop application. I examined its HTTP requests, tested for SQL injection and cross-site scripting (XSS), configured a web access control list (web ACL), and verified how the security rules handled subsequent requests.

Web application security involves more than identifying vulnerabilities. It also requires implementing controls that can detect and block malicious requests before they reach the application.
During an AWS Builder Lab titled Filtering and Blocking Web Incursions with AWS WAF, I explored how common web application vulnerabilities can be identified using OWASP Zed Attack Proxy (ZAP), and how AWS Web Application Firewall (AWS WAF) can help mitigate them through managed rule groups and custom rules.
The lab focused on a deliberately vulnerable OWASP Juice Shop application. I examined its HTTP requests, tested for SQL injection and cross-site scripting (XSS), configured a web access control list (web ACL), and verified how the security rules handled subsequent requests.
One of the most important findings was that managed WAF rules blocked several common attack patterns, but they did not prevent every form of unauthorized behavior. That demonstrated why application security requires multiple layers of protection rather than relying on a single control.

1. Understanding the Lab Environment

The exercise used an OWASP Juice Shop application hosted in an AWS environment. A separate EC2 instance, named PenTestingHost, provided the environment for conducting authorized security testing.
The main tools and services included:
  • OWASP ZAP: Used to intercept, inspect, and replay HTTP requests.
  • Firefox: Used to interact with the Juice Shop web application through the ZAP proxy.
  • Amazon EC2 and AWS Systems Manager Fleet Manager: Used to access the testing environment.
  • AWS WAF: Used to inspect web requests and apply rules that allow or block traffic.
  • AWS-managed rule groups: Used to detect common web attack patterns.
  • Custom WAF rules: Used to address a specific weakness that the managed protections did not block.
The objective was to understand the application’s weaknesses, introduce appropriate defensive controls, and test whether those controls produced the expected results.
All testing took place within the lab-provided environment and its intentionally vulnerable application.

2. Setting Up OWASP ZAP for Web Application Testing

I began by connecting to the PenTestingHost EC2 instance through AWS Systems Manager Fleet Manager and opening an RDP session.
After launching OWASP ZAP, I created a persistent session and used its Manual Explore feature to open the Juice Shop application in Firefox.
ZAP acted as an intercepting proxy between the browser and the application. This made it possible to inspect the requests generated by normal activities, such as searching for products, registering an account, and logging in.
These requests provided useful information about the application’s API endpoints and how user input was transmitted to the server.
For example, a product search generated a request to an endpoint resembling:
/rest/products/search?q=
The application also used an endpoint ending in /api/Users for user registration.
Understanding these requests was an important first step because web vulnerabilities frequently arise when applications process untrusted input without sufficient validation or protection.

3. Reconnaissance and SQL Injection Testing

After generating several normal application requests, I used ZAP’s Search feature to locate the product-search request and open it in the Request Editor.
The lab demonstrated an error-based reconnaissance technique by modifying the search parameter with a boolean-based SQL injection test.
The application returned an unhandled exception, revealing that it used an SQLite database. More importantly, the response indicated that the search functionality was susceptible to SQL injection.
SQL injection occurs when an application improperly incorporates untrusted input into a database query. Depending on the implementation and database permissions, an attacker may be able to alter query logic, access unauthorized records, or interfere with application behavior.
The exposed error message was also a security concern. Detailed internal errors can reveal implementation information that helps an attacker understand the application.
Two lessons stood out from this exercise:
First, user input must be handled safely. Applications should use parameterized queries or prepared statements rather than constructing SQL queries through unsafe string concatenation.
Second, error handling matters. Production applications should return controlled error responses without exposing database details, internal exceptions, or implementation information.
The testing also showed why reconnaissance is valuable during an authorized security assessment: it can reveal weaknesses that are not apparent from the application’s normal interface.

4. Demonstrating a Stored Cross-Site Scripting Vulnerability

The next exercise focused on stored, or persisted, cross-site scripting.
Stored XSS occurs when an application accepts untrusted content, saves it, and later renders that content in a way that allows browser-side script execution.
Using the intercepted registration request, I examined how the application processed the submitted user details. The lab then demonstrated that a specially crafted input could be accepted and stored without adequate protection.
The successful test showed that the application was vulnerable to stored XSS.
This type of vulnerability can be especially serious because the affected content may be presented to other users. Depending on the application and the victim’s privileges, successful exploitation can lead to unauthorized actions or exposure of sensitive information.
The appropriate defenses include:
  • Context-aware output encoding when rendering user-controlled content.
  • Safe handling and validation of user input.
  • Avoiding unsafe HTML or JavaScript execution patterns.
  • Using appropriate browser security controls, including a well-designed Content Security Policy.
  • Testing every feature that accepts and subsequently displays user-supplied content.
Input validation is useful, but it is not a substitute for safe output handling. Data that is harmless in one context may become dangerous when inserted into HTML, an attribute, or JavaScript without the correct encoding.

5. Creating a Web ACL in AWS WAF

After identifying the weaknesses, I moved to the defensive portion of the lab.
In the AWS WAF console, I created a web access control list named JuiceShopACL and associated it with the lab’s ProtectedJuiceShop resource.
A web ACL is a collection of rules that AWS WAF evaluates against incoming web requests. Depending on the configured conditions and actions, a request can be allowed, blocked, or handled according to other supported actions.
I configured the web ACL with two AWS-managed rule groups:
  • Core rule set: Provides general-purpose protections against common web request attack patterns.
  • SQL databases: Detects request patterns associated with attacks against SQL database-backed applications, including SQL injection.
Managed rule groups are useful because AWS maintains predefined detection rules, reducing the amount of custom detection logic that an administrator must create and maintain.
The lab reported that the initial configuration consumed 900 out of 5,000 available web ACL capacity units (WCUs). WCUs represent the processing capacity required by a web ACL’s rules.
After creating the ACL, I reviewed its rule configuration and left the default rule priority unchanged.
However, adding managed rules was only the beginning. The next step was to determine whether they actually blocked the attack patterns identified during testing.

6. Testing the AWS WAF Managed Protections

I returned to OWASP ZAP and replayed the earlier requests against the protected application.
The results showed that the managed rule groups blocked the SQL injection and XSS test requests.
Security testResult observed in the lab
SQL injection against the product-search endpointBlocked with HTTP 403 Forbidden
SQL injection against the login endpointBlocked with HTTP 403 Forbidden
Stored XSS registration requestBlocked with HTTP 403 Forbidden
Registration request containing an administrative role assignmentAccepted despite the managed protections
The HTTP 403 responses showed that AWS WAF was denying the tested requests rather than allowing them to proceed normally through the protected web application.
This was a useful validation step. Configuring a security control does not automatically prove that it works as intended. Replaying the same test cases provided evidence of how the web ACL handled those requests.
However, the final test revealed an important limitation.

7. Identifying a Gap in the Managed Rules

The lab demonstrated that a registration request containing an administrative role assignment could still be accepted.
The request included an ordinary-looking JSON body with fields such as an email address and password, alongside a role value requesting administrative privileges.
The application accepted the request and returned a response showing that the newly created account had an administrative role.
This was a serious application-level authorization weakness.
The problem was not simply that a suspicious string had passed through the firewall. The application was allowing a user-controlled request to determine a privileged account attribute.
In a properly designed registration flow, a public user should not be able to grant themselves administrative privileges by supplying a role field in an HTTP request.
The server should assign roles according to trusted authorization logic, enforce access controls, and reject unauthorized attempts to modify privileged attributes.
This is an example of why a WAF should complement secure application design rather than replace it. A firewall can identify and block known malicious patterns, but it cannot reliably correct every authorization or business-logic vulnerability.

8. Building a Custom AWS WAF Rule

To address the specific behavior demonstrated in the lab, I created a custom rule in JuiceShopACL.
The rule was named:
CustomSQLiRuleForJuiceShop
Despite its name, its principal purpose in this exercise was to block requests to the user-registration endpoint when their bodies contained a particular administrative role assignment.
I configured the rule using an AND condition with two statements:
Statement 1: Inspect the URI path
  • Inspection field: URI path
  • Match type: Contains string
  • String to match: api/Users
Statement 2: Inspect the request body
  • Inspection field: Body
  • Oversize handling: Continue
  • Match type: Contains string
  • String to match: "role": "admin"
The combined condition was designed to match requests whose URI contained api/Users and whose inspected request body contained the specified role string.
The purpose of combining these conditions was to make the rule more specific than a rule that simply blocked every request containing the word admin.
This approach illustrates an important WAF design principle: rules should be scoped to the relevant endpoint and request characteristics wherever possible.
Broad rules can generate false positives by blocking legitimate requests. More specific rules can reduce that risk, although their effectiveness depends on how well the conditions represent the intended security policy.
There is also an important limitation to this particular lab configuration. The body inspection relies on a specific string representation. JSON whitespace, alternative formatting, different capitalization, or other ways of expressing the same data may affect whether a simple string match succeeds.
For production applications, the rule should be tested against realistic variations. Where appropriate, structured JSON inspection, application-side authorization checks, and regression testing provide stronger coverage than relying on one exact textual representation.
The lab also notes that the custom rule applies to requests passing through CloudFront. If the application server remains directly reachable through another path, that route could bypass this particular WAF protection. Network architecture should therefore prevent unauthorized direct access to the origin.

9. Testing the Custom Rule

After adding the custom rule, I returned to ZAP and repeated the administrative-role registration test.
This time, AWS WAF returned an HTTP 403 Forbidden response.
The result showed that the custom rule blocked the request pattern that had passed through the managed rule groups.
The overall test sequence demonstrated three useful stages:
  1. Identify weaknesses in the application through authorized testing.
  2. Apply managed WAF protections against common attack patterns.
  3. Create and validate a custom rule for a specific gap revealed by the tests.
The final result was a more targeted web ACL that blocked the demonstrated SQL injection and XSS requests and the tested administrative-role assignment request.
These results apply to the specific lab scenarios. They do not establish that every possible SQL injection, XSS, or privilege-escalation attempt would be blocked.

10. What This Lab Taught Me About Web Application Security

Several practical lessons stood out from this exercise.

Managed rules are a starting point, not the complete solution

AWS-managed rule groups provide useful baseline protection, but they cannot anticipate every application-specific weakness. Security teams must validate the rules against their applications and add targeted controls where necessary.

Authorization must be enforced by the application

The administrative-role test demonstrated that a user should never be trusted to assign their own privileges. The server must control role assignment and verify that each operation is authorized.

WAF rules should be tested, not merely configured

Replaying the same requests before and after introducing the controls made the results measurable. Testing also revealed a gap that would have remained unnoticed if the assessment had ended after the initial managed-rule configuration.

False positives and rule scope matter

A rule that is too broad may block legitimate users. A rule that is too narrow may miss relevant attack variations. Both the matching conditions and the resulting behavior need to be evaluated.

Defense in depth remains essential

A web ACL is only one part of a secure application architecture. Parameterized database queries, safe output encoding, secure authentication, server-side authorization, controlled error messages, and restricted access to application origins remain necessary.

Logging supports ongoing investigation

The lab concludes by recommending that WAF logging be enabled so that requests can be examined beyond the immediate test session. Depending on the deployment, AWS WAF logs can be delivered to supported destinations such as Amazon CloudWatch Logs, Amazon S3, or Amazon Data Firehose.
Logging makes it easier to investigate blocked requests, understand recurring attack patterns, and assess whether rule changes introduce unexpected behavior.

11. AWS Services and Tools Used

Service or toolRole in the exercise
Amazon EC2Hosted the authorized testing environment
AWS Systems Manager Fleet ManagerProvided access to the Windows testing instance
OWASP ZAPIntercepted and inspected HTTP requests
FirefoxInteracted with the test web application
OWASP Juice ShopServed as the deliberately vulnerable target application
AWS WAFInspected requests and enforced web ACL rules
AWS-managed rule groupsProvided baseline protection against common attack patterns
Custom WAF ruleBlocked the specific administrative-role request demonstrated in the lab

This AWS Builder Lab reinforced an important principle: effective web application security depends on identifying weaknesses, applying appropriate controls, and verifying their behavior through testing.
OWASP ZAP helped reveal how the application processed requests and exposed SQL injection and stored XSS weaknesses. AWS WAF then demonstrated how managed rules could block common attack patterns, while a custom rule addressed a specific request pattern that had passed through the initial protections.
The most valuable lesson was that a blocked attack request does not necessarily mean the underlying application is secure. WAF protections are useful, but secure database access, correct authorization logic, safe handling of user input, logging, and restricted origin access are equally important.
For anyone learning cloud security or working toward a cloud security role, this exercise provides a practical example of how application testing and AWS-native defensive controls can work together to reduce risk.
Lab reference: AWS Builder Lab — Filtering and Blocking Web Incursions with AWS WAF (SPL-TF-200-SIAWAF-1, Version 1.2.16). The findings described above are from the intentionally vulnerable lab environment.
Any opinions in this article are those of the individual author and may not reflect the opinions of AWS.
Enjoyed reading this content? Let the author know!

Your likes, comments, shares, and saves help creators reach more builders.

Loading recommendations

Loading article