Введение
В логах веб-сервера, в поле поиска или в параметрах URL иногда можно встретить странные строки, содержащие функции EXTRACTVALUE, CONCAT и ELT. Одна из таких строк — %')))) AND EXTRACTVALUE(8645,CONCAT(0x7e,((SELECT (ELT(8645=8645,1)))),0x7e))-- -. Многие пользователи и начинающие администраторы задаются вопросом: что это за конструкция и какова её цель? Ответ однозначен: это классический пример error-based SQL-инъекции, нацеленной на СУБД MySQL. Подобные строки используются злоумышленниками для извлечения данных из базы через вывод сообщения об ошибке.
Что такое SQL-инъекция?
SQL-инъекция (SQL injection) — это один из самых распространённых способов атаки на веб-приложения. Суть метода заключается во внедрении произвольного SQL-кода в запрос, который приложение отправляет в базу данных. Если разработчики не экранируют пользовательский ввод и не используют подготовленные выражения, злоумышленник может выполнить собственный запрос, прочитать, изменить или удалить данные.
Существует несколько разновидностей SQL-инъекций:
- Union-based — объединение результатов легитимного запроса с данными из других таблиц.
- Error-based — извлечение информации через сообщения об ошибках, которые возвращает СУБД.
- Blind — когда приложение не выводит ошибки, и атакующий задаёт вопросы базе, анализируя поведение страницы (true/false или временные задержки).
- Stacked queries — выполнение нескольких запросов подряд.
Рассматриваемая строка относится именно к error-based типу. Она заставляет MySQL сгенерировать ошибку, в тексте которой будут содержаться интересующие атакующего данные.
Разбор строки по частям
Давайте разберём запрос %')))) AND EXTRACTVALUE(8645,CONCAT(0x7e,((SELECT (ELT(8645=8645,1)))),0x7e))-- - поэлементно.
1. Начальные символы %'))))
Эта последовательность предназначена для того, чтобы «закрыть» исходный запрос приложения. Например, если в коде было что-то вроде SELECT * FROM users WHERE name = '$input', то подстановка %')))) позволяет завершить строковый литерал, закрыть скобки и подготовить почву для добавления собственного условия. Символ % часто используется как подстановочный знак в LIKE-запросах.
2. AND EXTRACTVALUE(8645, ...)
Функция EXTRACTVALUE() в MySQL предназначена для извлечения значения из XML-документа по заданному XPath-выражению. Синтаксис: EXTRACTVALUE(XML_document, XPath_expression). Если переданный фрагмент не является корректным XML или XPath-выражение не соответствует ожидаемому формату, MySQL возвращает ошибку XPATH syntax error. Именно это и нужно атакующему: в тексте ошибки будет отображён переданный фрагмент.
3. CONCAT(0x7e, ..., 0x7e)
Функция CONCAT() объединяет строки. Здесь она склеивает символ 0x7e (тильда «~») с результатом подзапроса и ещё одной тильдой. Тильда используется как маркер, чтобы в сообщении об ошибке было легко найти внедрённые данные. Символ 0x7e — это шестнадцатеричное представление символа «~».
4. (SELECT (ELT(8645=8645,1)))
Внутренний подзапрос использует функцию ELT(). ELT(N, str1, str2, ...) возвращает N-ю строку из списка. В данном случае 8645=8645 — это всегда истинное выражение, которое в MySQL приводится к числу 1. Значит, ELT(1, 1) вернёт строку «1». Это простейшая проверка работоспособности инъекции. В реальной атаке вместо 1 могли бы стоять, например, database(), user() или (SELECT password FROM users LIMIT 1).
5. Завершающие символы -- -
Двойной дефис с пробелом — это комментарий в SQL. Он «отрезает» оставшуюся часть оригинального запроса, чтобы синтаксис оставался корректным. Иногда вместо -- - используют #.
Как это работает на практике
Предположим, уязвимый запрос выглядит так:
SELECT id, title FROM articles WHERE title LIKE '%ЗАПРОС%'
После подстановки вредоносной строки запрос превращается в нечто подобное:
SELECT id, title FROM articles WHERE title LIKE '%%')))) AND EXTRACTVALUE(8645,CONCAT(0x7e,((SELECT (ELT(8645=8645,1)))),0x7e))-- -%'
MySQL попытается выполнить EXTRACTVALUE с аргументом, содержащим тильды и результат подзапроса. Поскольку это не является валидным XPath, СУБД вернёт ошибку вида:
XPATH syntax error: '~1~'
В сообщении об ошибке атакующий увидит «~1~». Если бы вместо 1 стоял вызов database(), он получил бы имя текущей базы данных. Это и есть основной механизм error-based инъекции.
Почему это опасно?
Error-based SQL-инъекции позволяют злоумышленнику:
- Получить имена таблиц и столбцов.
- Извлечь логины и пароли пользователей.
- Читать конфиденциальные данные (персональные сведения, номера карт).
- В некоторых случаях — изменять или удалять информацию.
Особенно опасны такие атаки для сайтов, где ввод пользователя напрямую попадает в SQL-запрос без фильтрации. Даже если приложение не выводит ошибки на экран, они могут попадать в логи, к которым иногда имеют доступ сторонние лица.
Как защититься от SQL-инъекций
Существует несколько надёжных способов предотвратить подобные атаки:
- Использовать подготовленные выражения (prepared statements). Это самый эффективный метод. Параметры передаются отдельно от SQL-кода, и база данных не интерпретирует их как часть запроса.
- Применять ORM-библиотеки. Современные фреймворки (например, Django ORM, Hibernate, Sequelize) автоматически экранируют данные.
- Валидировать и фильтровать ввод. Если поле должно содержать число, проверяйте, что это действительно число. Для строк используйте белые списки допустимых символов.
- Ограничить права пользователя БД. Учётная запись, от имени которой работает приложение, не должна иметь прав на удаление таблиц или доступ к системным схемам.
- Отключить вывод подробных ошибок. В production-окружении сообщения об ошибках не должны показываться пользователю. Это усложняет эксплуатацию error-based инъекций.
- Регулярно обновлять СУБД и библиотеки. В новых версиях MySQL функция EXTRACTVALUE помечена как устаревшая (deprecated), а в некоторых сборках её поведение изменено.
Заключение
Строка %')))) AND EXTRACTVALUE(8645,CONCAT(0x7e,((SELECT (ELT(8645=8645,1)))),0x7e))-- - — это не случайный набор символов, а тщательно сконструированный эксплойт для error-based SQL-инъекции в MySQL. Он использует функцию EXTRACTVALUE для генерации ошибки, в тексте которой передаются данные, полученные через вложенный подзапрос. Понимание механизма таких атак помогает разработчикам и администраторам своевременно закрывать уязвимости и защищать свои приложения.
Если вы обнаружили подобную строку в логах своего сайта, это тревожный сигнал: возможно, ваш ресурс пытаются взломать. Проверьте код на наличие уязвимостей и убедитесь, что все запросы к базе данных используют параметризацию.
Комментарии
—Войдите, чтобы оставить комментарий