Data Extraction Using Binary Conversion/Binary Anding 2023
In this article we will learn about Data Extraction Using Binary Conversion/Binary Anding.
This article describes how to extract data in the case of blind SQL injections in the fastest and most efficient way.
Overview of Data Extraction Using Binary Conversion
SQL injection vulnerability has been around for a very long time and over time many researchers have introduced a lot of techniques to exploit this vulnerability and exfiltrate data. However, there are certain techniques that are quite unusual and very effective in exfiltrating data. In this article, we will take an in-depth look at some of these techniques and understand how we can implement them in real-world scenarios and effectively exfiltrate data.
The test rig used for this article can be downloaded here.
We will explore the following techniques:
- Binary Conversion/Binary Anding
- Bin2POS
All of the above techniques follow a trade-off between the length of the payload, the number of requests sent, and the time it takes to retrieve the data.
Binary Conversion/Binary Anding
In this case, we convert the trailing character to its binary equivalent and iterate over the binary sequence to get back the original value. To understand this easily, let’s look at the following sample payload.
select mid((lpad(bin(ascii(mid((select database()),1,1))),8,0)),2,1)
Payload distribution
To parse the above payload, we need to look at the innermost query, since all other functions work on its results.
So the first function is executed as select database(); which we all know will return the current database name as follows.

The second function “mid()” selects first character from the output of database() function.

The third function generates an ASCII equivalent of character obtained from mid() function.

Finally, the fourth character creates a binary equivalent of character ‘s’.

As the bin function return the binary equivalent without padding, so we are using lpad function to pad zeros to the end result to balance the loop used in the final script.

As we already know that an ASCII character has a range from 0 to 255, the first character of the final binary sequence will always be zero. So we are left with seven requests for each character, which is obviously a large number of requests, but loading larger data will take less time.
Related article:Everything you need to know about Ethical Hacking as a Career by Blackhat Pakistan 2023
Run our POC script to see how many requests it would take to determine the database name.

As you can see, it took us seven character requests to get an eight-character word.
Binary per position
This amazing technique was introduced by Roberto Salgado at Blackhat USA 2013. In this case, the author uses a function called find_in_set, which finds the character’s location in the character set by returning the character’s index. Next, the author converts the returned index to binary and reads the character.
Example
Let’s reload the database name, i.e. “security” from our previous example. To do this, we need to load it one character at a time. We can use the following function for this.
mid(‘security’,1,1) -> ‘s’
Let’s define one character set as follows
Charset = [a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w, x,y,z]
Now if we use find_in_set(substr(‘sahil’,1,1)) it returns 19 because the character ‘s’ is placed at the 19th position in the character set.
Now we convert the obtained index to binary using the following function.
bin(find_in_set(mid(‘security’,1,1))) -> 1011 (4 requests)
As you can see, we now have 4 bytes of binary code to load, but there is a challenge when using this technique which is to “determine the end of the binary sequence”, i.e. how does the automatic program know that the binary sequence is finished and should stop loading location data for any particular character. Well, in this case the author uses mySQL variables to determine if the mid/substr function returns None, if so, then sleep for some time and break out of the loop.
Now you might be thinking, will this require one more request to get the binary sequence?
The answer is no, because we already knew that all the characters in our character set would already be one byte.
Example: for a character it should ideally take 2 requests, one for the current binary data and one to determine the end of the binary sequence, but we already knew that a is present in the first position, ie
For a: 1,b:10,c:11,d:100
So here we always need to load from the second character instead of the first character.
Complete Payload:
((SELECT @a:=MID(BIN(FIND_IN_SET(ascii(MID((database select()),1,1)),’48,49,50,51,52,53,54,55,56,57 , 97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,116,117,118,74,75,76,70,71,75,76,73,71,73,73,74,75,76,76 ,704,75,6666,704,75,66666,704,75,666,704,75,666666,74,712,666666,74,712,6666,74,712,666666, ,87,88,89,90,33,34,35,36, 37,38,39,40,41,42,43,44,45,46,47,58,59,60,61,62,63 ,64,91,92,93,94,95,96,123,124,125,126,32, 9,10,13,11,12′)),2,1))=@a) AND (IF(@a!=”,@ a,sleep(1)))
Payload distribution
To break down the above payload, we again first break it apart by innermost functions.
The innermost function which is select database() returns the name of the database.

The second function is a substr function, selecting the first character of the database name.

In the third function, we are obtaining ASCII equivalent of the first character of the database name.

Finally, in the fourth function, we are locating the position of 115 in defined set.

The fourth function returned that 115 is located at the 29th index of defined character set, let’s convert this value into binary.

As you can see in the screenshot above, we now have 5 bytes to load, but since the bin function does not fill the resulting binary sequence, and we also don’t want to send more requests to retrieve that sequence. We will use the property of the substr/mid function, i.e. it returns nothing when the requested index is greater than the actual length.
Example
As you can see, the word “sahil” is 5 characters long, but if we ask the mid function to fetch six characters, it will return None.

Using the above technique, we can determine the end of the binary sequence, i.e. when the mid function returns nothing sleep for 1-2 seconds, effectively breaking out of the loop and moving on to the next character.
As seen in the screenshot above, we get the 6th character. However, in our previous query, we saw that the binary sequence for the location of the letter “s” was 5 characters long, but when we load the 6th character, we see if the condition fires, which means the binary sequence is terminated.
Run our POC script to see how many requests it would take to determine the database name.

As you can see, it took us 39 requests to determine the database name compared to the binary conversion.
The POC scripts shown in this article can be downloaded here.
References
https://www.owasp.org/index.php/SQL_Injection
https://github.com/Audi-1/SQLi-labs
http://websec.ca/blog/view/optimized_blind_SQL_injection_data_retrieval