Что такое SQL-инъекция?
SQL-инъекция (SQL injection) — один из самых распространённых способов взлома веб-приложений. Злоумышленник внедряет вредоносный SQL-код в запросы, которые приложение отправляет базе данных. Если приложение не проверяет вводимые пользователем данные, база может выполнить команды атакующего и раскрыть конфиденциальную информацию.
Существует несколько типов SQL-инъекций: union-based, boolean-based, time-based и error-based. В этой статье мы детально разберём error-based SQL-инъекцию на примере строки:
%")) AND EXTRACTVALUE(5401,CONCAT(0x7e,((SELECT (ELT(5401=5401,1)))),0x7e))-- -
Эта строка — классический пример эксплуатации уязвимости в СУБД MySQL с использованием функций EXTRACTVALUE, CONCAT и ELT.
Как работает error-based инъекция?
Error-based SQL-инъекция основана на том, что база данных возвращает сообщения об ошибках, содержащие полезную для атакующего информацию. Если приложение выводит эти ошибки на страницу (или в логи, доступные злоумышленнику), можно извлечь данные из базы, даже не имея прямого доступа к ней.
В MySQL есть функции, которые при определённых условиях вызывают ошибку с текстом, зависящим от переданных аргументов. Это позволяет «вытащить» результат подзапроса в сообщении об ошибке.
Функция EXTRACTVALUE
EXTRACTVALUE(XML_frag, XPath_expr) — функция MySQL для извлечения значения из XML-фрагмента по заданному XPath-выражению. Она возвращает текст, соответствующий XPath. Однако если XPath-выражение некорректно, MySQL генерирует ошибку.
В контексте инъекции EXTRACTVALUE используется так: в XPath подставляется строка, содержащая недопустимые символы (например, тильду ~), что вызывает ошибку. В текст ошибки попадает переданное значение — это и есть данные, которые хочет получить атакующий.
Функция CONCAT
CONCAT(str1, str2, ...) объединяет строки. В нашем примере она склеивает тильду, результат подзапроса и ещё одну тильду. Тильда здесь — маркер, по которому удобно найти извлечённые данные в сообщении об ошибке.
Функция ELT
ELT(N, str1, str2, ...) возвращает N-ю строку из списка. В примере используется ELT(5401=5401, 1). Поскольку условие 5401=5401 всегда истинно (возвращает 1), ELT вернёт первый элемент — число 1. Это простейший случай; на практике вместо условия может быть подзапрос, извлекающий данные, например: ELT(1=1, (SELECT password FROM users LIMIT 1)).
Пошаговый разбор строки инъекции
Рассмотрим строку по частям:
%"))— часть, которая «закрывает» предыдущий SQL-запрос. Символ%часто используется в LIKE-запросах, а"))завершает кавычки и скобки, делая исходный запрос синтаксически корректным для внедрения.AND EXTRACTVALUE(5401,CONCAT(0x7e,((SELECT (ELT(5401=5401,1)))),0x7e))— внедряемое условие. Оно всегда истинно (5401=5401), но при выполнении вызывает ошибку, содержащую результат подзапроса.-- -— комментарий, который «отрезает» остаток исходного запроса, чтобы не возникло синтаксических ошибок.
В итоге база данных выполняет подзапрос SELECT (ELT(5401=5401,1)), получает результат (в данном случае 1), подставляет его в CONCAT с тильдами, а затем EXTRACTVALUE пытается обработать строку как XPath и выдаёт ошибку вида: XPATH syntax error: '~1~'. В реальной атаке вместо ELT(5401=5401,1) может стоять подзапрос, возвращающий имя пользователя, хеш пароля и т.д.
Зачем злоумышленнику это нужно?
Цель — получить доступ к данным, которые не должны быть видны. Через error-based инъекцию можно:
- узнать версию СУБД;
- получить имена таблиц и столбцов;
- извлечь логины, пароли, номера карт и другую чувствительную информацию.
Опасность в том, что для атаки достаточно лишь возможности отправлять запросы к уязвимому параметру. Не требуется никаких специальных привилегий.
Примеры реальных атак
Подобные строки часто встречаются в логах веб-серверов. Например, при сканировании сайтов утилитами вроде sqlmap можно увидеть множество вариаций с EXTRACTVALUE, UPDATEXML и другими функциями. Если приложение выводит ошибки MySQL на экран, атакующий сразу получает результат.
Вот ещё один пример из практики:
' AND EXTRACTVALUE(3720,CONCAT(0x7e,(SELECT version()),0x7e))-- -
Эта строка вернёт версию MySQL в сообщении об ошибке.
Как защититься от SQL-инъекций?
Главное правило — никогда не доверять данным от пользователя. Вот ключевые меры:
- Используйте подготовленные выражения (prepared statements). Это самый надёжный способ. Параметры передаются отдельно от SQL-кода, и внедрение становится невозможным.
- Применяйте ORM. Современные ORM (например, Hibernate, Entity Framework) автоматически экранируют параметры.
- Валидируйте и фильтруйте входные данные. Если поле должно содержать число — принимайте только числа.
- Отключайте вывод ошибок БД на продакшене. Ошибки должны логироваться, но не показываться пользователю.
- Используйте Web Application Firewall (WAF). Он может блокировать подозрительные запросы, но не является панацеей.
- Регулярно обновляйте СУБД и фреймворки. Уязвимости в старых версиях упрощают атаки.
Если вы разработчик, всегда проверяйте код на наличие конкатенации SQL-строк с пользовательским вводом. Даже одна такая строка может скомпрометировать всю базу.
Заключение
Строка %")) AND EXTRACTVALUE(5401,CONCAT(0x7e,((SELECT (ELT(5401=5401,1)))),0x7e))-- - — это типичный пример error-based SQL-инъекции для MySQL. Она демонстрирует, как через функции EXTRACTVALUE, CONCAT и ELT злоумышленник может заставить базу вернуть данные в сообщении об ошибке. Понимание механизма таких атак помогает разработчикам и администраторам лучше защищать свои системы. Помните: лучшая защита — это параметризованные запросы и минимизация вывода ошибок.
Комментарии
—Войдите, чтобы оставить комментарий