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

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

В этой статье мы разберём каждый элемент запроса, объясним, как работает функция EXTRACTVALUE, зачем нужны CONCAT и 0x7e, что делает ELT, и почему комментарий -- - завершает строку. Также рассмотрим, как защититься от подобных атак.

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

1. Начало: `) AND ...

Символы `)` (закрывающая скобка и обратный апостроф) часто используются для завершения оригинального SQL-запроса, который был вставлен в уязвимый параметр. Обратный апостроф в MySQL экранирует идентификаторы (имена таблиц, столбцов), а закрывающая скобка завершает выражение. После этого добавляется AND — логический оператор, который позволяет присоединить дополнительное условие к исходному запросу. Если исходный запрос был, например, SELECT * FROM users WHERE id = '...', то внедрение `) AND ... может изменить логику.

2. Функция EXTRACTVALUE

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

В нашем случае первый аргумент — 9615 (произвольное число, которое не является корректным XML), а второй — CONCAT(0x7e, ((SELECT (ELT(9615=9615,1)))), 0x7e).

3. CONCAT и 0x7e

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

4. Подзапрос с ELT

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

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

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

Как это работает в реальной атаке

Предположим, на сайте есть скрипт, который выполняет запрос:

SELECT * FROM articles WHERE id = '$_GET[id]'

Злоумышленник передаёт параметр id со значением:

1') AND EXTRACTVALUE(9615,CONCAT(0x7e,((SELECT (ELT(9615=9615,1)))),0x7e))-- -

Тогда итоговый запрос становится:

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

MySQL выполняет запрос, и при вычислении EXTRACTVALUE возникает ошибка, потому что первый аргумент 9615 не является корректным XML. В сообщении об ошибке будет отображено значение, переданное во втором аргументе, то есть ~1~. Если вместо ELT(9615=9615,1) подставить подзапрос, возвращающий конфиденциальные данные, они попадут в текст ошибки и будут видны атакующему.

Зачем это нужно злоумышленнику?

  • Извлечение данных: error-based инъекции позволяют получать содержимое базы данных по частям, даже если прямой вывод результатов запроса не отображается на странице.
  • Обход фильтров: использование функций вроде EXTRACTVALUE и CONCAT помогает обойти простые сигнатуры WAF.
  • Автоматизация: существуют инструменты (sqlmap), которые автоматически подставляют подобные конструкции для дампа базы.

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

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

  • Применять ORM или библиотеки, которые автоматически экранируют данные.
  • Ограничить права пользователя базы данных, чтобы даже при успешной инъекции ущерб был минимален.
  • Использовать WAF для фильтрации подозрительных запросов, но помнить, что WAF не является панацеей.
  • Регулярно обновлять MySQL: в версии 8.0 функции EXTRACTVALUE и UPDATEXML были удалены, что снижает риск error-based атак.

Заключение

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

Источники