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

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

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

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

1. AND

Логический оператор, который добавляется к исходному SQL-запросу. Если исходный запрос уже содержит условие WHERE, то инъекция через AND позволяет внедрить дополнительное выражение. Оно должно быть истинным, чтобы запрос вернул результаты, но в error-based инъекциях важнее сама ошибка.

2. EXTRACTVALUE(9987, ...)

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

Первый аргумент 9987 — произвольное число, оно не играет роли, так как ошибка возникает из-за второго аргумента. В реальных эксплойтах на месте 9987 может быть любое число или даже строка.

3. CONCAT(0x7e, ..., 0x7e)

Функция CONCAT объединяет строки. Здесь 0x7e — это шестнадцатеричное представление символа ~ (тильда). Тильда используется как разделитель, чтобы в сообщении об ошибке было легко найти выводимые данные. Между двумя тильдами вставляется результат подзапроса.

4. (SELECT (ELT(9987=9987,1)))

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

5. -- -

Комментарий. Двойной дефис с пробелом (или -- -) заставляет MySQL игнорировать остаток исходного запроса. Это нужно, чтобы не нарушать синтаксис и обойти возможные проверки.

Как это работает на практике

Предположим, есть уязвимый параметр id в URL: ?id=1. Исходный запрос: SELECT * FROM users WHERE id = 1. Атакующий подставляет:

?id=1 AND EXTRACTVALUE(9987,CONCAT(0x7e,((SELECT (ELT(9987=9987,1)))),0x7e))-- -

Итоговый запрос:

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

MySQL выполнит EXTRACTVALUE с аргументом ~1~. Поскольку ~1~ не является корректным XPath, сервер вернёт ошибку:

ERROR 1105 (HY000): XPATH syntax error: '~1~'

В тексте ошибки мы видим ~1~ — это результат выполнения подзапроса. Если вместо 1 подставить, например, SELECT database(), то в ошибке отобразится имя текущей базы данных.

Зачем это нужно?

Error-based SQL-инъекции — один из способов обхода защиты, когда приложение не выводит данные напрямую, но возвращает сообщения об ошибках СУБД. Это позволяет:

  • определить версию MySQL;
  • получить имя текущей базы данных;
  • извлечь имена таблиц и колонок;
  • читать содержимое таблиц (логины, пароли, персональные данные).

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

Меры защиты

Чтобы предотвратить подобные атаки, разработчики должны:

  • использовать подготовленные выражения (prepared statements) с параметризацией запросов;
  • экранировать все пользовательские данные, попадающие в SQL;
  • отключить вывод подробных ошибок СУБД в продакшене;
  • применять принцип наименьших привилегий для учётной записи базы данных;
  • регулярно обновлять СУБД и использовать WAF.

Важно понимать, что EXTRACTVALUE — не единственная функция для error-based инъекций. Аналогично используются UPDATEXML, GTID_SUBSET, EXP и другие. Однако EXTRACTVALUE остаётся популярной из-за простоты и наглядности.

Заключение

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

Источники