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

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

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

Разбор функций: EXTRACTVALUE, CONCAT, ELT

EXTRACTVALUE

EXTRACTVALUE(XML_frag, XPath_expr) — функция MySQL, которая извлекает значение из XML-фрагмента по заданному XPath-выражению. Если XPath-выражение некорректно или возвращает несколько узлов, MySQL генерирует ошибку, содержащую переданные данные. Именно это и используется для извлечения информации.

CONCAT

CONCAT(str1, str2, ...) объединяет строки. В нашем случае он склеивает символ ~ (0x7e), результат подзапроса и снова ~. Это нужно, чтобы отделить полезные данные в сообщении об ошибке.

ELT

ELT(N, str1, str2, ...) возвращает N-ю строку из списка. В запросе ELT(7998=7998,1) условие 7998=7998 всегда истинно (возвращает 1), поэтому ELT вернёт первый элемент — число 1. Это простейший пример, демонстрирующий работу механизма. В реальных атаках вместо 1 подставляются имена таблиц, столбцов или другие данные, полученные через подзапросы.

Как работает внедрение

Предположим, что исходный SQL-запрос выглядит так:

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

Если параметр $input не экранируется, злоумышленник может передать строку:

1' AND EXTRACTVALUE(7998,CONCAT(0x7e,((SELECT (ELT(7998=7998,1)))),0x7e))-- -

Тогда итоговый запрос примет вид:

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

СУБД выполнит функцию EXTRACTVALUE. Поскольку второй аргумент (XPath) содержит символ ~, который не является допустимым XPath-выражением, MySQL сгенерирует ошибку вида:

XPATH syntax error: '~1~'

В тексте ошибки появятся данные, возвращённые подзапросом. В нашем примере это просто 1, но в реальной атаке вместо ELT(7998=7998,1) может быть, например, (SELECT version()) или (SELECT table_name FROM information_schema.tables LIMIT 1).

Символы -- - в конце — это комментарий, который отсекает остаток оригинального запроса (например, закрывающую кавычку), чтобы синтаксис оставался корректным.

Цели и опасность error-based инъекций

Error-based SQL-инъекции позволяют злоумышленнику получать данные напрямую из сообщений об ошибках. Это быстрее и проще, чем слепые (blind) инъекции, где информацию приходится извлекать по битам. С помощью таких атак можно:

  • Получить версию СУБД, имя пользователя, имя базы данных.
  • Извлечь содержимое таблиц: логины, пароли, персональные данные.
  • В некоторых случаях выполнить произвольные команды на сервере (при наличии соответствующих привилегий).

Особенно опасны подобные уязвимости для сайтов, работающих с персональными данными, платёжной информацией или коммерческой тайной.

Примеры реальных полезных нагрузок

Вместо ELT(7998=7998,1) атакующий может использовать:

  • (SELECT database()) — имя текущей базы данных.
  • (SELECT user()) — текущий пользователь MySQL.
  • (SELECT version()) — версия сервера.
  • (SELECT table_name FROM information_schema.tables WHERE table_schema=database() LIMIT 1) — имя первой таблицы.
  • (SELECT column_name FROM information_schema.columns WHERE table_name='users' LIMIT 1) — имя столбца.
  • (SELECT password FROM users LIMIT 1) — хеш пароля.

Все эти данные будут возвращены в тексте ошибки, если приложение выводит сообщения об ошибках пользователю.

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

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

  • Экранирование специальных символов (например, с помощью mysqli_real_escape_string).
  • Использование ORM (например, Doctrine, Hibernate), которые автоматически применяют параметризацию.
  • Ограничение привилегий пользователя базы данных: не давать прав на чтение information_schema, если это не нужно.
  • Отключение вывода подробных ошибок в production-окружении: сообщения об ошибках не должны показываться пользователю.
  • Регулярное обновление СУБД и фреймворков для устранения известных уязвимостей.
  • Использование WAF (Web Application Firewall) для блокировки подозрительных запросов.

Важно понимать, что фильтрация чёрных списков (например, удаление слова EXTRACTVALUE) неэффективна, так как злоумышленник может использовать другие функции (UPDATEXML, GTID_SUBSET и т.д.) или обфускацию.

Заключение

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

Помните: лучшая защита — это параметризованные запросы и минимизация привилегий базы данных.

Источники