Введение
Встречая в логах веб-сервера или в поле ввода подобную строку: )) AND EXTRACTVALUE(3665,CONCAT(0x7e,((SELECT (ELT(3665=3665,1)))),0x7e))-- -, многие задаются вопросом: что это и какова её цель? Это классический пример SQL-инъекции, нацеленной на извлечение данных из базы данных MySQL через механизм ошибок. В данной статье мы подробно разберём каждый элемент этого запроса, объясним, как работает атака, и расскажем о методах защиты.
Что такое SQL-инъекция?
SQL-инъекция (SQL injection) — один из самых распространённых способов взлома веб-приложений. Злоумышленник внедряет вредоносный SQL-код в поля ввода или параметры URL, которые затем попадают в SQL-запрос без должной обработки. В результате атакующий может читать, изменять или удалять данные, а в некоторых случаях — выполнять произвольные команды на сервере.
Существует несколько разновидностей SQL-инъекций: union-based, boolean-based, time-based и error-based. Наш пример относится к последней категории.
Error-based SQL-инъекция через EXTRACTVALUE
Error-based SQL-инъекция — это техника, при которой злоумышленник заставляет базу данных выдать сообщение об ошибке, содержащее полезные данные. В MySQL для этого часто используется функция EXTRACTVALUE().
Функция EXTRACTVALUE() принимает два строковых аргумента: фрагмент XML-разметки и выражение XPath (локатор). Она возвращает текст (CDATA) первого текстового узла, который является дочерним для элемента или элементов, соответствующих XPath-выражению. Если XPath-выражение некорректно, MySQL генерирует ошибку, в тексте которой может отображаться переданная строка.
Именно эту особенность эксплуатируют злоумышленники: они передают в качестве XPath-выражения результат подзапроса, содержащий интересующие данные, и провоцируют ошибку, чтобы увидеть эти данные в сообщении об ошибке.
Разбор строки `)) AND EXTRACTVALUE(3665,CONCAT(0x7e,((SELECT (ELT(3665=3665,1)))),0x7e))-- -`
Давайте разберём каждый элемент этого запроса.
- `))` — закрывающие скобки. Они нужны, чтобы завершить предыдущее выражение в исходном SQL-запросе, которое было открыто разработчиком. Например, если исходный запрос выглядел как
SELECT * FROM users WHERE id = ('$input'), то вставка))закроет скобки и позволит добавить новое условие. - `AND` — логический оператор, который добавляет наше условие к исходному запросу.
- `EXTRACTVALUE(3665,CONCAT(0x7e,((SELECT (ELT(3665=3665,1)))),0x7e))` — вызов функции EXTRACTVALUE. Первый аргумент — число 3665 (может быть любым, здесь используется как заполнитель). Второй аргумент — результат функции CONCAT, которая объединяет символ
0x7e(тильда ~) с результатом подзапроса и ещё одной тильдой. Тильды используются как маркеры, чтобы облегчить поиск данных в сообщении об ошибке. - `(SELECT (ELT(3665=3665,1)))` — подзапрос, который возвращает результат функции ELT. ELT(N, str1, str2, ...) возвращает N-ю строку из списка. Здесь N — это результат сравнения 3665=3665, который равен 1 (истина). Таким образом, ELT(1, 1) вернёт «1». В реальной атаке вместо этого подзапроса мог бы быть, например,
(SELECT version())или(SELECT database()), чтобы извлечь версию СУБД или имя базы данных. - `-- -` — комментарий. В MySQL
--(с последующим пробелом) означает начало комментария до конца строки. Это позволяет отсечь оставшуюся часть исходного SQL-запроса, чтобы не возникло синтаксической ошибки.
Таким образом, вся конструкция заставляет базу данных выполнить подзапрос, получить некоторые данные, а затем попытаться использовать их в качестве XPath-выражения. Поскольку эти данные не являются корректным XPath, MySQL выдаёт ошибку, в тексте которой отображается переданная строка (в нашем случае «~1~»). Злоумышленник, читая сообщение об ошибке, может получить интересующую его информацию.
Зачем это нужно злоумышленнику?
Основная цель — извлечение данных из базы. В отличие от union-based инъекций, error-based не требует, чтобы приложение выводило результаты запроса на странице. Достаточно, чтобы сообщения об ошибках отображались пользователю (или попадали в логи, к которым есть доступ). Это делает метод мощным инструментом в руках атакующего.
С помощью error-based инъекций можно получить:
- версию MySQL;
- имя текущей базы данных;
- список таблиц и колонок;
- учётные данные пользователей;
- любые другие данные, доступные в рамках прав текущего пользователя БД.
Пример реальной атаки
Представим, что на сайте есть форма поиска, которая формирует запрос:
SELECT * FROM articles WHERE title LIKE '%$search%';
Если пользователь введёт ')) AND EXTRACTVALUE(3665,CONCAT(0x7e,((SELECT (ELT(3665=3665,1)))),0x7e))-- -, итоговый запрос станет таким:
SELECT * FROM articles WHERE title LIKE '%')) AND EXTRACTVALUE(3665,CONCAT(0x7e,((SELECT (ELT(3665=3665,1)))),0x7e))-- -%';
База данных выполнит подзапрос, получит строку «1», затем попытается вычислить XPath-выражение «~1~», что вызовет ошибку вида:
XPATH syntax error: '~1~'
Если вместо «1» подставить, например, (SELECT user()), в ошибке отобразится имя текущего пользователя MySQL.
Как защититься от таких атак?
Основной метод защиты — использование параметризованных запросов (prepared statements). Они гарантируют, что пользовательский ввод никогда не интерпретируется как SQL-код.
Дополнительные меры:
- Экранирование специальных символов (но это менее надёжно, чем параметризация).
- Ограничение прав пользователя базы данных: приложению не нужны права на чтение системных таблиц или выполнение опасных функций.
- Отключение вывода подробных сообщений об ошибках на продакшене — это усложняет эксплуатацию error-based инъекций.
- Использование WAF (Web Application Firewall) для фильтрации подозрительных запросов.
- Регулярное обновление СУБД и фреймворков.
Важно понимать, что даже если ошибки не выводятся пользователю, они могут попадать в логи, поэтому необходимо следить за их содержимым и своевременно реагировать на подозрительные записи.
Заключение
Строка )) AND EXTRACTVALUE(3665,CONCAT(0x7e,((SELECT (ELT(3665=3665,1)))),0x7e))-- - — это типичный пример error-based SQL-инъекции, использующей функцию EXTRACTVALUE для извлечения данных через сообщения об ошибках. Понимание механики таких атак помогает разработчикам и администраторам лучше защищать свои системы. Помните: безопасность — это процесс, а не разовое действие.
Комментарии
—Войдите, чтобы оставить комментарий