Введение
В логах веб-сервера или в поле ввода можно встретить подозрительную строку: %')) AND EXTRACTVALUE(2768,CONCAT(0x7e,((SELECT (ELT(2768=2768,1)))),0x7e))-- -. Что это такое и какова её цель? Это классический пример SQL-инъекции, нацеленной на извлечение данных из базы через вывод сообщений об ошибках. В данной статье мы подробно разберём каждую часть этого запроса, объясним, как работает атака, и расскажем, как защититься.
Что такое SQL-инъекция?
SQL-инъекция (SQL injection) — один из самых распространённых способов взлома веб-приложений. Злоумышленник внедряет вредоносный SQL-код в поля ввода, URL-параметры или cookie, чтобы заставить базу данных выполнить нежелательные действия: украсть данные, изменить их или удалить. Существует несколько типов SQL-инъекций: union-based, error-based, blind, time-based. Строка, которую мы рассматриваем, относится к error-based инъекциям, где атакующий заставляет СУБД выдать сообщение об ошибке, содержащее полезные данные.
Разбор строки запроса
Давайте разберём её по частям:
- %')) — это начало строки. Символ
%часто используется в URL-кодировании, но здесь он может быть частью исходного значения. Далее идут две закрывающие скобки и апостроф. Это попытка закрыть ранее открытые скобки и строковый литерал в оригинальном SQL-запросе, чтобы внедрить свой код. Например, если уязвимый запрос выглядел какSELECT * FROM users WHERE id = ('$input'), то вставка'))закроет кавычку и скобку, позволив добавить произвольные команды. - AND EXTRACTVALUE(2768,CONCAT(0x7e,((SELECT (ELT(2768=2768,1)))),0x7e)) — это основная полезная нагрузка. Функция
EXTRACTVALUE()в MySQL предназначена для извлечения значения из XML-документа по указанному XPath-выражению. Однако при передаче некорректного XPath она генерирует ошибку, текст которой включает переданный аргумент. Это и используется для вывода данных. - -- - — это комментарий. Два дефиса и пробел (или другой символ) заставляют MySQL игнорировать оставшуюся часть оригинального запроса, чтобы не возникло синтаксической ошибки.
Как работает EXTRACTVALUE для извлечения данных
Функция EXTRACTVALUE(XML_document, XPath_expression) возвращает текст из XML-документа, соответствующий XPath. Если XPath содержит недопустимые символы, например, тильду (~), MySQL выдаёт ошибку вида: XPATH syntax error: '~...~'. Злоумышленник формирует XPath так, чтобы в сообщении об ошибке оказались нужные данные. В нашем случае используется CONCAT(0x7e, ((SELECT (ELT(2768=2768,1)))), 0x7e). 0x7e — это шестнадцатеричный код символа ~ (тильда). ELT(N, str1, str2, ...) возвращает N-ю строку из списка. Выражение 2768=2768 всегда истинно (1), поэтому ELT(1,1) вернёт 1. Таким образом, в XPath попадёт строка ~1~, что вызовет ошибку с текстом XPATH syntax error: '~1~'. Это простейший пример; на практике вместо 1 подставляют подзапросы, извлекающие имена таблиц, логины, пароли и т.д.
Цель атаки
Основная цель — получить информацию из базы данных. В примере с ELT(2768=2768,1) атакующий просто проверяет, что инъекция работает: если приложение вернёт ошибку с ~1~, значит, уязвимость подтверждена. Далее он может заменить 1 на подзапрос, например, (SELECT password FROM users LIMIT 1), и извлечь пароль. Такой метод называется error-based SQL injection, потому что данные извлекаются через сообщения об ошибках.
Пример уязвимого кода
Рассмотрим фрагмент на PHP:
$id = $_GET['id'];
$query = "SELECT * FROM articles WHERE id = ('$id')";
$result = mysqli_query($conn, $query);
Если пользователь передаст id=1')) AND EXTRACTVALUE(...)-- -, то итоговый запрос станет:
SELECT * FROM articles WHERE id = ('1')) AND EXTRACTVALUE(2768,CONCAT(0x7e,((SELECT (ELT(2768=2768,1)))),0x7e))-- -')
MySQL выполнит его, и если возникнет ошибка XPath, она будет выведена на страницу (если включён вывод ошибок). Так злоумышленник получает данные.
Как защититься от таких атак
Существует несколько надёжных способов предотвратить SQL-инъекции:
- Использование подготовленных выражений (prepared statements). Это самый эффективный метод. Параметры передаются отдельно от SQL-кода, и база данных не интерпретирует их как часть запроса. Например, в PHP с PDO или MySQLi.
- Экранирование специальных символов. Функции вроде
mysqli_real_escape_string()помогают, но не гарантируют полную защиту, если не использовать их повсеместно. - Валидация входных данных. Если поле ожидает число, проверяйте, что это действительно число. Отклоняйте всё, что не соответствует формату.
- Ограничение прав пользователя БД. Учётная запись, от имени которой работает приложение, должна иметь минимально необходимые привилегии. Не используйте root.
- Отключение вывода ошибок на продакшене. Сообщения об ошибках не должны показываться пользователям, чтобы не давать подсказок атакующему. Логируйте их, но не выводите в браузер.
- Использование WAF (Web Application Firewall). Современные WAF могут обнаруживать и блокировать попытки SQL-инъекций по сигнатурам.
Заключение
Строка %')) AND EXTRACTVALUE(2768,CONCAT(0x7e,((SELECT (ELT(2768=2768,1)))),0x7e))-- - — это типичный пример error-based SQL-инъекции через функцию EXTRACTVALUE. Она демонстрирует, как злоумышленники используют особенности СУБД для извлечения данных. Понимание механизмов таких атак помогает разработчикам и администраторам лучше защищать свои системы. Всегда используйте подготовленные выражения, валидируйте входные данные и следите за обновлениями безопасности.
Комментарии
—Войдите, чтобы оставить комментарий