Введение
В мире веб-безопасности одной из самых распространённых угроз является SQL-инъекция. Это способ внедрения вредоносного кода в SQL-запросы через пользовательский ввод. Строка, которую мы рассматриваем: %' OR EXTRACTVALUE(3087,CONCAT(0x7e,((SELECT (ELT(3087=3087,1)))),0x7e))-- - — представляет собой классический пример error-based SQL-инъекции для СУБД MySQL. В этой статье мы детально разберём, что означает каждый элемент этой конструкции, как она работает и какие меры защиты существуют.
Что такое error-based SQL-инъекция?
Error-based SQL-инъекция — это техника атаки, при которой злоумышленник заставляет базу данных выдать сообщение об ошибке, содержащее полезные данные. В MySQL для этого часто используются функции, которые генерируют ошибки при определённых условиях. Одной из таких функций является EXTRACTVALUE().
Функция EXTRACTVALUE() предназначена для извлечения значения из XML-документа с помощью XPath-выражения. Однако при передаче некорректного XPath-выражения она вызывает ошибку, в тексте которой может содержаться переданная строка. Это и позволяет атакующему извлекать данные из базы.
Разбор строки инъекции
Рассмотрим строку по частям:
%'— это начало полезной нагрузки. Символ%часто используется в SQL LIKE-запросах как wildcard, а одинарная кавычка'закрывает строковый литерал в оригинальном запросе, позволяя внедрить произвольный SQL-код.OR EXTRACTVALUE(3087,CONCAT(0x7e,((SELECT (ELT(3087=3087,1)))),0x7e))— это основная часть инъекции. Она добавляет условие OR, которое всегда истинно (если функция не вызовет ошибку), и вызывает функцию EXTRACTVALUE с параметрами, которые гарантированно приводят к ошибке.-- -— это комментарий, который отсекает остаток оригинального запроса, чтобы избежать синтаксических ошибок.
Функция EXTRACTVALUE
Синтаксис: EXTRACTVALUE(xml_frag, xpath_expr). Она возвращает текст первого текстового узла, соответствующего XPath-выражению. Если XPath-выражение содержит недопустимые символы, MySQL генерирует ошибку вида: XPATH syntax error: '...'. Внутри ошибки отображается переданный фрагмент, что и используется для извлечения данных.
Функция CONCAT и 0x7e
CONCAT() объединяет строки. 0x7e — это шестнадцатеричное представление символа тильды ~. Тильда используется как разделитель, чтобы облегчить чтение извлечённых данных в сообщении об ошибке. Например, CONCAT(0x7e, (SELECT ...), 0x7e) создаст строку ~данные~.
Подзапрос с ELT и условием 3087=3087
ELT(N, str1, str2, ...) возвращает N-ю строку из списка. В данном случае ELT(3087=3087, 1) — условие 3087=3087 всегда истинно, что в числовом контексте даёт 1. Значит, ELT(1, 1) вернёт 1. Это просто заглушка, которая может быть заменена на любой другой подзапрос для извлечения реальных данных, например, (SELECT password FROM users LIMIT 1).
Таким образом, в ошибке будет выведено ~1~. В реальной атаке вместо 1 подставляется имя базы данных, версия, имена таблиц и другие данные.
Пример работы
Предположим, уязвимый запрос выглядит так:
SELECT * FROM articles WHERE title LIKE '%' + user_input + '%';
Если пользователь введёт нашу строку, запрос станет:
SELECT * FROM articles WHERE title LIKE '%%' OR EXTRACTVALUE(3087,CONCAT(0x7e,((SELECT (ELT(3087=3087,1)))),0x7e))-- -%';
MySQL выполнит функцию EXTRACTVALUE, которая вызовет ошибку: XPATH syntax error: '~1~'. Эта ошибка будет возвращена приложению, и атакующий увидит значение 1. Заменив подзапрос, он сможет извлечь любые данные.
Цели атакующего
Error-based инъекции позволяют злоумышленнику:
- Получить версию СУБД, имя текущей базы данных, пользователя.
- Извлечь содержимое таблиц: логины, пароли, персональные данные.
- В некоторых случаях выполнить произвольные команды на сервере.
Как защититься от SQL-инъекций
Основные меры защиты:
- Использование подготовленных выражений (prepared statements) с параметризацией запросов. Это самый надёжный способ, так как данные не смешиваются с кодом.
- Экранирование специальных символов с помощью функций вроде
mysqli_real_escape_string()в PHP, но это менее надёжно, чем подготовленные выражения. - Валидация и фильтрация входных данных — проверка типов, длины, допустимых символов.
- Ограничение прав пользователя базы данных — не использовать root для веб-приложений.
- Регулярное обновление СУБД и фреймворков для устранения известных уязвимостей.
- Использование WAF (Web Application Firewall) для блокировки подозрительных запросов.
Заключение
Строка %' OR EXTRACTVALUE(3087,CONCAT(0x7e,((SELECT (ELT(3087=3087,1)))),0x7e))-- - — это пример эксплойта для error-based SQL-инъекции в MySQL. Понимание принципов работы таких атак помогает разработчикам и администраторам лучше защищать свои системы. Всегда используйте параметризованные запросы и следите за безопасностью ваших приложений.
Комментарии
—Войдите, чтобы оставить комментарий