Введение
Строка ` AND EXTRACTVALUE(5312,CONCAT(0x7e,((SELECT (ELT(5312=5312,1)))),0x7e))-- - — это классический пример error-based SQL-инъекции (инъекции, основанной на ошибках) для СУБД MySQL. Подобные конструкции часто встречаются в логах веб-серверов, WAF и систем обнаружения вторжений. Они используются злоумышленниками для извлечения данных из базы через сообщения об ошибках, которые возвращает сервер.
В этой статье мы детально разберём, из чего состоит данный запрос, как он работает, какие функции MySQL задействованы и как защититься от подобных атак.
Что такое error-based SQL-инъекция
SQL-инъекция — это один из самых распространённых способов атаки на веб-приложения. Злоумышленник внедряет в пользовательский ввод специальные конструкции, которые меняют логику SQL-запроса. При error-based инъекции атакующий заставляет базу данных сгенерировать ошибку, в тексте которой содержатся полезные данные: имена таблиц, колонок, логины, пароли и т.д.
MySQL при определённых условиях возвращает подробные сообщения об ошибках, которые могут быть видны в ответе сервера. Это и позволяет извлекать информацию посимвольно или целыми строками.
Разбор строки по частям
Рассмотрим каждый элемент запроса:
- ` — обратный апостроф (бэктик). В MySQL используется для экранирования имён идентификаторов (таблиц, колонок). В начале строки он, скорее всего, закрывает ранее открытый бэктик в уязвимом запросе.
- AND — логический оператор, который добавляется к условию WHERE. Он позволяет внедрить дополнительное выражение, не нарушая синтаксис исходного запроса.
- EXTRACTVALUE(5312, CONCAT(...)) — функция MySQL, предназначенная для извлечения значения из XML-строки. Она принимает два аргумента: XML-документ и XPath-выражение. Если XPath-выражение некорректно, функция возвращает ошибку. Именно эту ошибку использует атакующий.
- 5312 — произвольное число, которое передаётся как XML-документ. Оно не является валидным XML, что уже может вызвать ошибку, но главное — второй аргумент.
- CONCAT(0x7e, ..., 0x7e) — функция конкатенации строк. Она объединяет символы в одну строку. 0x7e — это шестнадцатеричный код символа
~(тильда). Тильда используется как маркер, чтобы в сообщении об ошибке было легко найти границы извлечённых данных. - (SELECT (ELT(5312=5312,1))) — подзапрос, который возвращает результат функции ELT. ELT(N, str1, str2, ...) возвращает N-ю строку из списка. Здесь условие 5312=5312 всегда истинно, поэтому ELT возвращает 1 (первый элемент). Это простейший пример; в реальной атаке вместо 1 может быть подзапрос, извлекающий данные, например (SELECT password FROM users LIMIT 1).
- -- - — комментарий в MySQL. Всё, что идёт после него, игнорируется. Это нужно, чтобы обрезать остаток оригинального запроса, который мог бы вызвать синтаксическую ошибку.
Как это работает на практике
Предположим, исходный запрос выглядит так:
SELECT * FROM articles WHERE id = '1'
Злоумышленник подставляет вместо 1 строку 1` AND EXTRACTVALUE(5312,CONCAT(0x7e,((SELECT (ELT(5312=5312,1)))),0x7e))-- -. В результате запрос принимает вид:
SELECT * FROM articles WHERE id = '1` AND EXTRACTVALUE(5312,CONCAT(0x7e,((SELECT (ELT(5312=5312,1)))),0x7e))-- -'
MySQL выполняет функцию EXTRACTVALUE. Поскольку второй аргумент (XPath) содержит символ ~, который недопустим в XPath, возникает ошибка. В тексте ошибки MySQL выводит переданную строку, например:
XPATH syntax error: '~1~'
Таким образом, атакующий видит результат выполнения подзапроса. В данном примере это просто «1», но если вместо ELT(5312=5312,1) подставить, скажем, (SELECT version()), в ошибке отобразится версия MySQL. Это и есть извлечение данных.
Зачем нужны 0x7e и ELT
Символ ~ (0x7e) выбран не случайно: он редко встречается в обычных данных и легко заметен в сообщении об ошибке. Он служит разделителем, чтобы точно определить начало и конец извлечённой строки.
Функция ELT позволяет возвращать конкретную строку из списка в зависимости от условия. В простейшем случае условие всегда истинно, и возвращается первый элемент. В более сложных атаках ELT может использоваться для побитового извлечения данных: например, сравнивая символы и возвращая разные значения в зависимости от результата.
Какие данные можно извлечь
С помощью error-based инъекций через EXTRACTVALUE злоумышленник может получить:
- версию СУБД;
- имя текущей базы данных;
- имена таблиц и колонок;
- содержимое таблиц (логины, пароли, персональные данные).
Всё это становится возможным, если приложение не фильтрует пользовательский ввод и выводит ошибки базы данных на страницу.
Как защититься
Основные меры защиты от SQL-инъекций, включая error-based:
- Использовать подготовленные выражения (prepared statements). Это самый надёжный способ: параметры запроса передаются отдельно от SQL-кода и не могут изменить его структуру.
- Экранировать специальные символы. Если prepared statements недоступны, необходимо применять функции экранирования (например, mysqli_real_escape_string в PHP).
- Отключить вывод ошибок БД. Сообщения об ошибках не должны попадать в ответ сервера. Логируйте их, но не показывайте пользователю.
- Использовать WAF. Веб-application firewall может блокировать подозрительные конструкции вроде EXTRACTVALUE.
- Регулярно обновлять СУБД и приложения. Устаревшие версии могут содержать дополнительные уязвимости.
Заключение
Строка ` AND EXTRACTVALUE(5312,CONCAT(0x7e,((SELECT (ELT(5312=5312,1)))),0x7e))-- - — это не случайный набор символов, а тщательно сконструированный эксплойт для error-based SQL-инъекции в MySQL. Понимание того, как он работает, помогает разработчикам и специалистам по безопасности лучше защищать свои приложения. Если вы встретили такую строку в логах — это признак попытки взлома, и стоит немедленно проверить безопасность вашего кода.
Комментарии
—Войдите, чтобы оставить комментарий