Введение
В логах веб-сервера, в поле ввода формы или в параметрах URL иногда можно встретить странные последовательности символов, например: %")))) AND EXTRACTVALUE(5742,CONCAT(0x7e,((SELECT (ELT(5742=5742,1)))),0x7e))-- -. Для неподготовленного пользователя это выглядит как случайный набор знаков, но на самом деле перед нами классический пример error-based SQL-инъекции — атаки на базу данных через уязвимость в веб-приложении. В этой статье мы детально разберём, что означает каждый элемент этой строки, какую цель преследует злоумышленник и как защититься от подобных атак.
Что такое SQL-инъекция
SQL-инъекция (SQL injection) — один из самых распространённых способов взлома веб-сайтов. Суть метода в том, что злоумышленник передаёт в поля ввода или параметры запроса специально сконструированную строку, которая «вклинивается» в SQL-запрос, выполняемый на сервере. Если приложение не проверяет входные данные должным образом, база данных воспринимает часть введённой строки как исполняемый код.
Существует несколько разновидностей SQL-инъекций:
- Union-based — объединение результатов легального запроса с данными из других таблиц.
- Error-based — извлечение информации через сообщения об ошибках, которые генерирует сама СУБД.
- Blind — когда данные извлекаются по косвенным признакам (истина/ложь, задержки времени).
- Stacked queries — выполнение нескольких запросов подряд.
Рассматриваемая строка относится именно к error-based типу. Она заставляет MySQL выдать сообщение об ошибке, в текст которого подставляются данные из базы.
Разбор строки по частям
Давайте разберём payload поэтапно.
1. Начало: %"))))
Символ % — это URL-кодирование, за ним обычно следует шестнадцатеричный код. Далее идут кавычка, закрывающие скобки и апострофы. Их задача — «закрыть» легальный запрос приложения и подготовить почву для внедрения собственного кода. Конкретное количество скобок подбирается методом проб и ошибок, чтобы синтаксис стал корректным.
2. AND EXTRACTVALUE(...)
EXTRACTVALUE() — это функция MySQL, предназначенная для извлечения значения из XML-строки. Она принимает два аргумента: XML-документ и XPath-выражение. Если XPath-выражение синтаксически неверно, MySQL выдаёт ошибку XPATH syntax error, в тексте которой содержится переданное значение. Именно эту особенность эксплуатируют злоумышленники.
3. CONCAT(0x7e, ..., 0x7e)
CONCAT() объединяет строки. Здесь она склеивает символ ~ (код 0x7e в шестнадцатеричном виде), результат подзапроса и ещё один ~. Тильды служат визуальными маркерами, чтобы в сообщении об ошибке легко было найти внедрённые данные.
4. (SELECT (ELT(5742=5742,1)))
ELT() возвращает N-й элемент из списка. Выражение 5742=5742 всегда истинно, поэтому возвращается первый элемент — число 1. В реальной атаке вместо этого простого условия подставляется подзапрос, извлекающий, например, имя пользователя, версию СУБД или хеш пароля. Число 5742 — это просто «заглушка», которая может меняться от запроса к запросу, чтобы избежать сигнатурных фильтров.
5. Завершение: -- -
Двойной дефис с пробелом — это комментарий в SQL. Всё, что идёт после него, игнорируется парсером. Это позволяет «отрезать» остаток оригинального запроса, который мог бы вызвать синтаксическую ошибку.
Как это работает на практике
Предположим, на сервере выполняется запрос вида:
SELECT * FROM users WHERE id = '$input';
Если в $input подставить рассматриваемую строку, запрос превратится в нечто подобное:
SELECT * FROM users WHERE id = '%")))) AND EXTRACTVALUE(5742,CONCAT(0x7e,((SELECT (ELT(5742=5742,1)))),0x7e))-- -';
MySQL попытается выполнить EXTRACTVALUE с некорректным XPath (потому что CONCAT возвращает строку, не являющуюся валидным XPath). В результате возникнет ошибка, и в её тексте появится что-то вроде:
XPATH syntax error: '~1~'
Если вместо 1 подставить подзапрос, например (SELECT version()), в ошибке отобразится версия MySQL. Так злоумышленник может постепенно извлекать любые данные: имена таблиц, логины, пароли.
Зачем нужны тильды и ELT
Символ ~ (0x7e) выбран не случайно: он редко встречается в обычных данных и легко находится в тексте ошибки. ELT с всегда истинным условием — это способ вернуть конкретное значение, не прибегая к сложным конструкциям. В более продвинутых payload'ах вместо ELT могут использоваться UPDATEXML, EXTRACTVALUE с другими аргументами или функции GTID_SUBSET, JSON_KEYS и т.п.
Чем опасна такая инъекция
Error-based SQL-инъекции позволяют злоумышленнику:
- получить доступ к конфиденциальным данным (персональные данные пользователей, хеши паролей, номера карт);
- изменить или удалить информацию в базе;
- получить контроль над сервером в случае наличия дополнительных уязвимостей;
- использовать сайт для дальнейших атак на другие ресурсы.
Даже если база данных не содержит критичной информации, успешная инъекция подрывает доверие к сервису и может привести к блокировкам со стороны поисковых систем и хостинг-провайдеров.
Как защититься
Основной способ борьбы с SQL-инъекциями — параметризованные запросы (prepared statements). Они разделяют код и данные, поэтому введённая строка никогда не интерпретируется как SQL-код. Дополнительные меры:
- Использовать ORM и библиотеки, которые автоматически экранируют данные.
- Проверять и фильтровать все входные данные на стороне сервера.
- Ограничить права пользователя базы данных: приложение должно работать с минимально необходимыми привилегиями.
- Отключить вывод подробных ошибок СУБД в production-окружении.
- Регулярно обновлять СУБД и фреймворки.
- Проводить аудит безопасности и использовать сканеры уязвимостей.
Заключение
Строка %")))) AND EXTRACTVALUE(5742,CONCAT(0x7e,((SELECT (ELT(5742=5742,1)))),0x7e))-- - — это не случайный мусор, а тщательно сконструированный инструмент для атаки на базу данных MySQL. Понимание принципов её работы помогает разработчикам и администраторам своевременно распознавать попытки взлома и принимать меры. Если вы встретили подобную строку в логах своего сайта, стоит немедленно проверить код на наличие уязвимостей и, при необходимости, обратиться к специалистам по информационной безопасности.
Комментарии
—Войдите, чтобы оставить комментарий