Введение
SQL-инъекции остаются одной из самых опасных уязвимостей веб-приложений. Среди множества техник особое место занимает error-based SQL injection, при которой злоумышленник заставляет базу данных возвращать данные прямо в сообщениях об ошибках. Запрос, который вы видите — '))) AND EXTRACTVALUE(1054,CONCAT(0x7e,((SELECT (ELT(1054=1054,1)))),0x7e))-- - — представляет собой классический пример такой атаки на MySQL. В этой статье мы детально разберём, что означает каждый элемент этого запроса, как работает функция ExtractValue, почему возникает ошибка 1054 и как защититься от подобных атак.
Что такое error-based SQL инъекция?
Error-based SQL injection — это метод эксплуатации уязвимости, при котором атакующий использует механизм вывода ошибок СУБД для получения информации. Вместо того чтобы напрямую извлекать данные через UNION-запросы или слепые инъекции, злоумышленник конструирует запрос таким образом, чтобы нужные данные попали в текст ошибки. MySQL, в отличие от некоторых других СУБД, охотно раскрывает детали ошибок, что делает эту технику очень эффективной.
Основные функции MySQL, используемые для error-based инъекций:
- ExtractValue() — извлекает значение из XML-строки по заданному XPath-выражению. При некорректном XPath возвращает ошибку с указанием переданного аргумента.
- UpdateXML() — заменяет часть XML-документа. Также генерирует ошибку при неправильном XPath.
- Floor() и Rand() — комбинация для вызова ошибки дублирования ключа.
Разбор запроса: ExtractValue(1054, CONCAT(0x7e, ...))
Рассмотрим структуру запроса по частям.
1. Начало: ')))
Символы '))) закрывают предыдущие кавычки и скобки в уязвимом параметре. Это типичный приём для выхода из контекста оригинального SQL-запроса. Количество скобок и кавычек подбирается в зависимости от структуры исходного запроса на сервере.
2. AND EXTRACTVALUE(1054, CONCAT(...))
Оператор AND добавляет условие к оригинальному запросу. Функция EXTRACTVALUE(XML_document, XPath_expression) принимает два аргумента. Первый аргумент — 1054 — это просто число, которое будет интерпретировано как XML-документ (что само по себе некорректно, но это не важно, так как ошибка возникнет раньше). Второй аргумент — результат CONCAT, который формирует строку, начинающуюся и заканчивающуюся тильдой ~ (0x7e в шестнадцатеричном виде).
3. CONCAT(0x7e, ((SELECT (ELT(1054=1054,1)))), 0x7e)
Функция CONCAT объединяет три части: тильду, результат подзапроса и ещё одну тильду. Подзапрос SELECT (ELT(1054=1054,1)) использует функцию ELT(N, str1, str2, ...), которая возвращает N-ную строку из списка. В данном случае 1054=1054 — это истинное выражение, которое в MySQL возвращает 1. Таким образом, ELT(1, 1) вернёт строку '1'. Тильды нужны для того, чтобы отделить выводимые данные в сообщении об ошибке и облегчить их извлечение.
4. Завершение: -- -
Комментарий -- - (с пробелом после двух дефисов) отсекает оставшуюся часть оригинального SQL-запроса, чтобы синтаксис был корректным.
Почему возникает ошибка 1054?
Ошибка 1054 в MySQL — это ER_BAD_FIELD_ERROR, которая означает «Unknown column '...' in 'field list'». Однако в контексте error-based инъекции через ExtractValue ошибка 1054 может возникать по другой причине: когда XPath-выражение, переданное в ExtractValue, содержит недопустимые символы, MySQL возвращает ошибку вида XPATH syntax error: '~1~'. Число 1054 в запросе — это не код ошибки, а просто произвольное число, переданное в качестве первого аргумента. Оно может быть любым; главное — чтобы ExtractValue получила на вход некорректный XPath, что приведёт к выводу переданной строки в тексте ошибки.
Таким образом, атакующий может заменить подзапрос ELT(1054=1054,1) на любой другой, например, SELECT version() или SELECT database(), и получить результат в сообщении об ошибке. Это и есть суть атаки.
Практический пример эксплуатации
Предположим, уязвимый параметр — id в URL http://example.com/product.php?id=1. Оригинальный запрос может выглядеть так:
SELECT * FROM products WHERE id = '1'
Атакующий подставляет:
1' AND EXTRACTVALUE(1054,CONCAT(0x7e,(SELECT version()),0x7e))-- -
Если инъекция успешна, сервер вернёт ошибку, содержащую версию MySQL, например: XPATH syntax error: '~5.7.34~'. Аналогично можно извлечь имена таблиц, колонок и сами данные.
Как защититься от error-based SQL инъекций
Основной метод защиты — использование параметризованных запросов (prepared statements). Это полностью исключает возможность внедрения SQL-кода, так как данные передаются отдельно от структуры запроса. Дополнительные меры:
- Экранирование специальных символов — используйте функции экранирования, предоставляемые драйвером БД (например, mysqli_real_escape_string в PHP).
- Валидация входных данных — проверяйте, что параметры соответствуют ожидаемому типу (число, строка с ограниченным набором символов).
- Отключение вывода ошибок СУБД — в production-окружении не показывайте пользователям детали ошибок базы данных. Логируйте их, но не выводите в браузер.
- Использование ORM — современные ORM-библиотеки автоматически используют параметризацию.
- WAF — веб-application firewall может блокировать подозрительные запросы, содержащие функции ExtractValue, UpdateXML и подобные.
Заключение
Запрос '))) AND EXTRACTVALUE(1054,CONCAT(0x7e,((SELECT (ELT(1054=1054,1)))),0x7e))-- - — это учебный пример error-based SQL инъекции, демонстрирующий, как злоумышленники могут извлекать данные через сообщения об ошибках MySQL. Понимание этой техники необходимо разработчикам и специалистам по безопасности для построения надёжной защиты. Помните: лучшая защита — параметризованные запросы и минимальные привилегии для пользователя базы данных.
Комментарии
—Войдите, чтобы оставить комментарий