Введение

В запросе пользователя указана строка %\") OR EXTRACTVALUE(1579,CONCAT(0x7e,((SELECT (ELT(1579=1579,1)))),0x7e))-- -. Это классический пример полезной нагрузки для error-based SQL-инъекции через функцию EXTRACTVALUE в СУБД MySQL или MariaDB. В данной статье мы детально разберём, что делает каждый элемент этого запроса, как злоумышленники используют такие конструкции для извлечения данных и как защититься от подобных атак.

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

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

Существует несколько типов SQL-инъекций: UNION-based, error-based, blind (boolean и time-based). Наш случай относится к error-based — злоумышленник намеренно вызывает ошибку базы данных, чтобы в её тексте увидеть результат подзапроса.

Разбор полезной нагрузки

Рассмотрим строку по частям:

  • %\") — закрывающая кавычка и скобка, которые завершают оригинальный запрос приложения. Символ % может быть частью URL-кодирования, а \ — экранированием. Часто такая последовательность используется, чтобы «вырваться» из строкового литерала в уязвимом параметре.
  • OR EXTRACTVALUE(...) — логический оператор OR, после которого вызывается функция EXTRACTVALUE. Если исходное условие ложно, СУБД вычислит правую часть, что и приводит к выполнению внедрённого кода.
  • EXTRACTVALUE(1579, CONCAT(0x7e, (SELECT (ELT(1579=1579,1))), 0x7e)) — сама функция. EXTRACTVALUE(XML_fragment, XPath_expression) извлекает значение из XML-документа по XPath. Если XPath-выражение некорректно, MySQL генерирует ошибку, в тексте которой отображается переданный фрагмент.
  • CONCAT(0x7e, ..., 0x7e) — объединяет символ ~ (0x7e) с результатом подзапроса и ещё одним ~. Тильды служат маркерами, по которым атакующий легко находит выведенные данные в сообщении об ошибке.
  • (SELECT (ELT(1579=1579,1))) — подзапрос, возвращающий значение. ELT(N, str1, str2, ...) возвращает N-ю строку из списка. Здесь 1579=1579 — всегда истина (1), поэтому ELT(1,1) вернёт 1. В реальной атаке вместо этой заглушки стоял бы подзапрос к системным таблицам, например, SELECT password FROM users LIMIT 1.
  • -- - — комментарий, который отсекает оставшуюся часть оригинального SQL-запроса.

Таким образом, при выполнении уязвимого запроса база данных попытается обработать XPath-выражение, содержащее символ ~ и результат подзапроса, что вызовет ошибку вида XPATH syntax error: '~1~'. Атакующий увидит эту ошибку на странице и получит искомые данные.

Почему EXTRACTVALUE используется для error-based инъекций?

Функция EXTRACTVALUE появилась в MySQL 5.1 и предназначена для работы с XML. Однако при передаче некорректного XPath-выражения она возвращает ошибку, текст которой содержит переданный фрагмент. Это делает её удобным инструментом для извлечения данных через сообщения об ошибках. Аналогичными свойствами обладают UPDATEXML и GTID_SUBSET.

Важно: в MySQL 5.7+ и MariaDB 10.2+ использование EXTRACTVALUE в некоторых конфигурациях может быть ограничено, но на устаревших версиях она по-прежнему работает.

Пример эксплуатации

Предположим, есть уязвимый параметр id в URL: https://example.com/product?id=1. Злоумышленник подставляет:

1 AND EXTRACTVALUE(1, CONCAT(0x7e, (SELECT version()), 0x7e))

В ответе сервера появится ошибка: XPATH syntax error: '~5.7.32~'. Так узнаётся версия СУБД. Далее можно извлекать имена таблиц, столбцов и содержимое базы.

Последствия успешной атаки

  • Утечка конфиденциальных данных: логины, пароли, персональные данные пользователей.
  • Компрометация всей базы данных, включая возможность изменения или удаления записей.
  • В некоторых случаях — выполнение команд на сервере через LOAD_FILE или INTO OUTFILE.
  • Репутационные и финансовые потери для владельца сайта.

Как защититься от error-based SQL-инъекций

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

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

  1. Валидация и фильтрация входных данных: проверяйте типы, длины, допустимые символы.
  2. Экранирование специальных символов с помощью функций СУБД, например mysqli_real_escape_string.
  3. Отключение вывода ошибок базы данных на продакшене: сообщения об ошибках не должны попадать в браузер.
  4. Использование ORM и современных фреймворков, которые по умолчанию применяют параметризацию.
  5. Регулярное обновление СУБД и веб-приложений.
  6. Применение WAF (Web Application Firewall) для блокировки подозрительных запросов.

Заключение

Строка %\") OR EXTRACTVALUE(1579,CONCAT(0x7e,((SELECT (ELT(1579=1579,1)))),0x7e))-- - — это не случайный набор символов, а тщательно сконструированная полезная нагрузка для error-based SQL-инъекции. Понимание её работы помогает разработчикам и специалистам по безопасности лучше защищать свои приложения. Помните: ни один пользовательский ввод нельзя доверять без проверки.

Источники