Введение
В мире веб-безопасности SQL-инъекции остаются одной из самых распространённых и опасных уязвимостей. Строка, которую вы видите в запросе — %')) AND EXTRACTVALUE(8651,CONCAT(0x7e,((SELECT (ELT(8651=8651,1)))),0x7e))-- - — представляет собой классический пример error-based SQL-инъекции для СУБД MySQL. Такие конструкции используются злоумышленниками для извлечения данных из базы через вывод сообщений об ошибках. В этой статье мы детально разберём, как работает эта строка, какие механизмы MySQL она эксплуатирует и как защититься от подобных атак.
Что такое error-based SQL-инъекция?
SQL-инъекция — это способ внедрения вредоносного SQL-кода в запросы к базе данных через пользовательский ввод. Error-based (основанная на ошибках) — разновидность, при которой атакующий заставляет сервер выдать сообщение об ошибке, содержащее полезные данные (например, версию БД, имена таблиц, логины). MySQL охотно возвращает детализированные ошибки, что делает этот метод очень эффективным.
Основная идея: с помощью специальных функций, таких как EXTRACTVALUE или UPDATEXML, вызвать ошибку, в текст которой подставляется результат подзапроса. Сервер возвращает эту ошибку клиенту, и атакующий читает данные.
Разбор строки по частям
Давайте препарируем нашу строку:
- %'))) — часть, которая «закрывает» предыдущие кавычки и скобки в уязвимом запросе. Символ
%здесь — это URL-кодирование, но в контексте инъекции он может быть просто частью строки. Обычно инъекция начинается с попытки разорвать существующий SQL-запрос. Например, если оригинальный запрос былSELECT * FROM users WHERE name = '$input', то ввод%')))приведёт к синтаксической ошибке, но атакующий добавляетAND ..., чтобы запрос остался валидным. - AND EXTRACTVALUE(8651,CONCAT(0x7e,((SELECT (ELT(8651=8651,1)))),0x7e)) — это сердце инъекции. Функция
EXTRACTVALUE(XML_document, XPath_expression)извлекает значение из XML. Если XPath-выражение некорректно, MySQL генерирует ошибку. В нашем случае: - Первый аргумент
8651— это произвольное число, которое не является XML-документом. EXTRACTVALUE ожидает XML, но получает число, что уже может вызвать ошибку. - Второй аргумент —
CONCAT(0x7e, ((SELECT (ELT(8651=8651,1)))), 0x7e).0x7e— это шестнадцатеричное представление символа~(тильда).ELT(N, str1, str2, ...)возвращает N-ю строку из списка. ЗдесьELT(8651=8651,1)— условие8651=8651истинно, что даёт 1, поэтому ELT возвращает первый элемент —1. То есть подзапрос возвращает строку'1'. - В итоге CONCAT склеивает:
~1~. Этот результат подставляется в XPath-выражение. Поскольку~1~не является допустимым XPath, EXTRACTVALUE выдаёт ошибку видаXPATH syntax error: '~1~'. В сообщении об ошибке отображается наш результат —1. - -- - — это комментарий в SQL. Всё, что идёт после
--, игнорируется сервером. Пробел после--обязателен в MySQL, поэтому пишут-- -или--+.
Таким образом, вся конструкция заставляет MySQL выполнить подзапрос, вернуть его результат в составе сообщения об ошибке, которое затем увидит атакующий.
Зачем это нужно злоумышленнику?
Цель — извлечь данные, которые не отображаются на странице. В примере с ELT(8651=8651,1) возвращается просто 1, но в реальной атаке вместо этого подзапроса может быть, например, (SELECT version()) или (SELECT password FROM users LIMIT 1). Тогда в ошибке появится версия СУБД или хеш пароля. Поскольку ошибки часто показываются в отладочном режиме, это прямой канал утечки.
Более того, с помощью EXTRACTVALUE можно извлекать данные посимвольно, используя SUBSTRING и LIMIT, что позволяет полностью выгрузить базу.
Пример реальной атаки
Представим уязвимый скрипт на PHP:
$id = $_GET['id'];
$query = "SELECT * FROM products WHERE id = '$id'";
$result = mysqli_query($conn, $query);
if (!$result) {
echo mysqli_error($conn);
}
Если передать id=1' AND EXTRACTVALUE(1,CONCAT(0x7e,(SELECT version()),0x7e))-- -, то в браузере отобразится ошибка: XPATH syntax error: '~5.7.33~'. Так атакующий узнаёт версию MySQL.
Наша строка %')) AND EXTRACTVALUE(...) — это вариация для случаев, когда входные данные обёрнуты в двойные кавычки и скобки, например: WHERE name = ("$input"). Символы %'))) закрывают кавычку и скобки, а затем добавляется AND ....
Как защититься от таких инъекций?
Лучший способ — использовать подготовленные выражения (prepared statements) с параметризацией. В PHP это PDO или mysqli с bind_param. Тогда пользовательский ввод никогда не интерпретируется как SQL-код.
Дополнительные меры:
- Экранирование специальных символов (но это менее надёжно, чем параметризация).
- Отключение вывода ошибок БД в продакшене — чтобы сообщения об ошибках не попадали к пользователю.
- Использование ORM, которые автоматически параметризуют запросы.
- Регулярное обновление СУБД и фреймворков.
- Применение WAF (Web Application Firewall) для блокировки подозрительных запросов.
Важно понимать, что EXTRACTVALUE и подобные функции — не уязвимость MySQL, а инструмент, который может быть использован при наличии ошибок в коде приложения.
Заключение
Строка %')) AND EXTRACTVALUE(8651,CONCAT(0x7e,((SELECT (ELT(8651=8651,1)))),0x7e))-- - — это яркий пример error-based SQL-инъекции, эксплуатирующей функции MySQL для вывода данных через сообщения об ошибках. Понимание таких конструкций помогает разработчикам осознать важность безопасного кодирования и использования подготовленных выражений. Никогда не доверяйте пользовательскому вводу и всегда проверяйте его на стороне сервера.
Комментарии
—Войдите, чтобы оставить комментарий