Введение в SQL-инъекции через ошибки

SQL-инъекции остаются одной из самых распространённых уязвимостей веб-приложений. Среди них особое место занимают error-based инъекции, при которых злоумышленник извлекает данные, заставляя базу данных возвращать сообщения об ошибках, содержащие конфиденциальную информацию. Запрос `) AND EXTRACTVALUE(1403,CONCAT(0x7e,((SELECT (ELT(1403=1403,1)))),0x7e))-- - — классический пример такой атаки, нацеленной на MySQL.

Что такое EXTRACTVALUE?

EXTRACTVALUE — это встроенная функция MySQL, предназначенная для извлечения значения из фрагмента XML. Синтаксис: EXTRACTVALUE(XML_frag, XPath_expr). Она принимает XML-документ и выражение XPath, возвращая строку с результатом. Однако при некорректном XPath-выражении функция генерирует ошибку XPATH syntax error, которая включает в себя переданный фрагмент. Именно это свойство эксплуатируется в error-based SQL-инъекциях.

Впервые техника была описана в 2012 году исследователем безопасности, и с тех пор стала стандартным инструментом пентестеров. Аналогичные функции: UPDATEXML и GTID_SUBSET.

Разбор внедряемого запроса

Рассмотрим payload по частям:

  • `) AND ... -- - — закрывает предыдущее выражение в SQL-запросе приложения. Символы ) и ` завершают открытые скобку и обратный апостроф, а -- - комментирует остаток оригинального запроса.
  • EXTRACTVALUE(1403, CONCAT(0x7e, ((SELECT (ELT(1403=1403,1)))), 0x7e)) — основная часть. Первый аргумент 1403 — произвольное число, которое будет интерпретировано как XML-фрагмент (не является корректным XML). Второй аргумент — строка, начинающаяся и заканчивающаяся символом ~ (0x7e).
  • CONCAT(0x7e, ((SELECT (ELT(1403=1403,1)))), 0x7e) — конкатенация тильды, результата подзапроса и ещё одной тильды. Подзапрос SELECT (ELT(1403=1403,1)) возвращает 1, так как условие 1403=1403 истинно. ELT(N, str1, str2, ...) возвращает N-ю строку из списка; здесь список состоит из одного элемента 1.

В итоге EXTRACTVALUE получает на вход число 1403 (не XML) и строку ~1~. Поскольку 1403 не является валидным XML, MySQL выдаёт ошибку: XPATH syntax error: '~1~'. В реальной атаке вместо 1 подставляется выражение, извлекающее данные (например, имя пользователя, хеш пароля), и оно отображается в тексте ошибки.

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

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

1') AND EXTRACTVALUE(1403,CONCAT(0x7e,(SELECT database()),0x7e))-- -

Тогда итоговый SQL-запрос становится:

SELECT * FROM users WHERE id = '1') AND EXTRACTVALUE(1403,CONCAT(0x7e,(SELECT database()),0x7e))-- -'

База данных выполняет подзапрос, получает имя текущей базы (например, shop_db), формирует строку ~shop_db~, и EXTRACTVALUE генерирует ошибку с этим текстом. Приложение выводит ошибку на экран, и атакующий видит имя базы. Аналогично можно извлечь таблицы, столбцы, логины и пароли.

Почему используется CONCAT и ELT?

CONCAT нужен для объединения разделителей (тильд) с полезной нагрузкой, чтобы чётко выделить извлекаемые данные в сообщении об ошибке. Тильда выбрана как редко встречающийся символ, который легко найти в тексте ошибки.

ELT (Extract List of Terms) — функция, возвращающая N-й элемент из списка строк. В данном случае она используется для генерации константного значения 1, чтобы продемонстрировать работоспособность инъекции. В реальных атаках вместо ELT могут применяться другие функции, например CONCAT_WS или GROUP_CONCAT для объединения нескольких значений.

Последствия для безопасности

Успешная эксплуатация такой инъекции позволяет злоумышленнику:

  • Получить доступ ко всем данным в базе: учётные записи, персональные данные, платёжная информация.
  • Изменять или удалять информацию.
  • Выполнять административные операции, если уязвимый пользователь БД обладает высокими привилегиями.
  • В некоторых случаях — выполнять команды на сервере через LOAD_FILE или INTO OUTFILE.

По данным OWASP, инъекции занимают третье место в топ-10 критических угроз веб-приложений (2021).

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

Основной метод — использование параметризованных запросов (prepared statements). Они отделяют код SQL от данных, делая невозможным внедрение произвольных конструкций. Даже если злоумышленник передаст вредоносную строку, она будет обработана как литерал, а не как часть запроса.

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

  • Отключите вывод подробных ошибок БД в production-среде. Пользователь должен видеть общее сообщение, а детали записываться в лог.
  • Используйте хранимые процедуры с параметрами.
  • Ограничьте привилегии пользователя БД, от имени которого работает приложение (только необходимые операции).
  • Применяйте WAF (Web Application Firewall) для фильтрации подозрительных запросов.
  • Регулярно обновляйте СУБД и фреймворки.

Заключение

Запрос `) AND EXTRACTVALUE(1403,CONCAT(0x7e,((SELECT (ELT(1403=1403,1)))),0x7e))-- - — это не просто набор символов, а рабочий эксплойт для извлечения данных через ошибки MySQL. Понимание его механики помогает разработчикам и специалистам по безопасности лучше защищать свои приложения. Помните: лучшая защита — параметризация запросов и минимизация вывода ошибок.

Источники