Что такое SQL-инъекция через EXTRACTVALUE?
SQL-инъекция — это один из самых распространённых способов атаки на веб-приложения, при котором злоумышленник внедряет вредоносный SQL-код в запросы к базе данных. Особый интерес представляет техника error-based SQL-инъекции, когда атакующий извлекает данные через сообщения об ошибках. Функция EXTRACTVALUE в MySQL часто используется для таких атак, поскольку она генерирует ошибки, содержащие результаты подзапросов.
В данной статье мы детально разберём конкретный payload:
')))) AND EXTRACTVALUE(5885,CONCAT(0x7e,((SELECT (ELT(5885=5885,1)))),0x7e))-- -
и объясним, как он работает, какие функции задействованы и как защититься от подобных атак.
Разбор структуры payload
Payload состоит из нескольких частей, каждая из которых выполняет свою роль:
- ')))) — последовательность закрывающих скобок и кавычек, предназначенная для завершения оригинального SQL-запроса и внедрения собственного кода. Количество скобок зависит от структуры уязвимого запроса.
- AND — логический оператор, который соединяет оригинальное условие с внедрённым.
- EXTRACTVALUE(5885, CONCAT(0x7e, ((SELECT (ELT(5885=5885,1)))), 0x7e)) — вызов функции EXTRACTVALUE с двумя аргументами. Первый аргумент — произвольное число (5885), второй — строка, сформированная через CONCAT.
- -- - — комментарий, который игнорирует оставшуюся часть оригинального запроса.
Функция EXTRACTVALUE
EXTRACTVALUE(XML_fragment, XPath_expression) — это встроенная функция MySQL, предназначенная для извлечения данных из XML-документов с помощью XPath-выражений. Она принимает два строковых аргумента: фрагмент XML-разметки и XPath-локатор, и возвращает текст первого текстового узла, соответствующего выражению. Однако, если XPath-выражение содержит синтаксическую ошибку, MySQL генерирует сообщение об ошибке, в котором отображается часть переданного XPath-выражения. Это и используется в error-based SQL-инъекциях: атакующий может внедрить в XPath-выражение результат подзапроса, и этот результат попадёт в текст ошибки, которую затем можно прочитать.
Функция CONCAT и шестнадцатеричные литералы
CONCAT объединяет несколько строк в одну. В нашем payload используется CONCAT(0x7e, ((SELECT ...)), 0x7e). Здесь 0x7e — это шестнадцатеричное представление символа тильды (~). Тильда добавляется в начало и конец для того, чтобы отделить результат подзапроса от остального текста ошибки и облегчить его извлечение. Часто в качестве разделителей используют и другие символы, например, двоеточие или пробел, но тильда удобна тем, что редко встречается в обычных данных.
Подзапрос с ELT
ELT(N, str1, str2, ...) — функция MySQL, которая возвращает N-ю строку из списка. В нашем случае используется ELT(5885=5885, 1). Выражение 5885=5885 всегда истинно (возвращает 1), поэтому ELT(1, 1) вернёт строку '1'. Это простейший пример, демонстрирующий работу механизма. В реальных атаках вместо этого подзапроса может быть любой другой, например, извлекающий имена таблиц или пароли пользователей.
Как работает атака
Предположим, что веб-приложение выполняет следующий SQL-запрос:
SELECT * FROM users WHERE id = '$id';
Если параметр $id не фильтруется, злоумышленник может передать значение:
')))) AND EXTRACTVALUE(5885,CONCAT(0x7e,((SELECT (ELT(5885=5885,1)))),0x7e))-- -
Тогда итоговый запрос примет вид:
SELECT * FROM users WHERE id = '')))) AND EXTRACTVALUE(5885,CONCAT(0x7e,((SELECT (ELT(5885=5885,1)))),0x7e))-- -';
MySQL выполнит функцию EXTRACTVALUE. Поскольку второй аргумент содержит символ тильды, который не является допустимым XPath-выражением, возникнет ошибка. В сообщении об ошибке будет отображено значение, возвращённое подзапросом, обрамлённое тильдами. Например:
XPATH syntax error: '~1~'
Таким образом, атакующий может извлекать произвольные данные из базы, подставляя вместо ELT(5885=5885,1) другие подзапросы.
Зачем нужны множественные скобки и кавычки?
Количество закрывающих скобок и кавычек в начале payload зависит от того, как построен оригинальный запрос. Если запрос содержит вложенные функции или условия, может потребоваться несколько закрывающих символов, чтобы «выровнять» синтаксис и внедрить свой код. В нашем примере использованы четыре закрывающие скобки и одна кавычка — это типичный случай для запросов с несколькими уровнями вложенности.
Меры защиты от error-based SQL-инъекций
Чтобы предотвратить подобные атаки, необходимо применять комплексный подход:
- Использование подготовленных выражений (prepared statements). Это самый надёжный способ: параметры запроса передаются отдельно от SQL-кода, и внедрение становится невозможным.
- Экранирование специальных символов. Если по каким-то причинам нельзя использовать подготовленные выражения, необходимо тщательно экранировать все пользовательские данные, особенно кавычки и обратные слэши.
- Валидация входных данных. Проверяйте, что входные данные соответствуют ожидаемому формату (например, число, email и т.д.).
- Ограничение прав пользователя базы данных. Учётная запись, от имени которой работает приложение, должна иметь минимально необходимые привилегии.
- Отключение вывода ошибок в production. Сообщения об ошибках не должны показываться пользователям, чтобы злоумышленник не мог получить информацию.
- Использование WAF (Web Application Firewall). Современные WAF могут обнаруживать и блокировать попытки SQL-инъекций.
Заключение
Payload ')))) AND EXTRACTVALUE(5885,CONCAT(0x7e,((SELECT (ELT(5885=5885,1)))),0x7e))-- -' — это классический пример error-based SQL-инъекции через функцию EXTRACTVALUE. Он демонстрирует, как с помощью вложенных функций и комментариев можно извлечь данные из базы через сообщения об ошибках. Понимание механизмов таких атак помогает разработчикам и специалистам по безопасности правильно выстраивать защиту. Всегда используйте подготовленные выражения и следуйте лучшим практикам безопасной разработки.
Комментарии
—Войдите, чтобы оставить комментарий