Что это за строка?
Строка %' OR EXTRACTVALUE(7294,CONCAT(0x7e,((SELECT (ELT(7294=7294,1)))),0x7e))-- - — это классический пример error-based SQL-инъекции (инъекции на основе ошибок) для СУБД MySQL. Такие конструкции используют для извлечения данных из базы данных через вывод сообщения об ошибке. Злоумышленник внедряет в уязвимый параметр запроса код, который заставляет сервер вернуть ошибку, содержащую результат подзапроса. В данном случае функция EXTRACTVALUE генерирует ошибку формата XML, в текст которой попадает вычисленное значение.
Как работает этот эксплойт?
Разберём по частям:
%'— закрывает предыдущее строковое значение в SQL-запросе и добавляет символ%для обхода возможной фильтрации. Одинарная кавычка разрывает строку, позволяя внедрить произвольный SQL-код.OR— логический оператор, который делает условие истинным, если внедрённая часть верна. Это гарантирует, что исходный запрос не сломается, но выполнится внедрённый код.EXTRACTVALUE(7294,CONCAT(0x7e,((SELECT (ELT(7294=7294,1)))),0x7e))— вызов функции MySQLEXTRACTVALUE, которая извлекает значение из XML-документа. Первый аргумент — произвольное число (7294), второй — строка, которая должна быть корректным XPath-выражением. Если второй аргумент не является валидным XPath, MySQL выбрасывает ошибкуXPATH syntax error, в тексте которой отображается переданная строка. Это и есть канал утечки данных.CONCAT(0x7e,((SELECT (ELT(7294=7294,1)))),0x7e)— конкатенация символа~(0x7e в шестнадцатеричном виде), результата подзапроса и ещё одного~. Символы~служат маркерами для удобного извлечения данных из сообщения об ошибке.SELECT (ELT(7294=7294,1))— подзапрос, который возвращает1, если условие7294=7294истинно (что всегда так). ФункцияELT(N, str1, str2, ...)возвращает N-ю строку из списка. Здесь N=1, поэтому возвращается1. В реальных атаках вместо этого подзапроса подставляют вызовы, извлекающие данные: имена таблиц, колонок, пароли и т.д. Например,SELECT table_name FROM information_schema.tables LIMIT 1.-- -— комментарий, который отсекает оставшуюся часть оригинального SQL-запроса, чтобы синтаксис был корректным.
В результате выполнения такого запроса MySQL вернёт ошибку вида: XPATH syntax error: '~1~'. Злоумышленник видит значение 1 и понимает, что инъекция работает. Далее он может извлекать любые данные, подставляя вместо ELT(7294=7294,1) другие подзапросы.
Зачем это нужно злоумышленнику?
Error-based SQL-инъекция — один из самых быстрых способов извлечения информации из базы, когда приложение выводит сообщения об ошибках СУБД на страницу. В отличие от blind-инъекций, где данные приходится получать побитово через логические условия, здесь результат приходит напрямую в тексте ошибки. Это позволяет за считанные запросы вытащить:
- версию MySQL;
- имя текущей базы данных;
- список таблиц и колонок через
information_schema; - учётные данные пользователей, хеши паролей, персональные данные.
Функция EXTRACTVALUE — не единственная в арсенале. Аналогично работают UPDATEXML, GTID_SUBSET, EXP (в старых версиях) и другие функции, вызывающие ошибки с подконтрольным текстом. Выбор EXTRACTVALUE часто обусловлен тем, что она доступна во многих версиях MySQL и MariaDB и стабильно возвращает данные в сообщении об ошибке.
Пример реального использования
Предположим, на сайте есть скрипт product.php?id=1, который выполняет запрос:
SELECT * FROM products WHERE id = '$id';
Если параметр id не фильтруется, злоумышленник может передать:
1' OR EXTRACTVALUE(1,CONCAT(0x7e,(SELECT database()),0x7e))-- -
В ответе сервера появится ошибка: XPATH syntax error: '~mydb~', где mydb — имя текущей базы данных. Аналогично можно получить версию: SELECT version(), или хеши паролей: SELECT password FROM users LIMIT 1.
Как защититься от таких атак?
Основной метод — использование параметризованных запросов (prepared statements). В PHP с PDO или MySQLi, в Java с JDBC, в Python с psycopg2 и т.д. Параметризация гарантирует, что пользовательский ввод никогда не интерпретируется как SQL-код.
Дополнительные меры:
- Валидация входных данных — если параметр ожидает число, приводите его к целому типу, отбрасывайте всё, что не является числом.
- Экранирование спецсимволов — используйте функции вроде
mysqli_real_escape_string, но помните, что это не панацея. - Отключение вывода ошибок СУБД — на продакшене ошибки базы данных не должны попадать в ответ клиенту. Логируйте их, но не показывайте.
- Принцип наименьших привилегий — пользователь БД для веб-приложения должен иметь доступ только к необходимым таблицам и операциям.
- WAF — веб-application firewall может блокировать известные сигнатуры атак, но не заменяет исправление кода.
Помните, что SQL-инъекции по-прежнему входят в топ OWASP и остаются одной из самых опасных уязвимостей. Регулярно проводите аудит кода и используйте сканеры уязвимостей.
Частые вопросы
Почему используется именно 7294?
Число 7294 — произвольное. Оно не несёт смысловой нагрузки, кроме как быть первым аргументом EXTRACTVALUE. В других примерах можно встретить 7974, 3720 и т.п. Главное — чтобы функция вызвалась и сгенерировала ошибку.
Что означает 0x7e?
0x7e — шестнадцатеричное представление символа ~ (тильда). Его используют как разделитель, чтобы в сообщении об ошибке было легко найти начало и конец извлечённых данных. Тильда редко встречается в реальных данных, поэтому служит надёжным маркером.
Можно ли использовать эту инъекцию на других СУБД?
Нет, EXTRACTVALUE — специфичная для MySQL и MariaDB функция. В PostgreSQL, Oracle, MS SQL используются другие техники error-based инъекций.
Заключение
Строка %' OR EXTRACTVALUE(7294,CONCAT(0x7e,((SELECT (ELT(7294=7294,1)))),0x7e))-- - — это учебный пример эксплуатации error-based SQL-инъекции в MySQL. Она демонстрирует, как через функцию EXTRACTVALUE можно заставить базу вернуть произвольные данные в сообщении об ошибке. Понимание таких векторов атак необходимо разработчикам и специалистам по безопасности, чтобы своевременно закрывать уязвимости. Единственная надёжная защита — параметризованные запросы и минимизация прав пользователя БД.
Комментарии
—Войдите, чтобы оставить комментарий