SQLi WAF bypass is diffing, not magic

Token filters, double decoding, comment splits. What to try once per request and what to stop wasting cycles on.

Published Updated 2 min read

Most WAFs I meet are regex engines with a latency budget. They hate the word UNION more than they hate bad query logic.

Good news: UnIoN and UN/**/ION sometimes slip through because the rule author forgot case folding or nested comments. Bad news: you can obfuscate for an hour while the app never concatenates your input because it uses bound parameters end to end.

Bypass work is debugging. Baseline request. One mutation. Diff status, length, stable substring. Repeat.

The crafter Bypass step applies PAT-style transforms: tabs, inline comments, mixed case, URL encoding. I leave them off until a clean string returns 403, 406, or a vendor block page.

Boring breaks first

Tab or newline instead of space between UNION and SELECT has saved me on ModSecurity CRS setups that only normalized spaces. Inline comments SEL/**/ECT help when rules key on contiguous tokens. Mixed case costs nothing.

Double URL-encoding a quote (%2527) works when the WAF decodes once and PHP decodes again before the query is built. Over-encoding breaks parsers. Encode the minimum character the rule flagged, not the whole payload.

Same 200, same body length on every mutation? Check quote context first. Prepared statements do not care how clever your comment placement is.

Comment syntax is not portable

MySQL eats # and -- with quirks around trailing space. SQL Server wants -- plus whitespace. Oracle punishes MySQL comment assumptions. Match the engine you fingerprinted. Wrong dialect comments look like "injection failed" when you just broke the parser.

SIEM noise is part of the test

Aggressive bypass spraying triggers alerts. On client networks I note which transform fired the rule and whether the SOC called. Deliverable should be the smallest reproducible bypass chain, not the longest encoded blob from a CTF writeup.

Run baseline from the crafter. Copy. Enable one transform. Send. Compare. When something works, stop adding transforms.

Bypass consistently fails across parameters? Try blind techniques or alternate injection points: cookies, X-Forwarded-For, secondary JSON fields. WAF evasion is a means. The finding is still unsanitized input reaching SQL, not "I beat Cloudflare."

FAQ

Should I enable every WAF transform at once?
No. One change per request. Stacked encoding plus comments plus case tricks makes it impossible to know what slipped through when something finally returns 200.
Do WAF bypasses work on parameter-level filtering only?
Sometimes the WAF blocks at the edge and the app decodes again before concatenation. Sometimes the block is app code, not the WAF. Compare 403 vs 500 vs identical length.
Is URL encoding enough?
Against old filters, maybe. Modern stacks decode once or twice by default. Pair %27 with comment breaks or tab whitespace. Encoding alone rarely carries a full UNION string.

Related articles