SQL инъекция. UNION QUERY INJECTION

SQL инъекции (SQLI) — это техника, позволяющая внедрить свой SQL-код в БД используя уязвимость в приложении. Используя синтаксис SQL, атакующий может изменить запрос к базе данных, для получения необходимой информации или получения контроля над ней. В основном данный тип атак применим для веб приложений, но он может быть использован в любом приложении, где используются sql ДБ и входящие пользовательские данные обрабатываются плохо.

Виды SQL инъекций:

  1. UNION query SQLI
  2. Error-base SQLI
  3. Stacked queries
  4. Boolean based blind SQLI
  5. Time base blind SQLI
  6. Комментарии в инъекции

В это статье подробнее расскажу про UNION query SQL Injection

Union query sql injection

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

Запрос:

Инъекция:

Получаем запрос:

И в итоге, мы получаем список все email и паролей пользователей.

Но так как оператор  UNION требует одинаковой структуры для обеих частей запроса, атакующему необходимо подобрать структуру запрос схожую с первой частью. Чтобы сделать это, должно быть известно не только верное имя таблицы, но ещё количество выбираемых полей и их тип.

Получение количества полей в запросе

Есть два способа получения количества полей в первоначальном запросе.

Первый заключается в инъекции конструкции ORDER BY  с указанием номер столбца.

Пример.

Инъекция:

Полученный запрос:

Он завершится без ошибки, так как сортировка будет происходит по второму столбцу, который присутствует с выборкой. Такое же поведение будет и при инъекции ‘1 ORDER BY 3’. 

Но при инъекции:

Мы уже получим ошибку, потому что 4-ого столбца не существует. Из чего делаем вывод, что в запросе присутствует три столбца.

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

Инъекция:

Полученный запрос:

Если получаем ошибку, добавляем ещё одно поле в инъекцию:

И так до тех пор, пока не перестанем получать ошибки выполнения.

Получение имени таблицы

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

Посмотрим на пример:

Предположим, что база Oracle, системная таблица, со списком имеющихся таблиц — all_tables

Инъекция:

Полученный запрос:

Если получили ошибку, значит ошиблись в бд. Идем дальше, попробуем служебные таблицы mysql (таблица information_schema.tables)

Инъекция:

Полученный запрос:

И снова смотрим на полученный результат. Есть ошибка — пробуем другую базу, нет — мы нашли нашу базу данных.

Получение информации

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

Получение списка таблиц

В данном примере, будем рассматривать mysql (т.к. является самой популярной), в дальнейшем дам разбор и для других баз данных.

В MySQL имена таблиц и схем хранятся в служебной таблице information_schema.tables. Нас интересуют поля table_name и tables_schema

Инъекция:

Запрос:

И теперь, в выводимых данных мы сможем увидеть список схем и таблиц. Так как, скорее всего выводимые данные будут ограничены, в инъекции необходимо будет использовать LIMIT и OFFSET.

Для примера, необходимая нам таблица — ‘members‘.

Получение полей таблицы

Поля таблиц в MySQL хранятся в таблице information_schema.columns. Необходимые поля — table_name и column_name. Аналогично с получением имен таблиц, составим инъекцию:

Запрос:

И так же получаем необходимые нам поля таблицы.

И завершающий этап — получение данных. Допустим, что нам необходимы поля email и password.

Инъекция:

Полученный запрос:

И теперь уже можем получить email и пароль пользователей, для получения всех данных используем OFFSET и LIMIT.

Заключение.

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


Есть что написать?