5.6. Эксплуатация слепой инъекции Blind SQLi

Содержание статьи:

 

Эксплуатация слепой SQL инъекции отличается от рассмотренных выше приемов. Главное отличие SQLi от Blind SQLi в том, что обычно результат работы SQL запросов не возвращается сервером. Обычно сервер возвращает одно из двух состояний. Это может быть другая страница или дополнительный элемент на странице либо это может быть ошибка сервера или другой ответный код HTTP.

Для взлома приложения с уязвимостью Blind SQLi применяют различные техники, некоторые из которых мы рассмотрим в данной статье.

 

Генерирование ответов по определенному условию

Для симуляции узявимости Blind SQLi мы воспользуемся приложением DVWA (Damn Vulnerable Web Application). Для входа в приложение используйте admin/admin, затем выберете пункт SQL Injection (Blind). В открывшейся странице введите в поле ввода 1 или любую другую цифру:

Страница DVWA для тестирования слепой инъекции

Отображенный результат указывает на то, что введенное значение существует на сервере. Если ввести значение больше 6 или текстовые символы, то сервер не вернет никакого ответа. Именно такое поведение часто встречается при наличии уязвимости Blind SQLi, то есть сервер отображает одно из двух: либо существующее значение либо ничего. Ярким примером такой реакции является уязвимость в заголовке Cookie. Как вы знаете, с помощью Cookie серверы идентифицируют авторизованных пользователей. Если значение Cookie найдено на сервере, то приложение идентифицирует и авторизует пользователя. На странице отобразятся дополнительные элменты управления, а также данные самого пользователя. Однако, если хотя бы немного изменить значение Cookie либо ввести неразрешенные символы, то сервер просто не сможет идентифицировать пользователя. Вместо этого отобразится обычная страница, которая предназначена для неавторизованных пользователей.

Если ввести кавычки, апостроф либо любые другие символы для проверки на наличие узявимости, то сервер отобразит изначальную страницу без каких-либо ошибок, поэтому воспользуемся другим приемом. Введем дополнительное условие AND, чтобы получились идентичные выражения, например так:

1

1’ AND 1=1 #

1’ AND ‘a’=’a

Подтверждение уязвимости Blind SQLi

В выше приведенных выражениях условие AND всегда означает ИСТИНУ, а значит никак не влияет на результат работы SQL запроса. Однако, если применить ложное условие, то результат работы SQL сразу изменится, например, при вводе одного из следующих выражений сервер не вернет никакого значения:

1’ AND 1=2 #

1’ AND ‘a’=’b

На этом и основан принцип эксплуатации уязвимости Blind SQLi. Попробуем применить данный метод, чтобы получить название текущей базы данных.

Так как на сервере используется MySQL, то воспользуемся следующим выражением:

1’ AND SUBSTRING(DATABASE(), 1, 1)=’a, где

DATABASE() – получает имя текущей базы данных,

SUBSTRING(‘строка’, позиция_символа, длина _подстроки) – извлекает подстроку определенной длины и из определенной позици из введенной строки. В нашем случае мы извлекаем по одному символу, начиная с самого начала искомой строки и затем сравниваем полученный символ с каждой буквой алфавита, цифрами и другими символами. Как только наступит ИСТИНА в условии мы это сразу увидим.

Таким образом мы посылаем серию запросов, меняя сравниваемые символы и номер позиции в строке.

Воспользуемся Burp Suite для проведения данной операции, однако в начале создадим текстовый файл, который будет содержать все буквы латинского алфавита (заглавные и прописные) и цифры (от 0 до 9).

В Burp Suite перехватываем требуемый запрос и отправляем его в Intruder, где уже вставляем подготовленный SQL запрос:

Ввод пейлоада в Burp Intruder

Во вкладке Payloads выбираем заранее подготовленный файл с латинскими буквами и цифрами:

Найстройки словаря во вкладке Payloads

Запускаем атаку и в открывшемся окне выбираем тот запрос, длина которого отличается от остальных:

Успешная атака Blind SQLi

Первая буква у нас готова, теперь меняем номер позиции и снова запускаем атаку:

Меняем позицию символа в SQL выражении

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

1’ AND LENGTH(DATABASE()) <10 #

Используя данный метод эксплуатации вы можете извлечь практически любую информацию из БД.

 

Вызов задержки исполнения

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

Мы снова воспользуемся приложением DVWA. Чтобы подтвердить уязвимость введите следующий запрос:

1’ AND SLEEP(10) #

С помощью функции sleep() база данных «засыпает» на указанное в скобках количество  секунд. Если ввести выше указанное выражение, то ответ сервера придет примерно через 10 секунд, то есть это прямо указывает наналичие уязвимости.

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

1’ AND IF(условие, опция_1, опция_2)=’опция_2

Если условие ИСТИННО, то выполняется опция_1, если ЛОЖНО – то опция_2. В качестве условия будет использоваться выражение SUBSTRING(DATABASE(), 1, 1)=’a’. То есть мы будем использовать серию запросов, в котором будем менять буквы алфавита и номер позиции в искомой строке. Итоговое выражение будет выглядеть так:

1' AND IF(SUBSTRING(DATABASE(),1,1)='a', SLEEP(10), 'a')='a

Подобная опция задержки доступна и на других системах:

СУБД

Функция

Пример

MySQL

SLEEP(секунды)

SELECT SLEEP(10);

SELECT IF(условие,SLEEP(10),'a');

SELECT * FROM (SUBSTRING(version(),1,1)=5,SLEEP(10),null)

BENCHMARK(количество_повторов, любая_функция)

IF(условие,BENCHMARK(5000000, ENCODE('HELLO')), 'a')='a'

Oracle

DBMS_PIPE.RECEIVE_MESSAGE('любая_строка',секунды)

SELECT CASE WHEN (условие) THEN 'a'||DBMS_PIPE.RECEIVE_MESSAGE(('a'),10) ELSE NULL END FROM dual

UTL_HTTP.REQUEST (‘http://несуществующий_сайт/’)

SELECT UTL_HTTP.REQUEST (‘http://10.0.0.0/’) FROM DUAL;

PostgreSQL

PG_SLEEP(секунды)

SELECT PG_SLEEP(10);

SELECT CASE WHEN (условие) THEN PG_SLEEP(10) ELSE NULL END

MS SQL Server

WAITFOR DELAY '00:00:10'

IF (условие) WAITFOR DELAY '0:0:10'

WAITFOR TIME '00:00:10'

IF (условие) WAITFOR TIME '0:0:10'