Введение
Встречая в логах веб-сервера или в параметрах URL строку вида )))) AND EXTRACTVALUE(6086,CONCAT(0x7e,((SELECT (ELT(6086=6086,1)))),0x7e))-- -, многие задаются вопросом: что это и зачем? Ответ прост: перед вами классический пример error-based SQL-инъекции (SQLi). Такие строки — не случайный набор символов, а тщательно сконструированный запрос, цель которого — заставить базу данных вернуть информацию через сообщение об ошибке.
Подобные конструкции часто попадают в логи при сканировании уязвимостей или при попытке эксплуатации. В данной статье мы детально разберём, из чего состоит этот запрос, как он работает и, главное, как от него защититься.
Что такое SQL-инъекция?
SQL-инъекция (SQL Injection) — один из самых распространённых способов атаки на веб-приложения. Злоумышленник внедряет вредоносный SQL-код в поля ввода, URL-параметры или cookie, чтобы получить несанкционированный доступ к базе данных. Успешная инъекция может привести к утечке конфиденциальных данных, изменению или удалению информации, а в некоторых случаях — к полному захвату сервера.
Существует несколько типов SQL-инъекций:
- Union-based — использование оператора UNION для объединения результатов легитимного запроса с вредоносным.
- Error-based — извлечение данных через сообщения об ошибках, которые возвращает СУБД.
- Boolean-based (слепая) — когда атакующий задаёт вопросы базе и по изменению поведения страницы (истина/ложь) получает информацию.
- Time-based (слепая) — задержка ответа используется как сигнал для передачи данных.
Рассматриваемая строка относится к error-based типу. Она заставляет MySQL выдать сообщение об ошибке, содержащее результат подзапроса.
Разбор строки `)))) AND EXTRACTVALUE(6086,CONCAT(0x7e,((SELECT (ELT(6086=6086,1)))),0x7e))-- -`
Давайте разберём каждый элемент этой конструкции.
1. `))))` — закрытие скобок
В начале идут четыре закрывающие круглые скобки. Они нужны, чтобы «закрыть» ранее открытые скобки в оригинальном запросе и сделать внедряемый код синтаксически корректным. Часто в уязвимом запросе уже есть несколько открытых скобок, и атакующий должен их уравновесить.
2. `AND` — логический оператор
Оператор AND используется для присоединения условия к исходному запросу. Если исходный запрос был, например, SELECT * FROM users WHERE id = '$id', то после подстановки получится нечто вроде ... WHERE id = '')))) AND EXTRACTVALUE(...)-- -. Это позволяет выполнить внедрённую функцию только при определённых условиях.
3. `EXTRACTVALUE(6086, CONCAT(0x7e, ((SELECT (ELT(6086=6086,1)))), 0x7e))` — ядро инъекции
Функция EXTRACTVALUE() в MySQL предназначена для извлечения значения из XML-строки по заданному XPath-выражению. Синтаксис: EXTRACTVALUE(XML_target, XPath_expr). Если XPath-выражение некорректно, MySQL выдаёт ошибку, в тексте которой отображается переданное значение. Это и используется для извлечения данных.
Первый аргумент — 6086 — произвольное число (или строка), не имеющее особого значения. Второй аргумент — CONCAT(0x7e, ((SELECT (ELT(6086=6086,1)))), 0x7e) — формирует строку, которая будет вставлена в сообщение об ошибке.
0x7e— шестнадцатеричное представление символа~(тильда). Используется как разделитель, чтобы облегчить извлечение данных из текста ошибки.(SELECT (ELT(6086=6086,1)))— подзапрос, который возвращает результат функцииELT().
4. `ELT(6086=6086, 1)` — генерация данных
Функция ELT(N, str1, str2, ...) возвращает N-ю строку из списка. В данном случае N — это результат сравнения 6086=6086, которое всегда истинно (1). Значит, ELT(1, 1) вернёт первую строку из списка — 1. Это простейший пример; в реальной атаке вместо 1 мог бы стоять подзапрос, извлекающий, например, имя пользователя или хеш пароля.
Таким образом, вся конструкция заставляет MySQL выполнить EXTRACTVALUE с заведомо некорректным XPath (начинающимся с ~), что приводит к ошибке вида: XPATH syntax error: '~1~'. В этом сообщении и «утекает» результат подзапроса.
5. `-- -` — комментарий
Два дефиса и пробел (или дефис) обозначают начало однострочного комментария в SQL. Всё, что идёт после, игнорируется базой данных. Это нужно, чтобы «отрезать» остаток оригинального запроса, который мог бы помешать выполнению инъекции.
Зачем это нужно атакующему?
Цель — получить данные из базы. Поскольку приложение не выводит результаты SQL-запроса напрямую, атакующий использует ошибки как канал утечки. Подставляя в ELT или вместо 1 различные подзапросы, можно постепенно извлечь имена таблиц, колонок, логины и пароли пользователей.
Например, чтобы узнать имя текущей базы данных, злоумышленник может заменить 1 на database(). Тогда в ошибке появится название БД. Для извлечения данных из таблиц используются GROUP_CONCAT и LIMIT, так как EXTRACTVALUE возвращает не более 32 символов.
Как защититься от error-based SQL-инъекций?
Основной метод защиты — использование параметризованных запросов (prepared statements). Это надёжнее, чем экранирование строк, которое может быть обойдено. Кроме того, рекомендуется:
- Отключить вывод подробных ошибок СУБД в production-окружении. Пользователь должен видеть общее сообщение, а детали — только в логах сервера.
- Применять принцип наименьших привилегий для учётной записи, под которой работает приложение. Не давайте ей прав на чтение системных таблиц без необходимости.
- Регулярно обновлять СУБД и фреймворки, чтобы закрыть известные уязвимости.
- Использовать WAF (Web Application Firewall) для фильтрации подозрительных запросов.
- Проводить аудит кода и пентесты.
Заключение
Строка )))) AND EXTRACTVALUE(6086,CONCAT(0x7e,((SELECT (ELT(6086=6086,1)))),0x7e))-- - — это не бессмысленный набор символов, а рабочий эксплойт для error-based SQL-инъекции. Понимание принципов его работы помогает разработчикам и администраторам лучше защищать свои системы. Если вы обнаружили подобные строки в логах, это сигнал о попытке взлома. Немедленно проверьте безопасность вашего приложения и устраните уязвимости.
Комментарии
—Войдите, чтобы оставить комментарий