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

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

В данном случае используется функция EXTRACTVALUE(), которая извлекает значение из XML-фрагмента. Если передать ей некорректный XPath-выражение, MySQL сгенерирует ошибку, содержащую результат подзапроса. Это позволяет атакующему получить данные (например, версию БД, имена таблиц, логины и пароли) через текст ошибки.

Разбор компонентов инъекции

1. Начало: %') OR ...

Символы %') — это попытка закрыть предыдущее значение и скобку в оригинальном SQL-запросе. Знак % часто используется в LIKE-запросах, а ' и ) завершают строковый литерал и функцию. Затем следует OR — логический оператор, который делает условие всегда истинным, если внедрённая часть верна.

2. Функция EXTRACTVALUE(1955, CONCAT(...))

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

3. Конкатенация с тильдой: CONCAT(0x7e, ..., 0x7e)

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

4. Подзапрос: SELECT (ELT(1955=1955,1))

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

5. Комментарий: -- -

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

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

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

MySQL-функции, которые часто используются для этих целей:

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

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

Пример реальной атаки

Предположим, на сайте есть страница product.php?id=1, где параметр id подставляется в SQL-запрос без фильтрации. Злоумышленник может отправить:

1' AND EXTRACTVALUE(1, CONCAT(0x7e, (SELECT version()), 0x7e))-- -

В ответ сервер вернёт ошибку: XPATH syntax error: '~5.7.33-log~', раскрывая версию СУБД. Далее можно извлекать имена таблиц, столбцов и сами данные.

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

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

  1. Параметризованные запросы — самый надёжный способ.
  2. Экранирование спецсимволов — менее надёжно, но допустимо в некоторых случаях.
  3. Валидация входных данных — проверка типов, длины, допустимых символов.
  4. Ограничение прав БД — пользователь приложения не должен иметь прав на чтение системных таблиц.
  5. Регулярные обновления — новые версии MySQL и веб-фреймворков закрывают известные уязвимости.

Также рекомендуется использовать WAF (Web Application Firewall), который может блокировать подозрительные запросы, но не стоит полагаться только на него.

Заключение

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

Источники