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

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

Такие строки часто используются пентестерами и злоумышленниками для проверки наличия уязвимости и извлечения данных из базы. Если сайт уязвим, то в ответе сервера появится сообщение об ошибке, содержащее переданные данные, обрамлённые символами ~ (тильда, 0x7e).

Разбор составных частей

Давайте разберём строку по частям, чтобы понять её назначение.

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

Таким образом, вся конструкция заставляет MySQL выполнить EXTRACTVALUE(2856, CONCAT('~', 1, '~')). Поскольку 2856 не является корректным XML, MySQL выдаст ошибку вида XPATH syntax error: '~1~'. В реальной атаке вместо 1 подставляется подзапрос, извлекающий, например, имя пользователя или хеш пароля.

Как работает error-based SQL-инъекция

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

Основные функции MySQL, используемые для error-based инъекций:

  • EXTRACTVALUE() — извлекает значение из XML по XPath. При ошибке возвращает переданный XML.
  • UPDATEXML() — обновляет XML-документ. Также может вызывать ошибку с переданными данными.
  • GTID_SUBSET(), EXP() и другие — в зависимости от версии MySQL.

В нашем случае используется EXTRACTVALUE. Синтаксис: EXTRACTVALUE(XML_document, XPath_expression). Если XPath_expression начинается с недопустимого символа (например, тильды), MySQL выдаёт ошибку XPATH syntax error: '...', где ... — это переданное XPath-выражение.

Зачем нужен подзапрос с ELT?

Функция ELT(N, str1, str2, ...) возвращает N-й элемент из списка строк. В данном примере ELT(2856=2856,1) возвращает 1, потому что условие истинно (1). Это простейший случай, демонстрирующий работу. В реальной атаке вместо 1 может быть подзапрос, например, (SELECT password FROM users LIMIT 1). Тогда ELT не нужен, но он может использоваться для обхода фильтров или для приведения типов.

Конструкция SELECT (ELT(2856=2856,1)) — это просто подзапрос, возвращающий число 1. Он нужен, чтобы показать, что инъекция работает и может выполнять произвольные SQL-выражения.

Пример уязвимого запроса

Предположим, на сайте есть страница product.php?id=1, и в коде выполняется запрос:

SELECT * FROM products WHERE id = ('$_GET[id]')

Если передать id=1') AND EXTRACTVALUE(2856,CONCAT(0x7e,((SELECT (ELT(2856=2856,1)))),0x7e))-- -, то итоговый запрос станет:

SELECT * FROM products WHERE id = ('1') AND EXTRACTVALUE(2856,CONCAT(0x7e,((SELECT (ELT(2856=2856,1)))),0x7e))-- -')

MySQL выполнит EXTRACTVALUE и вернёт ошибку, которую приложение может показать пользователю. Если ошибки подавляются, инъекция не сработает, но её можно использовать в «слепых» техниках.

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

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

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

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

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

Заключение

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

Источники