Что такое SQL-инъекция?
SQL-инъекция (SQL injection) — один из самых распространённых способов взлома веб-приложений. Злоумышленник внедряет вредоносный SQL-код в запросы, которые приложение отправляет базе данных. Если разработчик не использует параметризованные запросы или не фильтрует входные данные, база может выполнить этот код и вернуть конфиденциальную информацию или даже изменить данные.
Существует несколько типов SQL-инъекций: union-based, boolean-based, time-based и error-based. В этой статье мы детально разберём именно error-based инъекцию через функцию EXTRACTVALUE в СУБД MySQL.
Функция EXTRACTVALUE в MySQL
Функция EXTRACTVALUE(XML_frag, XPath_expr) извлекает значение из фрагмента XML по заданному XPath-выражению. Если XPath-выражение некорректно или не соответствует синтаксису, MySQL возвращает ошибку XPATH syntax error. Эта ошибка содержит часть переданного XPath-выражения, что и позволяет злоумышленнику извлекать данные.
Пример корректного использования:
SELECT EXTRACTVALUE('<a><b>Текст</b></a>', '/a/b');
Результат: Текст.
Однако если передать в XPath что-то вроде ~текст~, MySQL выдаст ошибку, в тексте которой будет фигурировать этот текст. Именно на этом строится атака.
Разбор запроса: ' OR EXTRACTVALUE(4752,CONCAT(0x7e,((SELECT (ELT(4752=4752,1)))),0x7e))-- -
Рассмотрим по частям, что делает этот запрос.
'— закрывает строковый литерал в исходном запросе приложения. Предполагается, что введённые данные подставляются в SQL-запрос внутри кавычек.OR— логический оператор, который делает условие всегда истинным (если правая часть истинна) или позволяет внедрить дополнительное выражение.EXTRACTVALUE(4752, CONCAT(0x7e, ((SELECT (ELT(4752=4752,1)))), 0x7e))— вызов функции, который должен вызвать ошибку с внедрёнными данными.-- -— комментарий, обрезающий остаток оригинального запроса.
Внутри EXTRACTVALUE используется CONCAT(0x7e, ..., 0x7e). 0x7e — это шестнадцатеричное представление символа ~ (тильда). Тильда добавляется, чтобы отделить извлекаемые данные от служебного текста ошибки.
Выражение ELT(4752=4752,1) — это функция ELT(N, str1, str2, ...), возвращающая N-ю строку из списка. Здесь 4752=4752 — всегда истина (1), поэтому ELT(1,1) вернёт 1. Это простейший пример, который можно заменить на подзапрос, извлекающий реальные данные, например: (SELECT user FROM users LIMIT 1).
В результате MySQL попытается вычислить XPath-выражение ~1~, что приведёт к ошибке вида:
ERROR 1105 (HY000): XPATH syntax error: '~1~'
Если вместо единицы подставить подзапрос, в ошибке отобразится результат этого подзапроса — например, имя пользователя или хеш пароля.
Зачем это нужно злоумышленнику?
Error-based инъекция позволяет извлекать данные посимвольно или целыми строками, если приложение выводит сообщения об ошибках базы данных на экран. Даже если вывод ошибок отключён, но они логируются или передаются в другом виде, атакующий может использовать слепые методы. Однако именно EXTRACTVALUE даёт быстрый способ получить данные в тексте ошибки.
Типичный сценарий атаки:
- Найти уязвимый параметр (например,
?id=1'). - Внедрить конструкцию с EXTRACTVALUE и подзапросом для получения имени текущей базы данных:
EXTRACTVALUE(1, CONCAT(0x7e, (SELECT database()), 0x7e)). - Получить в ошибке имя базы, затем таблицы, столбцы и сами данные.
Примеры полезных подзапросов
- Версия MySQL:
SELECT version() - Текущий пользователь:
SELECT current_user() - Имя базы данных:
SELECT database() - Список таблиц:
SELECT table_name FROM information_schema.tables WHERE table_schema=database() LIMIT 1 - Данные из конкретной таблицы:
SELECT password FROM users LIMIT 1
Все эти подзапросы можно вставить вместо ELT(4752=4752,1) в приведённом запросе.
Как защититься от error-based SQL-инъекций?
Основные меры защиты:
- Параметризованные запросы (prepared statements) — самый надёжный способ. Данные передаются отдельно от SQL-кода и не интерпретируются как часть запроса.
- Экранирование специальных символов — если параметризация невозможна, используйте функции экранирования, предоставляемые драйвером БД.
- Отключение вывода ошибок БД — не показывайте пользователям сообщения об ошибках SQL. Логируйте их, но не выводите в браузер.
- Ограничение прав пользователя БД — приложение должно работать с минимально необходимыми привилегиями (обычно только SELECT, INSERT, UPDATE, DELETE для конкретных таблиц).
- WAF (Web Application Firewall) — может блокировать известные шаблоны атак, но не является панацеей.
Заключение
Запрос ' OR EXTRACTVALUE(4752,CONCAT(0x7e,((SELECT (ELT(4752=4752,1)))),0x7e))-- - — это учебный пример error-based SQL-инъекции в MySQL. Он демонстрирует, как через функцию EXTRACTVALUE и намеренно вызванную ошибку XPath можно извлечь произвольные данные из базы. Понимание таких техник необходимо как специалистам по безопасности, так и разработчикам для написания защищённого кода.
Помните: использование подобных запросов против чужих систем без разрешения является незаконным и преследуется по закону.
Комментарии
—Войдите, чтобы оставить комментарий