To access material, start machines and answer questions login.
You begin your penetration test expecting a hardened web application, only to compromise it with a simple SQL injection. How? The Web Application Firewall (WAF) was absent, misconfigured, or bypassed. Despite being a staple of modern security architecture, WAFs are often misunderstood: they are usually treated as magic shields when, in fact, they are complex systems with strengths, limitations, and blind spots.

Learning Objectives
This room introduces WAFs for cyber security practitioners who are already familiar with network and web application security but have not yet explored how WAFs operate under the hood. After completing this room, you will learn about:
- The evolution of firewalls from basic packet filters
- How WAFs detect threats using signatures and behavioural analysis
- Fingerprinting WAFs in real engagements using passive and active techniques
- Analysing WAF rules and anticipating bypass opportunities
- Dissecting real-world rules from the OWASP Core Rule Set (CRS)
- Assessing WAF limitations
Prerequisites
Before going through this room, users are expected to have a good understanding of:
What does WAF stand for?
Set up your virtual environment
We have prepared a virtual machine with OWASP Wafcontrol, a dashboard for ModSecurity and OWASP Core Rule Set. You can start the VM by clicking the green Start Machine button below. To attach the target VM, you will need to start the AttackBox by clicking the Start AttackBox button below.
It should take a couple of minutes for both machines to be ready. In later tasks, you can try the different attacks against http://MACHINE_IP. To view how your attacks are blocked and logged, access http://MACHINE_IP:7000 using the credentials below.
Credentials
Only needed if you are using your own machine.
Using Firefox on the AttackBox, confirm that you can access the web page at http://MACHINE_IP.
Using the provided credentials, confirm that you can log in to the dashboard at http://MACHINE_IP:7000 using the credentials provided in this task.
Before we delve into the advanced solutions, let’s revisit the history of computer firewalls. In the early days of networked computing, security was often an afterthought. As organisations began connecting their internal networks to the outside world, specifically the Internet, they realised the need for a “bouncer” at the entrance. They needed a way to decide which traffic is allowed to enter and which is turned away. Considering the technology available at that time, the answer was the stateless packet filter.
Stateless Firewalls: The Gatekeeper with No Memory
As the name implies, a stateless packet filter or firewall is stateless; it is a gatekeeper with no memory. It operates at Layers 3 and 4 of the OSI model, where it can inspect IP addresses, TCP and UDP ports, some headers, and other protocols. This basic packet filter is entirely ignorant of the context of the traffic; every packet is judged in isolation. Think of a border agent looking at a child’s passport as if the child is travelling alone.
This security measure worked for a while until attackers realised that they could abuse the fact that it is stateless. In other words, an attacker would send a packet with the ACK flag set to trick the firewall into treating the packet as if it were part of an established connection. Because this firewall does not keep track of established connections, it may allow it to pass. It became clear that a more intelligent firewall was necessary.
Stateful Firewalls: Remembering the Conversation
By the mid-1990s, as attacks became increasingly complex, a new firewall model emerged: the stateful firewall. Unlike stateless firewalls, which inspect each packet in isolation, stateful firewalls keep track of active connections, which allows them to better judge a packet before letting it pass through. Think of it as the firewall being able to answer the question, “Does this packet belong to a legitimate ongoing conversation?”
Because they track ongoing sessions, forging a packet with an ACK flag set can no longer trick the firewall into treating it as if it were part of an established TCP connection. Moreover, out-of-sequence packets, among other anomalies, can be detected and dropped. In other words, if the firewall allows outbound traffic to port 443, an outside attacker cannot simply send a packet with a source port of 443, set the ACK flag, and trick the firewall into treating it as part of a legitimate ongoing connection. Being aware of established connections significantly improved the firewall’s efficiency.
Firewalls that Understand Layer 7
As the need for improved security increased, new firewall technologies emerged on the market. Before exploring Web Application Firewalls (WAFs) in the next task, let’s revisit three more types of firewalls:
- Application-Level Gateway (Proxy Firewall)
- Deep Packet Inspection (DPI) Firewall
- Next-Generation Firewall (NGFW)
Application-Level Gateway
The Application-Level Gateway (ALG) is also referred to as a Proxy Firewall. One way to think of it is like a protocol interpreter. It is like a diplomatic interpreter who listens to your message and repeats it, ensuring that it does not contain any hidden slurs or secret codes. Unlike stateful firewalls that merely track TCP connections, ALGs terminate incoming connections and initiate new ones on the client’s behalf. This setup provides them with complete visibility into application-layer protocols, such as HTTP and FTP, among others. Consequently, they can validate command syntax and sanitise payloads. While superseded mainly by more scalable technologies, ALGs have laid the conceptual groundwork for Layer 7 inspection, showing that to defend an application, one must speak its language.
Deep Packet Inspection Firewall
Stateful firewalls inspect IP addresses and ports; Deep Packet Inspection (DPI) firewalls examine the contents of the message itself. DPI goes beyond headers to scan the actual payload of packets, looking for telltale byte sequences of malware, peer-to-peer traffic, or encrypted command-and-control beacons. Crucially, DPI isn’t a standalone firewall architecture but a capability embedded within modern threat prevention systems. For example, it might flag a seemingly benign HTTP stream because its entropy matches that of known ransomware traffic, or block a disguised Tor connection hidden within HTTPS. However, DPI alone lacks contextual awareness: it can detect a UNION SELECT in a packet. Still, it cannot determine if it’s part of a legitimate database administrator query or an attack, unless paired with protocol understanding. This limitation is precisely why DPI evolved into something more: the Next-Generation Firewall.
Next-Generation Firewall
Enter the Next-Generation Firewall (NGFW), a stateful firewall that decided to get a PhD in context. An NGFW doesn’t just ask, “Where is this traffic going?” It asks, “Who is sending it? What application is it using? Is it encrypted, and can I decrypt it safely? Should this user even be accessing this service?” By fusing stateful inspection, integrated intrusion prevention (IPS), SSL/TLS decryption, and identity awareness (via Active Directory, certificates, or SAML), NGFWs enforce policies based on users and applications, not just IP/port tuples. Yet despite their power, NGFWs still treat HTTP as one of many protocols. When it comes to defending against logic-based web app exploits (e.g., parameter tampering, JSON injection), they often lack the granularity of a purpose-built WAF.
The table below summarises the five firewall types that we reviewed in this task.
| Firewall Type | OSI Layer(s) | Key Capability |
|---|---|---|
| Stateless Packet Filter | L3–L4 | Filters individual packets based solely on static rules (source/destination IP, port, protocol). No session or flow awareness. |
| Stateful Inspection Firewall | L3–L4 | Maintains a state table of active connections; validates packets against expected TCP/UDP/ICMP state (e.g., flags, sequence). |
| Application-Level Gateway (Proxy Firewall) | L7 (protocol-specific) | Acts as an intermediary; terminates and re-initiates application-layer sessions (e.g., HTTP, FTP). Can inspect and sanitise protocol commands. |
| Deep Packet Inspection (DPI) Firewall | L3–L7 | Inspects packet payloads (not just headers) for known patterns (e.g., malware signatures, P2P protocols). Often integrated into NGFWs. |
| Next-Generation Firewall (NGFW) | L3–L7 + Identity | Combines stateful inspection, DPI, integrated intrusion prevention (IPS), SSL/TLS decryption, and user/application identification (via AD, certificates, etc.). May include basic WAF modules. |
Which flag can attackers misuse to bypass a stateless firewall?
What type of firewall tracks active connections?

At its core, a Web Application Firewall (WAF) is a security control that inspects HTTP(S) traffic, both inbound and outbound, for signs of malicious intent. Unlike network firewalls that guard ports or NGFWs that classify applications, a WAF speaks HTTP fluently: it parses methods, headers, cookies, query strings, and POST bodies to enforce policies aligned with threats such as SQL injection, cross-site scripting (XSS), file inclusion, and command injection. In other words, it strives to protect against the OWASP Top 10 web application security vulnerabilities.
Although they cannot fix broken code, WAFs attempt to mitigate known vulnerabilities without requiring source code changes; this is called virtual patching. Unlike real patching of vulnerable code, if the firewall rule does not cover a particular payload, it would pass through and exploit the vulnerability.
The Power of a WAF
Although the WAF is not the only firewall that understands HTTP traffic, it may be the only firewall that possesses in-depth knowledge of the various attacks targeting web applications. For instance, it would realise that ?id=1' OR '1'='1 is a classic SQLi probe and that <img src=x onerror=alert(1)> is a browser-executable XSS vector. WAF rules are built around detecting web attacks, or it is trained for that purpose.
Deployment modes are summarised in the table below.
| Model | Description | Common Examples |
|---|---|---|
| Cloud-based (Reverse Proxy) | traffic routed through vendor infrastructure (e.g., via DNS). WAF terminates TLS. | Cloudflare, AWS WAF, Akamai, Imperva Cloud |
| Network Appliance | Physical or virtual in-line device (often paired with a load balancer). | F5 Advanced WAF, Fortinet WAF, Barracuda WAF |
| Host-based (Embedded) | Module within the web server (e.g., Apache/Nginx). | ModSecurity + OWASP Core Rule Set (CRS) |
Fingerprinting a WAF
It was once said, “You don’t need to bypass a WAF to beat it; sometimes, just knowing it’s there is half the victory.” Penetration testing a web application behind a WAF can be very frustrating if we don’t recognise that a WAF is interfering with and blocking the different payloads we are attempting. Once we realise that a WAF is standing in the way, we can avoid wasting time on payloads it will block, tailor obfuscation strategies based on known rule weaknesses, and adjust our testing pace to avoid rate limiting or IP bans. In other words, we need to determine if a WAF exists before considering how to manipulate the packets and bypass it.
This section focuses on various techniques to discover a WAF in place. We will cover the following approaches:
- Passive header inspection
- Behavioural analysis
- Automated fingerprinting with
wafw00f - Subnet-level automation with Nmap’s
http-waf-fingerprint
Passive Header Inspection: Read the Name Tag
The first approach would be to inspect the headers of the target web application. From the terminal, use curl -I followed by the target URL or IP address. Try to see if you can spot one of the common cloud WAFs:
server: cloudflarefor CloudflareX-Sucuri-IDfor SucuriX-CDN: Impervafor Incapsula/ImpervaAkamai-Origin-Hop: 2for AkamaiX-F5-Application: ASMfor F5 Advanced WAF
The following are real examples. This one shows that the target is using Cloudflare.
root@attackbox:~# curl -I Web-App-Example1
HTTP/2 200
date: Fri, 07 Nov 2025 07:48:03 GMT
content-type: text/html
cf-ray: 99ab39e11ffdb6c4-MRS
cf-cache-status: DYNAMIC
cache-control: max-age=0
server: cloudflare
This one is using Imperva.
root@attackbox:~# curl -I Web-App-Example2
HTTP/1.1 200 OK
Date: Fri, 07 Nov 2025 08:01:56 GMT
Server: Apache/2.4.65 (Win64) OpenSSL/3.5.1
Content-Type: text/plain; charset=utf-8
Content-Length: 26
Strict-Transport-Security: max-age=31536000
X-CDN: Imperva
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
Referrer-Policy: strict-origin-when-cross-origin
This example shows Sucuri.
root@attackbox:~# curl -I Web-App-Example3
HTTP/1.1 200 OK
Composed-By: SPIP 4.1.11 @ www.spip.net
Connection: keep-alive
Content-Length: 154313
Content-Type: text/html;charset=utf-8
Server: JAWS/1.0 Sep 18 2018
[...]
X-Sucuri-Id: 67
X-Xss-Protection: 1; mode=block
Date: Fri, 07 Nov 2025 08:08:17 GMT
Behavioural Analysis: Watch How It Reacts When Poked
This one is more invasive than the first one. In this case, we are not only requesting a web page, but we are also sending something that looks malicious. We are literally concatenating malicious-like strings that are generally indicative of an attack. The following “harmless” strings match common attack signatures:
' OR 1=1--should trigger SQLi signature<script>alert(1)</script>matches XSS signature../../../../etc/passwdactivates LFI signature
Although the above are harmless, they resemble real attacks, and you should obtain permission before attempting them outside a lab environment. In the following example, we use curl along with -I or --head to fetch the headers only. In the first attempt, we get a response of 200 OK.
root@attackbox:~# curl -I "http://MACHINE_IP/search.html?q=test"
HTTP/1.1 200 OK
Server: nginx/1.28.0
Date: Mon, 17 Nov 2025 08:52:08 GMT
Content-Type: text/html
Content-Length: 3738
Last-Modified: Mon, 17 Nov 2025 08:48:00 GMT
Connection: keep-alive
ETag: "691ae140-e9a"
Accept-Ranges: bytes
By adding ' OR 1=1-- (or '%20OR%201=1-- after encoding the space as %20), the WAF was triggered and the response changed to 403 Forbidden, as is shown in the interaction below.
root@attackbox:~# curl -I "http://MACHINE_IP/search.html?q=test'%20OR%201=1--"
HTTP/1.1 403 Forbidden
Server: nginx/1.28.0
Date: Mon, 17 Nov 2025 08:52:36 GMT
Content-Type: text/html
Content-Length: 153
Connection: keep-alive
The table below provides a list of responses to watch for, along with probable interpretations.
| Response | Likely Meaning |
|---|---|
403 Forbidden, blank page |
Classic WAF block |
406 Not Acceptable |
Common in ModSecurity CRS |
| Custom HTML page with “Access Denied” | Vendor-specific (e.g., Fortinet, Barracuda) |
| Delayed response (>500ms) | WAF inspection overhead |
| No change from normal search | Possibly no WAF or blind probe |
Automated Fingerprinting: Let the Tool Do the Heavy Lifting
Instead of using curl to manually attempt to trigger various WAF rules, we can use a tool to do the work for us. WAFW00F (wafw00f), developed by EnableSecurity, follows the following steps:
- Begin with a baseline probe: issue a standard HTTP request and analyse the response, status code, headers, and body indicators to fingerprint standard WAF solutions.
- If results are inconclusive, escalate with a controlled set of potentially malicious HTTP requests and apply simple logic to map observed behaviours to a likely WAF implementation.
- If still unresolved, analyse the collected responses, codes, headers, timings, and any other pages and apply another simple algorithm to infer whether a WAF or related security control is actively mediating the traffic.
It can detect over 500 WAFs. Here are a few examples. In this first example, WAFW00F didn’t detect a WAF.
root@attackbox:~# wafw00f http://example1
[...]
~ WAFW00F : v2.3.1 ~
The Web Application Firewall Fingerprinting Toolkit
[*] Checking http://example1
[+] Generic Detection results:
[-] No WAF detected by the generic detection
[~] Number of requests: 7
In this example, the existence of a WAF was detected as the HTTP response code was changed from normal.
root@attackbox:~# wafw00f http://example2
[...]
~ WAFW00F : v2.3.1 ~
The Web Application Firewall Fingerprinting Toolkit
[*] Checking http://example2
[+] Generic Detection results:
[*] The site http://example2 seems to be behind a WAF or some sort of security solution
[~] Reason: The server returns a different response code when an attack string is used.
Normal response code is "200", while the response code to a cross-site scripting attack is "403"
[~] Number of requests: 5
This result also showed that a WAF was in place. In the output below, we can see that the existence of a WAF was detected when the usual HTTP response code was changed.
root@attackbox:~# wafw00f http://example3
[...]
~ WAFW00F : v2.3.1 ~
The Web Application Firewall Fingerprinting Toolkit
[*] Checking http://example3
[+] Generic Detection results:
[*] The site http://example3 seems to be behind a WAF or some sort of security solution
[~] Reason: The server returns a different response code when an attack string is used.
Normal response code is "429", while the response code to a file inclusion attack is "200"
[~] Number of requests: 6
Automated Fingerprinting: Using Nmap Script
WAFW00F is excellent for detecting WAFs when checking a single host; however, for checking a subnet, you might consider trying Nmap’s script, http-waf-fingerprint. Here’s a description from the script’s official info.
root@attackbox:~# nmap --script-help http-waf-fingerprint
[...]
https://nmap.org/nsedoc/scripts/http-waf-fingerprint.html
Tries to detect the presence of a web application firewall and its type and version.
[...]
Credit to wafw00f and w3af for some fingerprints.
To start using it, you need to build your Nmap command options like the following example: nmap -p 80,443 --script http-waf-fingerprint TARGET_IP. Remember to specify the TCP ports where you want Nmap to probe the target web server. In our experience, WAFW00F is the best automated tool at the time of writing. Unfortunately, it appears that Nmap’s http-waf-fingerprint feature remains silent when the WAF name is not detected; however, WAFW00F informs us of the presence of a WAF, even when its name or type is unclear.
Which layer does a WAF primarily inspect?
What do you call mitigating vulnerabilities without source code changes?
What HTTP status code do you get if you attempt an SQLi against http://MACHINE_IP?
A signature-based WAF says: “I know what a knife looks like.” A behavioural WAF says: “I know how a benign use of a knife, such as cutting bread, looks like.” (or “I know how someone holding a knife maliciously moves around.”) Unfortunately, both can be fooled: one by disguise, the other by mimicry. Let’s explore these two types of detection mechanisms.
Signature-Based Detection
A signature-based detection engine works by comparing the contents of each packet against a list of known malicious signatures. Generally speaking, such detection engines recognise what’s malicious and rely on this knowledge to decide what’s benign. For example, it would include rules that match SQLi patterns, such as the one in this HTTP Request: GET /search?q=' OR 1=1-- HTTP/1.1. Moreover, the WAF will respond with something such as 403 Forbidden if the received request matches the rule. Consequently, any similar attacks will be blocked unless the attacker finds a way to evade the rule.
Attackers evade signature rules using:
- Encoding: An attacker might attempt encoding
' OR 1=1--as'%20OR%201=1--,%27%20OR%201%3D1--, or even%27%20OR%201%3D1%2D%2D. - Case variation: In this evasion attempt, the attacker would type
UNION SELECTasunIOn sElEcT - Comment insertion: The attacker would attempt to insert comments to evade triggering the rule.
- Alternative syntax: If the attacker can replace one syntax with another, such as
1' AND SLEEP(10)--with1' AND IF(1=1, SLEEP(10), 1) --, they might succeed in escaping detection.
For the attacker to succeed, once they determine that a rule is blocking their payload, they need to make various changes and try again. Depending on the target WAF’s rules, they may be able to evade detection. The main advantage of signature-based detection is that the number of false positives, i.e., normal traffic incorrectly detected as malicious, is expected to be low. Furthermore, the rules are relatively manageable to write and understand. Finally, they can run as fast as the running code can match the incoming traffic. The disadvantages mainly lie in the fact that signature-based detection engines are as good as their signatures. Consequently, they might miss malicious payloads due to encoding or other related techniques. Needless to say, they cannot detect an attack if it is not within their signature database; therefore, they cannot detect zero-day attacks and require constant updates. A summary is provided in the table below.
| Advantages | Disadvantages |
|---|---|
| Low false positives (when tuned) | Blind to obfuscation (e.g., encoding, comments) |
| Easy to write and understand | Can’t detect zero-day attacks |
| High performance (regex engines are fast) | Requires constant updates |
Behavioural Detection
Behavioural detection is also known as anomaly-based detection. Generally speaking, such kinds of detection engines are trained to know what’s normal. Any deviation from normal is going to be flagged as an anomaly. To build a baseline for normal, exposing the engine to “normal traffic” is indispensable. Normal behaviour can include input length, parameter count, data types, session rate, and historical user behaviour, among others.
Let’s say that a standard HTTP POST request is expected to look like username=alice&password=pass1234, then the detection engines receive something such as username=' OR '1'='1&password=somepass; the existence of special characters in the username, along with white space, is an apparent deviation from what a normal username should be.
The main strength of anomaly-based detection is that it has a decent chance of blocking unknown and zero-day attacks, as such attacks deviate from normal behaviour. Furthermore, they are better at detecting malicious traffic even when encoding and similar tricks are employed. Finally, the detection engine will adapt to the application and get better over time. The main disadvantage is that a high false positive rate is expected, despite the necessity of undergoing a training period. It is also worth noting that, compared to signature-based detection, anomaly-based detection tends to be computationally more expensive. A summary is shown in the table below.
| Advantages | Disadvantages |
|---|---|
| Catches unknown (zero-day) attacks | High false positives (e.g., blocks legitimate long forms) |
| Harder to bypass with simple encoding | Requires training period (“learning mode”) |
| Adapts to application logic over time | Computationally expensive |
Hybrid Detection
In many modern commercial WAFs, a combination of both of the previous approaches is used. For example, the traffic might first undergo a fast signature check. Following this step, a deep inspection is conducted to determine the anomaly scoring, and finally, a weighted risk score is calculated to decide on the packet.
Which detection method uses known attack patterns?
What kind of attacks can behavioural detection catch that signature-based cannot?
At the heart of every WAF lies its rule set: a collection of conditional statements that define what traffic is allowed, logged, or blocked. These rules are human-readable (and often human-written) logic trees, usually expressed in a domain-specific language.

Example Real Rule
The best way to learn about rules is to dive into one. The following rule is for SQLi and it is from OWASP® CRS v3.3.7.
SecRule REQUEST_BASENAME "@detectSQLi" \
"id:942101,\
phase:2,\
block,\
capture,\
t:none,t:utf8toUnicode,t:urlDecodeUni,t:removeNulls,\
msg:'SQL Injection Attack Detected via libinjection',\
logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\
tag:'application-multi',\
tag:'language-multi',\
tag:'platform-multi',\
tag:'attack-sqli',\
tag:'OWASP_CRS',\
tag:'capec/1000/152/248/66',\
tag:'PCI/6.5.2',\
tag:'paranoia-level/3',\
ver:'OWASP_CRS/3.3.7',\
severity:'CRITICAL',\
setvar:'tx.sql_injection_score=+%{tx.critical_anomaly_score}',\
setvar:'tx.anomaly_score_pl3=+%{tx.critical_anomaly_score}'"
The Trigger: SecRule REQUEST_BASENAME "@detectSQLi"
In the first line, we have the following:
SecRule: Standard ModSecurity directive to define a ruleREQUEST_BASENAME: This variable refers to the filename or endpoint in the URL path. For example, in/api/user/123, the basename is123"@detectSQLi": This is a call to libinjection, a specialised C library designed only for detecting SQL injection. It is worth noting that libinjection tokenises input like a real SQL parser, instead of matching strings like' OR 1=1
Rule Metadata: Identity, Context, and Compliance
In the next four lines, we have the following:
id:942101: Unique identifier (part of CRS numbering scheme)phase:2: Run during request body processing (after headers, before app logic)block: Take action: reject the requestcapture: Save the matched payload for logging (%{TX.0})
Input Normalisation: Seeing Through the Noise
Before @detectSQLi runs, the input is normalised through a pipeline of transformations:
t:none: Start with raw input (no auto-decoding)t:utf8toUnicode: Convert UTF-8 sequences (e.g.,%C2%A7) to Unicode to prevent bypass via encodingt:urlDecodeUni: Perform recursive URL decoding (handles double-encoding like%2527is decoded to%27, which in turn, is decoded to')t:removeNulls: Strip null bytes (%00), often used to terminate strings in C-based parsers
It is crucial to decode the contents before checking; otherwise, it would be easy to miss the encoded threats.
Logging and Attribution: Making Incidents Actionable
In the following two lines, we log a human-readable alert.
msg:'SQL Injection Attack Detected via libinjection',\
logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',\
msg: Human-readable alert that shows up in logs and SIEM.logdata: Rich forensic detail:%{TX.0}: The exact payload that triggered the rule (thanks tocapture).%{MATCHED_VAR_NAME}: Which variable was inspected (REQUEST_BASENAME).%{MATCHED_VAR}: The full value (e.g.,1' OR '1'='1).
Tags: Connecting to Standards and Strategy
Now it is time to tag the traffic. It is worth noting that the tags are not merely labels; they’re operational hooks in some way. Consider the following example:
tag:'attack-sqli'
tag:'OWASP_CRS'
tag:'capec/1000/152/248/66'
tag:'PCI/6.5.2'
tag:'paranoia-level/3'
The above lines indicate the following:
capec/1000/152/248/66: Links to CAPEC (Common Attack Pattern Enumeration) – useful for threat modelling.PCI/6.5.2: References PCI DSS requirement for protecting against injection flaws.paranoia-level/3: CRS uses four paranoia levels. PL3 is stricter and blocks more, but has higher false positives. Used in high-security environments. You can learn more about paranoia levels here.
Scoring and Telemetry: Feeding the Anomaly Engine
Finally, we can use the detected traffic to update our risk score. Take a closer look at the following two lines:
setvar:'tx.sql_injection_score=+%{tx.critical_anomaly_score}'
setvar:'tx.anomaly_score_pl3=+%{tx.critical_anomaly_score}'
They achieve the following:
tx.sql_injection_score: Tracks cumulative SQLi risk across multiple rules.tx.anomaly_score_pl3: Feeds into CRS’s total anomaly score for paranoia level 3.
After studying this rule for detecting SQLi in a modern system, you can see that it embodies modern WAF design, including specialised detection, deep normalisation, contextual logging, and integration into a scoring system. It’s not only a firewall blocking traffic; it serves as a sensor in a larger security system.
Which library does OWASP CRS use to detect SQLi?
What transformation handles double URL encoding?
What score is increased when a critical rule triggers?
Log in to the dashboard at http://MACHINE_IP:7000. Under Attack Control, click Critical Attack, locate the attack that triggered rule 932160 at 2025-11-12 15:38:00. What is the URI that triggered this rule? You need to click View to see the request details.
Before concluding this room, it is worth visiting some of the limitations of WAFs.
WAFs Only Work If Rules Are Good
WAFs are as good as their rules. Although this may seem obvious, it is worth emphasising here: signature-based rules are likely to miss new payloads. Obfuscation, via encoding, comments, or even white-space, can make it possible to evade regex-based rules. Furthermore, a sizable number of organisations run WAFs in log-only mode due to the high rate of false positives, rendering them useless for protection.
WAFs Don’t Understand Application Logic
One of the biggest misconceptions when setting up a WAF is that it can stop all web attacks. This expectation is unrealistic. Because WAFs don’t understand the application logic, they cannot determine if a user should be allowed to edit another person’s profile or if a price parameter (?price=1.99) has been tampered with. These are business logic flaws, and WAFs are blind to them.
Consider the following example of real-world impacts:
- IDOR (Insecure Direct Object Reference): In the HTTP Request
GET /api/user/123, if the attacker changes123to124, where no special characters or malicious payloads were used. Consequently, nothing would trigger a WAF to block it. - Authorisation bypass: If a user can access
/adminwithout being an admin, the URL looks benign, and the WAF cannot detect anything wrong. - Race conditions and replay attacks: Similarly, such attacks don’t involve any malicious syntax for the WAF to detect.
In brief, WAFs filter syntax, not intent. They can’t fix broken access controls.
Encrypted Traffic Is a Blind Spot
Unless decrypted, encrypted traffic cannot be inspected for malicious payloads; therefore, modern WAFs sit in front of the TLS termination points to monitor all the HTTP traffic. However, if encryption occurs before the WAF, the WAF would only see encrypted blobs and not the actual HTTP requests.
It should be noted that when TLS is terminated at the WAF, certificate management adds to the complexity and risk of the setup. Furthermore, some organisations avoid decryption due to privacy or compliance concerns.
Client-Side Attacks Fly Under the Radar
WAFs inspect server-bound traffic; consequently, we cannot expect them to block attacks happening entirely in the browser. For example, in a DOM-based XSS attack, the payload executes in the browser and is never sent to the server. Also consider malicious first-party scripts, such as compromised analytics libraries; these don’t generate suspicious server requests for the WAF to intercept.
WAFs Introduce New Attack Surfaces
Ironically, adding a WAF introduces new attack surfaces. In fact, poorly configured custom rules can introduce RCE, for example, by dynamically constructing ModSecurity rules and failing to properly escape input. Also, care should be taken that a complex regex or large payloads do not lead to DoS due to memory exhaustion.
Furthermore, if the management interface is exposed on a public IP address, the attacker would gain access to a new WAF admin login page, allowing them to brute-force its login credentials. Or worse, the management user interface might be vulnerable to an RCE vulnerability, as in the case of CVE-2020-5902.
Performance vs. Security Trade-Off
It is worth noting that deep packet inspection incurs CPU time costs. Consider the cases where the WAF needs to do regex matching on large payloads or decode multi-layered encoding. This procedure may impact overall performance and introduce a delay. For anomaly-based detection, running behavioural models or ML engines also requires a non-trivial share of the system resources. As traffic scales, it is essential to watch for increases in latency or legitimate requests timing out.
Finally, deploying a WAF or any other security solution does not mean that the systems become miraculously secure. One should be careful not to fall into a false sense of security. On one hand, a properly configured WAF will add to the security, and it will even help meet compliance requirements; however, cyber security is built through a comprehensive security policy and various security solutions.
What prevents WAFs from inspecting traffic if not terminated at the WAF?
Web Application Firewalls are not silver bullets. They are complex tools designed to mitigate known vulnerabilities, enforce virtual patching, and filter malicious traffic; however, they can do so within certain technical and operational boundaries.
In this room, we’ve seen that WAFs are the result of firewalls evolving from simple stateless filters to deep-inspection engines capable of parsing HTTP traffic, detecting anomalies, and blocking entire classes of attacks, such as SQLi and XSS. However, their effectiveness depends on well-crafted rules, proper deployment, and a clear understanding of their limitations. A WAF cannot fix faulty business logic, making it blind to IDOR, privilege escalation, or even form value manipulation. It is powerless against encrypted and client-side traffic. Furthermore, poorly configured WAFs can introduce new attack surfaces, from rule injection to exposed management interfaces.
A WAF is best used as part of a defence in depth, not a replacement for secure coding. Unfortunately, if the underlying application is flawed, no amount of filtering will make it truly secure.
What principle should guide WAF use in a defence strategy?
Ready to learn Cyber Security? Create your free account today!
TryHackMe provides free online cyber security training to secure jobs & upskill through a fun, interactive learning environment.
Already have an account? Log in