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

Строка %')) AND EXTRACTVALUE(7620,CONCAT(0x7e,((SELECT (ELT(7620=7620,1)))),0x7e))-- - представляет собой классический пример SQL-инъекции (SQL injection), нацеленной на базу данных MySQL. Такие строки часто встречаются в логах веб-серверов или в полях ввода, когда злоумышленник пытается проверить уязвимость приложения или извлечь данные. В данной статье мы разберём, из чего состоит этот запрос, как он работает и какие меры защиты помогут предотвратить подобные атаки.

Расшифровка компонентов инъекции

Начнём с начала строки: %')). Символ % часто используется в SQL-шаблонах LIKE, но в данном контексте он, скорее всего, является частью полезной нагрузки для обхода фильтров или закрытия предыдущего выражения. Далее идут две закрывающие скобки и апостроф: ')). Это попытка «закрыть» оригинальный запрос приложения, чтобы внедрить свой код. Например, если исходный запрос был вида SELECT * FROM users WHERE name = '...', то injected-строка закрывает кавычку и скобки, делая дальнейший код частью SQL-выражения.

Затем следует AND EXTRACTVALUE(7620,CONCAT(0x7e,((SELECT (ELT(7620=7620,1)))),0x7e)). Это основная часть атаки. EXTRACTVALUE — функция MySQL (до версии 8.0), которая извлекает значение из XML-строки. Она принимает два аргумента: XML-документ и XPath-выражение. Если XPath-выражение некорректно, функция генерирует ошибку, которая может быть использована для извлечения данных (техника error-based SQL injection).

В нашем случае первый аргумент — число 7620 (произвольный идентификатор), второй аргумент — CONCAT(0x7e,((SELECT (ELT(7620=7620,1)))),0x7e). CONCAT объединяет строки: 0x7e — это шестнадцатеричное представление символа тильды (~). Внутри CONCAT выполняется подзапрос SELECT (ELT(7620=7620,1)). ELT — функция, возвращающая N-й элемент из списка. Выражение 7620=7620 всегда истинно (1), поэтому ELT(1,1) вернёт 1. Таким образом, CONCAT формирует строку ~1~. Затем EXTRACTVALUE пытается интерпретировать эту строку как XML и применить XPath, что приводит к ошибке, так как ~1~ не является корректным XML. Сообщение об ошибке будет содержать значение ~1~, что позволяет атакующему убедиться в работоспособности инъекции.

Завершает строку -- - — это комментарий в SQL, который «отрезает» оставшуюся часть оригинального запроса, чтобы синтаксис был корректным. Дефис и пробел после двух дефисов обязательны в MySQL для комментария.

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

Основная цель такой инъекции — проверка наличия уязвимости и возможности выполнения произвольного SQL-кода. Если приложение уязвимо, то при подстановке этой строки в запрос база данных вернёт ошибку с внедрённым значением (например, ~1~). Это сигнал для атакующего, что можно дальше эксплуатировать уязвимость: извлекать данные из других таблиц, получать имена пользователей и пароли и т.д. Техника error-based инъекции позволяет получать информацию по одному символу за раз, но автоматизированные инструменты (например, sqlmap) делают это быстро.

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

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

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

  • Экранировать специальные символы, если параметризация невозможна (например, с помощью функций экранирования в драйвере БД).
  • Использовать ORM (например, Hibernate, Entity Framework), которые по умолчанию применяют параметризацию.
  • Ограничить права пользователя базы данных, чтобы даже при успешной инъекции нельзя было выполнить опасные операции.
  • Регулярно обновлять СУБД и фреймворки, так как в старых версиях MySQL функция EXTRACTVALUE доступна и может быть использована для атак; в MySQL 8.0.17 и новее она удалена.

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

Заключение

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

Источники