Введение
Встречая в логах или в поле ввода подобную строку: ' AND EXTRACTVALUE(7909,CONCAT(0x7e,((SELECT (ELT(7909=7909,1)))),0x7e))-- -, многие задаются вопросом: что это и какова её цель? Это классический пример SQL-инъекции, нацеленной на извлечение данных из базы данных через вывод сообщения об ошибке. В данной статье мы подробно разберём, как работает эта конструкция, какие функции MySQL задействованы и как защититься от подобных атак.
Что такое error-based SQL-инъекция?
SQL-инъекция — это один из самых распространённых способов взлома веб-приложений, при котором злоумышленник внедряет вредоносный SQL-код в запрос к базе данных. Error-based SQL-инъекция — это разновидность, при которой атакующий заставляет сервер базы данных выдать сообщение об ошибке, содержащее конфиденциальную информацию (например, версию СУБД, имена таблиц, данные из полей).
Строка ' AND EXTRACTVALUE(7909,CONCAT(0x7e,((SELECT (ELT(7909=7909,1)))),0x7e))-- - представляет собой классический пример error-based SQL-инъекции для СУБД MySQL. Она предназначена для извлечения данных из базы через вывод сообщения об ошибке.
Разбор структуры инъекции
Давайте разберём эту строку по частям, чтобы понять, как она работает.
1. Начало: кавычка и AND
Строка начинается с одинарной кавычки ', которая закрывает предыдущее строковое значение в оригинальном SQL-запросе. Затем следует AND — логический оператор, который добавляет новое условие к запросу. Это позволяет внедрить произвольный SQL-код, если исходный запрос не фильтрует входные данные.
2. Функция EXTRACTVALUE
EXTRACTVALUE(7909, CONCAT(...)) — это встроенная функция MySQL, предназначенная для извлечения значения из XML-документа. Она принимает два аргумента: XML-документ и XPath-выражение. Если XPath-выражение некорректно, MySQL генерирует ошибку, которая включает переданное значение. Именно это и используется для вывода данных.
3. CONCAT и шестнадцатеричные символы
CONCAT(0x7e, ((SELECT (ELT(7909=7909,1)))), 0x7e) — функция CONCAT объединяет строки. Здесь 0x7e — это шестнадцатеричное представление символа тильды (~). Тильда используется как разделитель, чтобы облегчить чтение выводимых данных в сообщении об ошибке. Внутри CONCAT находится подзапрос (SELECT (ELT(7909=7909,1))).
4. ELT и условие 7909=7909
ELT(7909=7909, 1) — функция ELT возвращает N-й элемент из списка. Первый аргумент — это условие 7909=7909, которое всегда истинно (возвращает 1). Второй аргумент — 1. Таким образом, ELT возвращает 1. Это условие всегда истинно, что гарантирует предсказуемый результат. В реальной атаке вместо 7909=7909 могло бы быть условие, проверяющее, например, первый символ имени базы данных, и в зависимости от результата выводить разные данные.
5. Комментарий -- -
В конце строки -- - — это комментарий в SQL. Он закомментирует оставшуюся часть оригинального запроса, чтобы синтаксис был корректным. Пробел после -- обязателен в некоторых реализациях MySQL.
Как это работает в реальной атаке
Предположим, есть уязвимый запрос:
SELECT * FROM users WHERE id = '$input';Если злоумышленник передаст в $input нашу строку, запрос станет таким:
SELECT * FROM users WHERE id = '' AND EXTRACTVALUE(7909,CONCAT(0x7e,((SELECT (ELT(7909=7909,1)))),0x7e))-- -';MySQL выполнит функцию EXTRACTVALUE, которая попытается интерпретировать строку, начинающуюся с тильды, как XPath. Это вызовет ошибку вида:
XPATH syntax error: '~1~'
В сообщении об ошибке будет выведено значение, возвращённое подзапросом. В нашем случае это 1. В реальной атаке вместо 1 могло быть имя базы данных, таблицы или конкретные данные.
Зачем используется ELT?
Функция ELT позволяет атакующему извлекать данные посимвольно или по частям. Например, можно сконструировать условие, которое будет истинным только если первый символ имени базы данных равен определённой букве. Если условие истинно, ELT вернёт 1, и в ошибке появится 1; если ложно — 0 или другое значение. Так можно перебрать все символы и восстановить данные.
Как защититься от error-based SQL-инъекций
Основной метод защиты — использование параметризованных запросов (prepared statements). Они разделяют код SQL и данные, поэтому внедрение произвольного SQL-кода становится невозможным.
- Параметризация запросов: всегда используйте подготовленные выражения с плейсхолдерами.
- Валидация входных данных: проверяйте типы данных, ограничивайте длину, используйте белые списки.
- Экранирование специальных символов: если параметризация невозможна, применяйте функции экранирования, предоставляемые драйвером БД.
- Отключение вывода ошибок: не показывайте пользователям подробные сообщения об ошибках БД. Логируйте их, но выдавайте обобщённые сообщения.
- Использование ORM: современные ORM-библиотеки обычно используют параметризацию по умолчанию.
- Регулярные обновления: следите за обновлениями СУБД и веб-приложений, чтобы закрывать известные уязвимости.
Заключение
Строка ' AND EXTRACTVALUE(7909,CONCAT(0x7e,((SELECT (ELT(7909=7909,1)))),0x7e))-- - — это яркий пример error-based SQL-инъекции, использующей особенности функций MySQL для извлечения данных через сообщения об ошибках. Понимание механизмов таких атак помогает разработчикам и администраторам лучше защищать свои системы. Помните, что безопасность — это процесс, а не одноразовое действие.
Комментарии
—Войдите, чтобы оставить комментарий