Строка ) AND EXTRACTVALUE(4898,CONCAT(0x7e,((SELECT (ELT(4898=4898,1)))),0x7e))-- - — это классический пример error-based SQL-инъекции для СУБД MySQL. Она предназначена для извлечения данных из базы через вывод сообщения об ошибке. В данной статье мы подробно разберём, как работает эта конструкция, какие функции MySQL задействованы и как защититься от подобных атак.

Что такое SQL-инъекция?

SQL-инъекция (SQL injection) — это один из самых распространённых способов атаки на веб-приложения, при котором злоумышленник внедряет произвольный SQL-код в запрос к базе данных. Если приложение недостаточно фильтрует пользовательский ввод, вредоносный код выполняется на сервере базы данных. Это может привести к утечке конфиденциальной информации, изменению или удалению данных, а в некоторых случаях — к полному захвату сервера.

Существует несколько разновидностей SQL-инъекций: union-based, boolean-based, time-based и error-based. Рассматриваемая строка относится именно к error-based типу.

Разбор строки по частям

Давайте разберём конструкцию ) AND EXTRACTVALUE(4898,CONCAT(0x7e,((SELECT (ELT(4898=4898,1)))),0x7e))-- - на составляющие.

1. Закрывающая скобка и оператор AND

Строка начинается с символа ). Это закрывающая скобка, которая, вероятно, завершает какой-то фрагмент оригинального запроса, например, условие в скобках. Далее идёт AND — логический оператор, который добавляет новое условие к существующему запросу. Злоумышленник предполагает, что исходный запрос выглядит примерно так:

SELECT * FROM users WHERE id = (какой-то параметр) AND ...

Внедряя ) AND ..., он закрывает скобку и добавляет своё условие.

2. Функция EXTRACTVALUE

EXTRACTVALUE() — это встроенная функция MySQL, предназначенная для работы с XML. Она извлекает значение из XML-документа по заданному XPath-выражению. Синтаксис:

EXTRACTVALUE(xml_frag, xpath_expr)

Функция возвращает текст узла, соответствующего XPath. Однако, если XPath-выражение некорректно, MySQL генерирует сообщение об ошибке, в котором может содержаться часть переданных данных. Это и используется в error-based инъекциях.

3. CONCAT и шестнадцатеричные литералы

CONCAT(0x7e, ((SELECT (ELT(4898=4898,1)))), 0x7e) — здесь 0x7e — это шестнадцатеричное представление символа ~ (тильда). Функция CONCAT объединяет строки. Таким образом, злоумышленник оборачивает результат подзапроса в тильды, чтобы облегчить его поиск в сообщении об ошибке.

4. Подзапрос с ELT

(SELECT (ELT(4898=4898,1))) — это подзапрос, который возвращает результат функции ELT(). ELT(N, str1, str2, ...) возвращает N-ю строку из списка. В данном случае 4898=4898 — это логическое выражение, которое всегда истинно (1). Поэтому ELT(1, 1) вернёт 1. То есть подзапрос вернёт строку '1'. Это простейший пример; на практике вместо 1 может быть имя таблицы, версия СУБД или другие данные.

5. Комментарий в конце

-- - — это комментарий в SQL. В MySQL комментарий начинается с -- (два дефиса и пробел) и продолжается до конца строки. Символ - после пробела добавлен для надёжности, чтобы гарантировать, что комментарий распознается даже в некоторых нестандартных конфигурациях. Всё, что идёт после -- -, игнорируется базой данных. Это позволяет отсечь остаток оригинального запроса.

Как работает атака

Когда MySQL выполняет запрос, содержащий EXTRACTVALUE с некорректным XPath, он выдаёт ошибку вида:

XPATH syntax error: '~1~'

В этом сообщении отображается переданная строка, включая результат подзапроса. Злоумышленник может подставить вместо 1 любой другой SQL-запрос, например, (SELECT database()), чтобы получить имя текущей базы данных, или (SELECT version()) для версии MySQL. Поскольку сообщение об ошибке возвращается клиенту (если приложение не подавляет ошибки), атакующий может последовательно извлекать данные.

Таким образом, данная строка — это шаблон для проверки уязвимости и извлечения информации. Число 4898 в EXTRACTVALUE(4898, ...) — это просто произвольный идентификатор (может быть любым), он не несёт смысловой нагрузки. Аналогично, 4898=4898 — всегда истинное условие, используемое для демонстрации.

Пример реального использования

Предположим, на сайте есть страница product.php?id=1, и параметр id подставляется в SQL-запрос без экранирования. Злоумышленник может отправить:

product.php?id=1) AND EXTRACTVALUE(4898,CONCAT(0x7e,(SELECT database()),0x7e))-- -

В ответе сервера он увидит ошибку с именем базы данных. Это подтверждает наличие уязвимости и позволяет продолжить атаку.

Меры защиты

Чтобы предотвратить подобные атаки, необходимо применять комплекс мер:

  • Использование подготовленных выражений (prepared statements). Это самый надёжный способ, при котором SQL-код и данные передаются раздельно, и база данных не интерпретирует ввод как часть запроса.
  • Экранирование специальных символов. Если подготовленные выражения недоступны, следует использовать функции экранирования, предоставляемые драйвером БД (например, mysqli_real_escape_string в PHP).
  • Валидация входных данных. Проверка типов, форматов, белых списков допустимых значений.
  • Ограничение прав пользователя БД. Приложение должно работать с базой от имени пользователя с минимально необходимыми привилегиями.
  • Отключение вывода ошибок БД в production. Сообщения об ошибках не должны попадать к конечному пользователю.
  • Использование WAF (Web Application Firewall). Может помочь обнаружить и заблокировать попытки инъекций, но не является панацеей.

Заключение

Строка ) AND EXTRACTVALUE(4898,CONCAT(0x7e,((SELECT (ELT(4898=4898,1)))),0x7e))-- - — это типичный пример error-based SQL-инъекции, использующей особенности функций MySQL EXTRACTVALUE и ELT. Понимание механики таких атак помогает разработчикам и специалистам по безопасности правильно выстраивать защиту. Никогда не доверяйте пользовательскому вводу и всегда используйте параметризованные запросы.

Источники