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

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

Подобные строки часто встречаются в логах веб-серверов, в отчётах систем обнаружения вторжений (IDS) и в базах уязвимостей. Они не являются частью легитимного кода — это попытка взлома, замаскированная под параметр запроса.

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

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

1. Начало: %"))

Символ % — это URL-кодированный пробел (в некоторых контекстах). Далее идут закрывающая кавычка " и две закрывающие круглые скобки )). Это попытка «закрыть» предполагаемую конструкцию в уязвимом SQL-запросе. Например, если исходный запрос выглядел как:

SELECT * FROM users WHERE name = "$input"

то после подстановки ввода %")) AND EXTRACTVALUE(...)-- - запрос станет:

SELECT * FROM users WHERE name = "%")) AND EXTRACTVALUE(...)-- -"

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

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

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

В нашем случае EXTRACTVALUE(1050, CONCAT(0x7e, (SELECT ...), 0x7e)) — первый аргумент 1050 не является XML-фрагментом, что уже провоцирует ошибку. Второй аргумент — это XPath-выражение, которое строится динамически с помощью CONCAT. Символ 0x7e — это тильда ~, используется как разделитель, чтобы облегчить поиск данных в сообщении об ошибке.

3. Подзапрос (SELECT (ELT(1050=1050,1)))

Здесь ELT(N, str1, str2, ...) возвращает N-ю строку из списка. В данном случае ELT(1050=1050, 1) — условие 1050=1050 всегда истинно, что в MySQL даёт 1, поэтому ELT(1, 1) вернёт 1. Это простейшая проверка, которая не несёт полезной нагрузки, но демонстрирует работу инъекции. В реальной атаке вместо 1 мог бы быть, например, SELECT password FROM users LIMIT 1.

Фактически подзапрос (SELECT (ELT(1050=1050,1))) возвращает 1, и тогда CONCAT(0x7e, 1, 0x7e) даёт строку ~1~. Эта строка передаётся как XPath в EXTRACTVALUE. Поскольку ~1~ не является валидным XPath, MySQL выдаст ошибку вида:

XPATH syntax error: '~1~'

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

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

Как уже упоминалось, -- в MySQL начинает комментарий до конца строки. Пробел после -- обязателен, поэтому -- - — это комментарий, за которым следует дефис (он тоже в комментарии). Это позволяет «отрезать» остаток оригинального запроса, чтобы синтаксис стал корректным.

Зачем это используется?

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

В современных системах такие атаки часто блокируются на уровне WAF (Web Application Firewall), но в устаревших или плохо настроенных приложениях они могут сработать.

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

  • Используйте подготовленные выражения (prepared statements) с параметризацией. Это самый надёжный способ предотвратить SQL-инъекции.
  • Экранируйте пользовательский ввод с помощью функций, специфичных для вашей СУБД (например, mysqli_real_escape_string).
  • Отключите вывод ошибок БД в продакшене. Ошибки должны логироваться, но не показываться пользователю.
  • Применяйте WAF для фильтрации подозрительных запросов.
  • Регулярно обновляйте СУБД и библиотеки, чтобы закрыть известные уязвимости.

Пример безопасного кода на PHP

Вместо конкатенации строк используйте параметризованные запросы:

$stmt = $pdo->prepare('SELECT * FROM users WHERE name = :name');
$stmt->execute(['name' => $userInput]);

Такой подход гарантирует, что ввод пользователя не будет интерпретирован как SQL-код.

Заключение

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

Источники