Использование sleep() вместо benchmark() в sql-инъекциях

Hint: flag is not a frag: once you've got it, you can get one more...

Зачастую встречаются sql-инъекции, в которых нет ни вывода полей, ни вывода ошибок.
В таких случаях применяют find_in_set() и ей подобные.
Можно ввести ещё одну (сомнительную) альтернативу для пятой ветки mysql – sleep().

Рассмотрим следующий запрос:

SELECT SLEEP((SELECT substring(version(),1,1)))

Здесь будет задержка 5 секунд (работаем с пятой веткой) + уйдёт время на выполнение самого запроса.
Если сначала посмотреть, сколько уходит времени на получение ответа от сервера на запрос без задержки, можно точно узнать первый символ одним запросом.
А учитывая то, что обычно сервер выполняет запрос меньше, чем за одну секунду, можно брать просто целую часть от времени ответа сервера.

Теперь посмотрим, как вытаскивать символы. Предлагаю делать это с помощью ASCII-кодов:

SELECT SLEEP((SELECT ascii(substring((SELECT password FROM users LIMIT 1,1),1,1)))/50)

В данном запросе задержка будет равна одной пятидесятой от кода символа в секундах.
В зависимости от того, как быстро сервер возвращает ответы без задержки, можно варьировать это число во избежание ошибки.

Таким образом, на 1 md5() хеш потребуется ровно столько запросов, сколько в нём символов – 32.

Теперь о плюсах и минусах:

+ Рекордные 32 запроса на md5()
+ Не требует вывода ошибок
- Работает лишь начиная с MySQL 5
- Возможны погрешности, если сервер перегружен

Надо отметить, что минусы не так существены, как плюсы – старые ветки MySQL уже отмирают, а погрешностей можно избежать, меняя знаменатель в функции SLEEP().

Но главный минус -- это то, что эксплойт работает долго (чем больше множитель, тем дольше).

PoC-эксплойт (Pastebin):

UPD После того, как я это опубликовал на античате, в ][ вышла статья Ams (0x416d73.name) с описанием аналогичного метода (он его придумал параллельно)