Что такое error-based SQL-инъекция?

SQL-инъекция — это один из самых распространённых способов атаки на веб-приложения, при котором злоумышленник внедряет вредоносный SQL-код в запрос к базе данных. Error-based SQL-инъекция (инъекция на основе ошибок) — это техника, при которой атакующий заставляет СУБД вернуть сообщение об ошибке, содержащее полезные данные (например, логины или пароли пользователей). В отличие от UNION-based инъекций, здесь не требуется, чтобы количество столбцов в запросе совпадало, что делает метод более универсальным.

В вашем запросе присутствует строка: %')) OR EXTRACTVALUE(2499,CONCAT(0x7e,((SELECT (ELT(2499=2499,1)))),0x7e))-- -. Это типичный пример error-based инъекции для СУБД MySQL. Давайте разберём её по частям.

Разбор структуры инъекции

Начнём с начала строки: %')). Символ % часто используется как подстановочный знак в LIKE-запросах, но в данном контексте он, скорее всего, является частью исходного значения, которое передаётся в параметр. Далее идут две закрывающие скобки )) и одинарная кавычка '. Это попытка закрыть ранее открытые скобки и кавычку в оригинальном SQL-запросе, чтобы внедрить свой код. Например, если исходный запрос выглядел как SELECT * FROM users WHERE username = ('%')), то такая конструкция позволяет «вырваться» из строкового литерала и добавить логическое условие.

Далее следует OR EXTRACTVALUE(2499,CONCAT(0x7e,((SELECT (ELT(2499=2499,1)))),0x7e)). Оператор OR используется для того, чтобы внедрённое условие выполнилось, даже если исходное условие ложно. Функция EXTRACTVALUE() — это встроенная функция MySQL, предназначенная для извлечения значения из XML-строки. Она принимает два аргумента: XML-документ и XPath-выражение. Если XPath-выражение синтаксически неверно, MySQL генерирует ошибку, в тексте которой отображается переданный XML-фрагмент. Именно это и используется для извлечения данных.

Первый аргумент 2499 — это просто число, которое будет интерпретировано как XML-документ. Второй аргумент — CONCAT(0x7e,((SELECT (ELT(2499=2499,1)))),0x7e). Функция CONCAT объединяет строки. 0x7e — это шестнадцатеричное представление символа ~ (тильда). Он используется как разделитель, чтобы облегчить поиск полезной нагрузки в сообщении об ошибке. Внутри CONCAT находится подзапрос SELECT (ELT(2499=2499,1)).

Функция ELT() возвращает N-й элемент из списка строк. В данном случае ELT(2499=2499,1) — первый аргумент это логическое выражение 2499=2499, которое истинно (равно 1). Второй аргумент — строка '1'. Таким образом, ELT вернёт '1'. Это простейший пример; в реальной атаке вместо 1 мог бы быть подзапрос, извлекающий, например, имя пользователя или хеш пароля из таблицы users. Например: ELT(1, (SELECT password FROM users LIMIT 1)).

Завершающая часть -- - — это комментарий в SQL. Два дефиса с пробелом означают, что весь оставшийся код запроса будет проигнорирован. Это необходимо, чтобы «обезвредить» возможные остатки оригинального запроса, которые могли бы вызвать синтаксическую ошибку.

Как это работает на практике

Предположим, уязвимый запрос выглядит так: SELECT * FROM articles WHERE id = '%')). Злоумышленник подставляет свою строку, и запрос превращается в:

SELECT * FROM articles WHERE id = '%')) OR EXTRACTVALUE(2499,CONCAT(0x7e,((SELECT (ELT(2499=2499,1)))),0x7e))-- -

MySQL выполняет запрос. Сначала вычисляется левая часть id = '%')) — она, скорее всего, ложна. Затем вычисляется правая часть после OR. Функция EXTRACTVALUE пытается обработать XPath-выражение ~1~ (результат CONCAT). Поскольку ~1~ не является корректным XPath, MySQL возвращает ошибку: XPATH syntax error: '~1~'. В этом сообщении об ошибке и содержится искомая информация — в данном случае просто 1. Если бы вместо 1 был подзапрос, возвращающий конфиденциальные данные, они бы отобразились в тексте ошибки.

Важно отметить, что для успешной эксплуатации приложение должно выводить сообщения об ошибках СУБД пользователю. Если ошибки подавляются, метод не сработает.

Зачем нужны EXTRACTVALUE и ELT?

Функция EXTRACTVALUE появилась в MySQL 5.1 и часто используется в error-based инъекциях благодаря тому, что она генерирует ошибку с контролируемым содержимым. Другие функции, такие как UPDATEXML, работают аналогично. ELT же позволяет выбрать конкретную строку из списка, что удобно для извлечения одного значения за раз. Комбинация этих функций даёт атакующему гибкий инструмент для посимвольного извлечения данных.

Стоит подчеркнуть, что подобные техники относятся к категории «слепых» инъекций, когда данные извлекаются не напрямую, а через анализ ответов сервера. Error-based — более удобный вариант, так как данные сразу видны в сообщении об ошибке.

Как защититься от error-based SQL-инъекций?

Основной способ защиты — использование параметризованных запросов (prepared statements). Это гарантирует, что пользовательский ввод никогда не будет интерпретирован как SQL-код. В языках программирования, таких как PHP, Java, Python, C#, существуют готовые библиотеки для работы с параметризованными запросами (PDO, JDBC, psycopg2 и т.д.).

Дополнительные меры:

  • Отключение вывода ошибок СУБД в продакшене. Ошибки должны логироваться, но не показываться пользователю.
  • Валидация и фильтрация входных данных. Например, если параметр должен быть числом, приводите его к целому типу.
  • Использование ORM (Object-Relational Mapping), которые по умолчанию экранируют опасные символы.
  • Регулярные сканирования уязвимостей и обновление СУБД и фреймворков.

Также рекомендуется применять принцип наименьших привилегий для учётной записи, под которой работает приложение: она не должна иметь прав на чтение системных таблиц или выполнение опасных функций.

Заключение

Строка %')) OR EXTRACTVALUE(2499,CONCAT(0x7e,((SELECT (ELT(2499=2499,1)))),0x7e))-- - — это компактный, но мощный пример error-based SQL-инъекции. Она демонстрирует, как злоумышленники используют особенности функций MySQL для извлечения данных через сообщения об ошибках. Понимание таких техник необходимо разработчикам и специалистам по безопасности для своевременного выявления и устранения уязвимостей. Всегда используйте параметризованные запросы и не доверяйте пользовательскому вводу — это золотое правило веб-безопасности.

Источники