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

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

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

Разбор запроса по частям

Рассмотрим синтаксис подробнее. Запрос состоит из нескольких частей:

  • )))) — закрывающие скобки, которые завершают предыдущее выражение в уязвимом SQL-запросе. Их количество подбирается так, чтобы синтаксис остался корректным.
  • AND EXTRACTVALUE(3857,CONCAT(0x7e,((SELECT (ELT(3857=3857,1)))),0x7e)) — основная полезная нагрузка. Функция EXTRACTVALUE принимает два аргумента: первый — произвольное число (здесь 3857), второй — XPath-выражение. В качестве XPath передаётся строка, начинающаяся с символа ~ (0x7e), затем результат подзапроса и снова ~.
  • -- - — комментарий, который «отрезает» оставшуюся часть оригинального SQL-запроса, чтобы не возникло синтаксической ошибки.

Внутри CONCAT выполняется подзапрос SELECT (ELT(3857=3857,1)). Функция ELT(N, str1, str2, ...) возвращает N-ю строку из списка. Здесь условие 3857=3857 всегда истинно (1), поэтому ELT(1,1) вернёт строку '1'. В реальной атаке вместо этого подзапроса вставляется выражение, извлекающее нужные данные, например, версию СУБД, имя базы или хеши паролей.

Как работает error-based инъекция

MySQL при попытке разобрать XPath-выражение, начинающееся с символа ~ (тильда), вызывает ошибку вида: XPATH syntax error: '~1~'. В этом сообщении отображается переданная строка. Если вместо '1' подставить результат подзапроса, например SELECT version(), то в ошибке появится версия MySQL. Так пошагово атакующий может извлечь любые данные: имена таблиц, столбцов, логины, пароли.

Error-based SQL-инъекции особенно опасны, потому что не требуют слепого перебора и позволяют мгновенно получать результат прямо в ответе сервера.

Какие данные можно извлечь?

С помощью EXTRACTVALUE и аналогичных функций (UPDATEXML, GTID_SUBSET) злоумышленник может получить:

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

Получив эти сведения, атакующий может развить атаку: изменить данные, удалить таблицы, загрузить веб-шелл на сервер или использовать скомпрометированные учётные записи для доступа к другим системам.

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

Предположим, на сайте есть уязвимый параметр id в URL: https://example.com/product?id=1. Запрос к базе выглядит так:

SELECT * FROM products WHERE id = 1;

Атакующий подставляет полезную нагрузку:

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

В ответе сервера появится ошибка: XPATH syntax error: '~8.0.32~'. Так узнаётся версия MySQL. Далее можно извлекать имена таблиц, например:

1 AND EXTRACTVALUE(3857,CONCAT(0x7e,(SELECT table_name FROM information_schema.tables LIMIT 0,1),0x7e))-- -

И так далее, пока не будут получены все нужные данные.

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

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

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

  1. Экранирование специальных символов с помощью функций вроде mysqli_real_escape_string (но это менее надёжно, чем prepared statements).
  2. Ограничение прав пользователя базы данных: приложению не нужны права на чтение information_schema или выполнение опасных функций.
  3. Использование ORM-библиотек, которые автоматически параметризуют запросы.
  4. Регулярное обновление СУБД и фреймворков для устранения известных уязвимостей.
  5. Внедрение WAF (Web Application Firewall) для блокировки подозрительных запросов, хотя WAF не является панацеей.

Важно понимать, что error-based инъекции — лишь один из многих типов SQL-инъекций. UNION-based, blind, time-based и другие техники также широко распространены. Поэтому защита должна быть комплексной.

Заключение

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

Источники