Что это за строка?

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

Подобные конструкции часто встречаются в отчётах пентестеров, на тренировочных платформах (DVWA, SQLZoo) и в эксплойтах. Понимание того, как они устроены, помогает разработчикам и администраторам распознавать атаки и выстраивать защиту.

Разбор по элементам

Рассмотрим каждый компонент запроса.

  • ) — закрывающая скобка. Она нужна, чтобы «закрыть» оригинальное выражение в уязвимом запросе и добавить собственное условие.
  • AND — логический оператор, который позволяет присоединить дополнительное условие к исходному WHERE. Если исходное условие истинно, выполнится и наша инъекция.
  • EXTRACTVALUE(8398, ...) — функция MySQL, извлекающая значение из XML-документа. В данном случае первый аргумент (8398) — это не XML, а число. Функция вызывается намеренно некорректно, чтобы спровоцировать ошибку, в текст которой попадёт результат второго аргумента.
  • CONCAT(0x7e, ..., 0x7e) — объединение строк. 0x7e — шестнадцатеричный код символа ~ (тильда). Тильды служат маркерами, чтобы в сообщении об ошибке легко было найти внедрённые данные.
  • (SELECT (ELT(8398=8398,1))) — подзапрос. ELT(N, str1, str2, ...) возвращает строку по номеру N. Выражение 8398=8398 всегда истинно (1), поэтому ELT возвращает первый аргумент — строку '1'. В реальной атаке вместо этого подзапроса подставляют вызовы, извлекающие версию СУБД, имя пользователя, таблицы и т.п.
  • -- - — комментарий. В MySQL символы -- начинают комментарий до конца строки, а пробел после них обязателен. Дефис в конце часто добавляют для надёжности, чтобы комментарий точно сработал.

В результате выполнения такого запроса MySQL выдаёт ошибку вида: XPATH syntax error: '~1~'. Именно эти тильды и содержимое между ними возвращаются атакующему.

Зачем это нужно злоумышленнику

Error-based инъекции применяются, когда приложение не выводит данные напрямую (например, при UNION-инъекции), но показывает сообщения об ошибках БД. С помощью EXTRACTVALUE, UPDATEXML или GEOMETRYCOLLECTION можно заставить сервер вернуть произвольные данные в тексте ошибки.

Пример из реальной практики: замена ELT(8398=8398,1) на version() или user() позволяет узнать версию MySQL и текущего пользователя. Далее можно извлекать имена таблиц и колонок через information_schema.

Пример работы

Допустим, уязвимый запрос выглядит так:

SELECT * FROM users WHERE id = '$id';

Если передать в $id значение 1) AND EXTRACTVALUE(8398,CONCAT(0x7e,version(),0x7e))-- -, итоговый запрос станет:

SELECT * FROM users WHERE id = '1) AND EXTRACTVALUE(8398,CONCAT(0x7e,version(),0x7e))-- -';

Сервер вернёт ошибку с версией MySQL, например: XPATH syntax error: '~8.0.32~'.

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

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

  • Никогда не конкатенируйте ввод в SQL-строку.
  • Используйте ORM и библиотеки с параметризацией.
  • Отключите вывод подробных ошибок БД в production.
  • Применяйте WAF как дополнительный слой.
  • Проводите регулярные аудиты кода и пентесты.
Важно: даже если приложение не показывает ошибки, error-based инъекция может быть использована вслепую (blind), поэтому полагаться только на скрытие ошибок нельзя.

Вывод

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

Источники