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

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

В основе лежит функция EXTRACTVALUE, предназначенная для работы с XML. Она принимает два аргумента: XML-документ и XPath-выражение. Если XPath-выражение синтаксически некорректно, MySQL генерирует ошибку, в тексте которой может содержаться переданная строка. Именно это свойство используется для error-based SQL-инъекции — метода, при котором данные извлекаются через сообщения об ошибках базы данных.

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

Рассмотрим структуру запроса детально:

  • OR — логический оператор, который добавляется к исходному условию WHERE. Если исходное условие ложно, OR с истинным выражением сделает всё условие истинным, что может привести к возврату всех строк таблицы.
  • EXTRACTVALUE(9800, ...) — вызов функции. Первый аргумент 9800 — это произвольное число, которое интерпретируется как XML-фрагмент (в данном случае не является валидным XML, но это не мешает вызову).
  • CONCAT(0x7e, ..., 0x7e) — функция конкатенации. 0x7e — это шестнадцатеричное представление символа тильды (~). Тильда используется как разделитель, чтобы облегчить поиск внедрённых данных в тексте ошибки.
  • ((SELECT (ELT(9800=9800,1)))) — подзапрос, который возвращает результат функции ELT. ELT(N, str1, str2, ...) возвращает N-ю строку из списка. Здесь 9800=9800 — всегда истинное условие, поэтому ELT возвращает 1 (первый элемент). В реальной атаке вместо 1 мог бы быть, например, version() или database().
  • -- - — комментарий, который отсекает оставшуюся часть оригинального SQL-запроса, чтобы не нарушать его синтаксис.

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

Предположим, что веб-приложение формирует запрос вида:

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

Если злоумышленник передаст в $input строку 1 OR EXTRACTVALUE(9800,CONCAT(0x7e,((SELECT (ELT(9800=9800,1)))),0x7e))-- -, то итоговый запрос станет таким:

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

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

Стоит отметить, что EXTRACTVALUE была удалена в MySQL 8.0. В более старых версиях (5.7 и ниже) она доступна и активно использовалась в эксплойтах. Аналогичный принцип применяется с функциями UPDATEXML и GTID_SUBSET.

Цели и последствия

Основная цель такой инъекции — получить несанкционированный доступ к данным. В зависимости от привилегий пользователя базы данных злоумышленник может:

  • Читать содержимое таблиц (персональные данные, хеши паролей, платёжная информация).
  • Изменять или удалять данные.
  • Выполнять административные операции, если уязвимость позволяет обойти аутентификацию.

Error-based инъекции особенно опасны, потому что они не требуют слепого перебора и дают немедленный результат в виде сообщения об ошибке. Однако они возможны только тогда, когда приложение выводит ошибки СУБД пользователю.

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

Чтобы предотвратить подобные атаки, разработчикам следует придерживаться следующих правил:

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

Важно понимать, что EXTRACTVALUE — не единственная функция, эксплуатируемая в error-based атаках. Злоумышленники также используют UPDATEXML, XMLType, GTID_SUBSET и другие. Поэтому защита должна быть комплексной.

Заключение

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

Источники