Введение

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

В этой статье мы детально разберём каждый элемент запроса, объясним, как работает атака, и покажем, как защититься от подобных угроз.

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

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

Error-based SQL-инъекция — это техника, при которой атакующий заставляет базу данных вернуть сообщение об ошибке, содержащее полезную информацию (например, версию СУБД, имена таблиц, данные из полей). MySQL охотно делится такими подробностями, если не отключить вывод ошибок.

Разбор строки `%')) AND EXTRACTVALUE(1708,CONCAT(0x7e,((SELECT (ELT(1708=1708,1)))),0x7e))-- -`

Давайте разберём эту строку по частям. Предположим, что она вставлена в параметр, который в исходном запросе выглядит так: SELECT * FROM users WHERE name = '%...'. Тогда часть %')) закрывает кавычку и скобку, разрывая исходный запрос, а далее идёт внедрённый код.

  • %')) — закрывает строковый литерал и круглую скобку, завершая оригинальное условие. Символ % может быть любым, это просто заполнитель.
  • AND — логический оператор, присоединяющий дополнительное условие.
  • EXTRACTVALUE(1708, CONCAT(0x7e, ((SELECT (ELT(1708=1708,1)))), 0x7e)) — вызов функции MySQL, которая извлекает значение из XML-строки. Первый аргумент — произвольное число (1708), второй — XPath-выражение. Если XPath некорректен, MySQL выдаёт ошибку, в тексте которой отображается переданное выражение.
  • CONCAT(0x7e, ..., 0x7e) — объединяет символ ~ (0x7e) с результатом подзапроса и ещё одним ~. Это делается, чтобы отделить полезные данные в сообщении об ошибке.
  • (SELECT (ELT(1708=1708,1))) — подзапрос, возвращающий число 1. Функция ELT(N, str1, str2, ...) возвращает N-ю строку из списка. Здесь 1708=1708 — истина (1), поэтому ELT(1,1) вернёт 1. Это простейший пример, но на месте 1 может быть любой другой подзапрос, например, извлечение имени пользователя или пароля.
  • -- - — комментарий, который заставляет MySQL игнорировать оставшуюся часть исходного запроса (пробел после -- обязателен).

В результате MySQL выполнит функцию EXTRACTVALUE с некорректным XPath (потому что ~1~ не является валидным XPath), и вернёт ошибку вида: XPATH syntax error: '~1~'. В этом сообщении атакующий увидит результат подзапроса — в данном случае 1. Меняя подзапрос, можно извлекать любые данные.

Почему это работает?

MySQL позволяет использовать функции EXTRACTVALUE и UPDATEXML для работы с XML. Если передать в них заведомо неверный XPath, содержащий специально сформированную строку, СУБД включает эту строку в текст ошибки. Это и есть основа error-based инъекции.

Пример из реальной практики: на уязвимом сайте в параметре id передаётся 1' AND EXTRACTVALUE(1, CONCAT(0x7e, (SELECT database()), 0x7e))-- -. В ответе сервера появляется ошибка с именем текущей базы данных.

Как защититься?

Основной способ защиты — использование параметризованных запросов (prepared statements). Они не позволяют данным влиять на структуру SQL-запроса.

Дополнительные меры:

  • Отключите вывод подробных ошибок MySQL в продакшене (директива display_errors = Off в php.ini или соответствующие настройки сервера).
  • Используйте ORM или библиотеки, которые экранируют спецсимволы.
  • Применяйте принцип наименьших привилегий для пользователя базы данных: веб-приложение не должно иметь прав на чтение системных таблиц.
  • Регулярно обновляйте СУБД и фреймворки.
  • Установите WAF (Web Application Firewall), который может блокировать известные шаблоны инъекций.

Заключение

Строка %')) AND EXTRACTVALUE(1708,CONCAT(0x7e,((SELECT (ELT(1708=1708,1)))),0x7e))-- - — это не случайный набор символов, а целенаправленная попытка эксплуатации уязвимости. Понимание механики таких атак помогает разработчикам и администраторам своевременно закрывать дыры в безопасности. Если вы нашли подобную строку в логах, стоит немедленно проверить код приложения на наличие SQL-инъекций и принять меры.

Источники