Введение
SQL-инъекции остаются одной из самых распространённых угроз для веб-приложений. Среди них выделяется класс error-based инъекций, когда злоумышленник извлекает данные через сообщения об ошибках базы данных. Одним из классических примеров является использование функции EXTRACTVALUE в СУБД MySQL. В этой статье мы разберём, как работает строка вида %') AND EXTRACTVALUE(2103,CONCAT(0x7e,((SELECT (ELT(2103=2103,1)))),0x7e))-- -, зачем она нужна и как защитить свой сайт.
Что такое SQL-инъекция?
SQL-инъекция (SQL injection) — это способ внедрения вредоносного SQL-кода в запросы к базе данных через пользовательский ввод. Если приложение не проверяет и не экранирует входные данные, злоумышленник может выполнить произвольные SQL-команды: получить доступ к конфиденциальной информации, изменить или удалить данные, а в некоторых случаях — выполнить команды на сервере.
Error-based инъекции — это подкласс, при котором атакующий заставляет базу данных выдать сообщение об ошибке, содержащее полезные данные. MySQL, в отличие от некоторых других СУБД, может возвращать детализированные ошибки, что делает этот метод очень эффективным.
Функция EXTRACTVALUE
EXTRACTVALUE — это встроенная функция MySQL (до версии 8.0), предназначенная для извлечения значения из XML-строки по заданному XPath-выражению. Синтаксис: EXTRACTVALUE(XML_fragment, XPath_expression). Если XPath-выражение некорректно, функция генерирует ошибку, которая включает переданный фрагмент. Эту особенность и используют злоумышленники.
Например, запрос SELECT EXTRACTVALUE(1, CONCAT(0x7e, (SELECT version()), 0x7e)) вызовет ошибку вида XPATH syntax error: '~5.7.32~', где 0x7e — это тильда (~), служащая маркером для облегчения чтения результата.
Разбор примера инъекции
Рассмотрим строку: %') AND EXTRACTVALUE(2103,CONCAT(0x7e,((SELECT (ELT(2103=2103,1)))),0x7e))-- -
- %') — часть, которая закрывает предыдущее выражение в уязвимом запросе. Символ
%часто используется в LIKE-запросах, а')закрывает скобку и кавычку, чтобы вставить свой код. - AND EXTRACTVALUE(...) — добавляет условие, которое всегда ложно (или истинно, в зависимости от контекста), но главное — вызывает выполнение функции EXTRACTVALUE.
- 2103 — произвольное число, первый аргумент EXTRACTVALUE. Он не несёт смысловой нагрузки, но должен быть допустимого типа.
- CONCAT(0x7e,((SELECT (ELT(2103=2103,1)))),0x7e) — формирует строку для XPath.
ELT(2103=2103,1)возвращает 1, так как условие истинно. Это простейший пример; на практике вместоELTподставляют подзапросы, извлекающие данные (например, имена таблиц, пароли). - -- - — комментарий, который обрезает оставшуюся часть оригинального запроса, чтобы синтаксис был корректным.
В результате выполнения такого запроса MySQL вернёт ошибку, содержащую результат подзапроса, обёрнутый в тильды. Например: XPATH syntax error: '~1~'. Злоумышленник, подставляя разные подзапросы, может посимвольно извлекать данные из базы.
Зачем это нужно атакующему?
Error-based инъекции позволяют быстро получать информацию, не прибегая к слепым методам (boolean-based или time-based), которые требуют множества запросов и времени. EXTRACTVALUE даёт возможность вытащить целую строку за один запрос, что делает атаку очень эффективной. С помощью таких инъекций можно:
- Получить версию СУБД, имена таблиц и колонок.
- Извлечь логины и пароли пользователей.
- Читать другие конфиденциальные данные.
Примеры практического использования
В учебных целях (например, на платформе DVWA или SQLZoo) часто демонстрируют следующие вариации:
' AND EXTRACTVALUE(1, CONCAT(0x7e, (SELECT database()), 0x7e))-- -
Этот запрос вернёт имя текущей базы данных. Аналогично можно получить список таблиц:
' AND EXTRACTVALUE(1, CONCAT(0x7e, (SELECT table_name FROM information_schema.tables WHERE table_schema=database() LIMIT 0,1), 0x7e))-- -
Обратите внимание, что в реальных атаках злоумышленники комбинируют EXTRACTVALUE с другими функциями, например UPDATEXML, чтобы обойти фильтры.
Как защититься от SQL-инъекций?
Основной принцип — никогда не доверять пользовательскому вводу. Вот ключевые меры:
- Использование подготовленных выражений (prepared statements). Это самый надёжный способ. Параметризованные запросы отделяют код от данных, и внедрение SQL становится невозможным.
- Экранирование специальных символов. Если по каким-то причинам нельзя использовать подготовленные выражения, применяйте функции экранирования (например,
mysqli_real_escape_stringв PHP). Но помните, что это не панацея. - Валидация входных данных. Проверяйте, что вводимые данные соответствуют ожидаемому формату (числа, email, даты и т.д.).
- Ограничение прав пользователя БД. Не давайте приложению прав на удаление таблиц или доступ к системным таблицам, если это не требуется.
- Регулярное обновление СУБД. В MySQL 8.0 функция EXTRACTVALUE удалена, что снижает риск таких атак. Однако старые версии всё ещё используются.
- Использование WAF (Web Application Firewall). Современные WAF могут обнаруживать и блокировать попытки SQL-инъекций, но не стоит полагаться только на них.
Заключение
SQL-инъекция через EXTRACTVALUE — яркий пример того, как ошибки в коде могут привести к утечке данных. Понимание механизма атаки помогает разработчикам осознать важность безопасного программирования. Всегда используйте подготовленные выражения, валидируйте входные данные и следите за обновлениями используемых технологий. Безопасность — это процесс, а не одноразовое действие.
Комментарии
—Войдите, чтобы оставить комментарий