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

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

Как работает эта инъекция?

Функция EXTRACTVALUE(XML_document, XPath_expression) в MySQL извлекает значение из XML-документа, используя выражение XPath. Если XPath-выражение содержит недопустимый синтаксис, MySQL возвращает ошибку, в которой отображается часть переданного выражения. Злоумышленники используют это для вывода данных: они формируют XPath-строку так, чтобы в тексте ошибки оказались результаты подзапроса.

В нашем примере:

  • 0x7e — это шестнадцатеричное представление символа тильды ~. Он используется как разделитель, чтобы отделить выводимые данные от остального текста ошибки.
  • ELT(1236=1236,1) — функция ELT(N, str1, str2, ...) возвращает N-ю строку из списка. Если 1236=1236 истинно (1), то возвращается строка '1'. Это простейший пример, демонстрирующий, как можно выводить произвольные данные, подставляя вместо условия нужный подзапрос.
  • CONCAT(0x7e, (SELECT ...), 0x7e) — объединяет тильду, результат подзапроса и ещё одну тильду.
  • EXTRACTVALUE(1236, ...) — первый аргумент (1236) не является корректным XML-документом, но это не важно: главное, чтобы XPath-выражение было синтаксически неверным и вызвало ошибку с внедрёнными данными.
  • -- - — комментарий, который обрезает остаток оригинального SQL-запроса, чтобы не возникло синтаксической ошибки.

В результате MySQL выдаёт ошибку вида: XPATH syntax error: '~1~'. В реальной атаке вместо ELT(1236=1236,1) подставляется подзапрос, например, (SELECT version()) или (SELECT password FROM users LIMIT 1), и в сообщении об ошибке отображается версия СУБД или хеш пароля.

Почему это опасно?

Error-based инъекции позволяют злоумышленнику получать произвольные данные из базы, даже если приложение не выводит результаты запроса на экран. Это один из самых быстрых способов эксплуатации SQL-инъекций, поскольку не требует слепого перебора. Успешная атака может привести к:

  • утечке конфиденциальной информации (пароли, персональные данные, номера кредитных карт);
  • полному захвату контроля над базой данных;
  • дальнейшему развитию атаки — например, загрузке веб-шелла или компрометации сервера.

Пример эксплуатации

Рассмотрим упрощённый сценарий. Уязвимый запрос может выглядеть так:

SELECT * FROM articles WHERE id = '$id';

Если параметр $id не экранируется, злоумышленник подставляет:

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

В ответе сервера появится ошибка с версией MySQL. Аналогично можно извлечь имена таблиц, колонок и содержимое записей.

Как защититься?

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

  • экранирование специальных символов с помощью функций драйвера БД;
  • применение ORM (например, Hibernate, Entity Framework), которые автоматически параметризуют запросы;
  • ограничение прав пользователя БД: не давайте приложению прав на чтение системных таблиц и выполнение опасных функций;
  • регулярное обновление СУБД и фреймворков;
  • использование WAF (Web Application Firewall) для блокировки подозрительных запросов.

Важно отметить, что EXTRACTVALUE и подобные функции (UPDATEXML, GTID_SUBSET) часто используются в error-based атаках, поэтому некоторые СУБД по умолчанию ограничивают их вызов. Однако в MySQL они доступны, если не отключены явно.

Заключение

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

Источники