SQLi - WAF Detection & Bypass Techniques That Still Work in 2023
There are many techniques out there to detect and bypass WAFs and the goal of this blog isn't to show or explain all of them - just to share a few techniques that I've found still work well in 2023. Although there are more advanced techniques out there, these will help you get started on bypassing WAFs.
Some of these techniques are also incorporated in SQLMap's tamper scripts. The point here is to exploit these vulnerabilities manually, not throw a tool at a target and see what sticks.
SQLi has been around for over 20 years. It's still rampant today, and has recently become one of my favorite types of vulnerabilities to hunt for in applications.
Nowadays, many people believe that you need complex detection methods to find a potential instance of SQL injection. Sometimes that's the case, but often simply checking for response differences between injecting a single
' and a double
'' will still demonstrate if you were able to close and then re-open the query statement.
We've found that instead of fixing the actual code (ex. parameterizing the query), many teams will just implement a Web Application Firewall (WAF)!
Detecting a WAF
You'll know you're dealing with a WAF if you try to inject certain common SQL keywords such as
SELECT, or even use the
= character and get a strange response from the server (something like "Not Allowed!", "Request rejected", a 403 response, or a custom response such as "Hey you! Knock it off!")
If you found a WAF, there's a good chance that it is the only defense implemented and you may have a solid shot at exploitation if you can find a bypass.
Comments & Junk Text + Whitespace + Random Casing + URL-Encoded Hex Values
Break up your injection with in-line comments such as
/*comment*/. Combine this with an alternative for whitespace using
/**/, randomized casing, and substituting URL-Encoded hex values. This was recently used on one of our engagements and worked quite well.
This can be as simple as transforming
UNION SELECT password FROM...
A few things to note here: Not only were hex values substituted, but the casing was also mixed. The above also used
/**/ instead of whitespace or
%20, as the WAF was also looking for that in this specific instance.
Sometimes though, it doesn't need to be as complex:
When = is filtered... Not Equal + Null Bytes
I've often found that the
= is filtered or the request is blocked if there's anything that follows the
= character. There are a few workarounds for this situation.
!= or another comparison operator such as
I have had success with this many times but WAF's are starting to catch on. A nice way to confuse the WAF is using a few null bytes (
%00). Here's another example of a transformation using this technique:
' OR '1'='1
%27 OR 1!=%00%00%00%272
When '1' = '1 Doesn't Work and + is Blocked
There have been many instances where I'll try to detect what "feels" like SQLi and come up short with the
'' techniques and
CASE WHEN THEN. This is a simple comparison statement that is often overlooked by many signature-based WAFs. However, I've found many SQLi vulnerabilities this way.
In this case, we're using a double-URL encoded value of the
+ but we're also using a different comparison operator instead of the all-known
1=2. The payload above will return a different response than:
In the techniques explained above, we're not relying on a single method to avoid detection and bypass the firewall. WAFs today are better than that - so you have to get creative.
Stay tuned for Part 2, where I walk through a real example of manually bypassing one of the most popular commercial WAFs available using some of these techniques.