Введение

В логах веб-сервера или в поле ввода можно встретить загадочную последовательность символов: ' OR EXTRACTVALUE(8819,CONCAT(0x7e,((SELECT (ELT(8819=8819,1)))),0x7e))-- -. Для неспециалиста это выглядит как случайный набор знаков, но на самом деле перед нами классический пример SQL-инъекции. Подобные строки — попытка злоумышленника вмешаться в работу базы данных через уязвимость в веб-приложении. В этой статье мы детально разберём, что означает каждый элемент этого запроса, какова его цель и как защититься от таких атак.

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

SQL-инъекция (SQL injection) — один из самых распространённых способов взлома веб-сайтов. Атакующий вставляет в поля ввода или параметры URL специально сконструированные команды SQL, которые выполняются на сервере баз данных. Если приложение не проверяет входные данные должным образом, эти команды могут изменить логику запроса, позволить получить конфиденциальную информацию, изменить или удалить данные.

Существует несколько разновидностей SQL-инъекций: классические (основанные на ошибках), слепые (boolean-based, time-based), а также инъекции, использующие специфические функции СУБД. Рассматриваемый пример относится к типу error-based, где злоумышленник намеренно вызывает ошибку, чтобы извлечь данные через сообщение об ошибке.

Разбор строки запроса

Давайте разложим атаку на составляющие:

  • ' — одиночная кавычка, которая закрывает строковый литерал в оригинальном SQL-запросе. Это точка внедрения.
  • OR — логический оператор, который делает условие всегда истинным (или изменяет логику запроса).
  • EXTRACTVALUE(8819, CONCAT(0x7e, ((SELECT (ELT(8819=8819,1)))), 0x7e)) — вызов функции EXTRACTVALUE, предназначенной для извлечения значения из XML-документа по XPath-выражению.
  • -- - — комментарий, который «отрезает» оставшуюся часть оригинального запроса, чтобы синтаксис оставался корректным.

Функция EXTRACTVALUE

В СУБД MySQL и MariaDB функция EXTRACTVALUE(XML, XPath) возвращает текст из XML-фрагмента, соответствующий заданному XPath-выражению. Она часто используется в легитимных задачах обработки XML. Однако злоумышленники нашли способ применять её для извлечения данных: если XPath-выражение содержит ошибку, MySQL генерирует сообщение об ошибке, в которое попадает результат вычисления вложенного запроса. Это позволяет атакующему «прочитать» содержимое базы данных.

Синтаксис: EXTRACTVALUE(xml_frag, xpath_expr). Если XPath-выражение не соответствует ни одному узлу или содержит недопустимые символы, возвращается ошибка. Именно эту ошибку и использует атакующий.

Конкатенация и шестнадцатеричные литералы

В строке CONCAT(0x7e, ((SELECT (ELT(8819=8819,1)))), 0x7e) применяется функция CONCAT, которая объединяет строки. 0x7e — это шестнадцатеричное представление символа ~ (тильда). Тильда используется как разделитель, чтобы отделить результат подзапроса от остального текста в сообщении об ошибке. Это облегчает автоматизированный парсинг данных инструментами вроде sqlmap.

Подзапрос с ELT

Внутри конкатенации находится подзапрос: SELECT (ELT(8819=8819,1)). Функция ELT(N, str1, str2, ...) возвращает N-ю строку из списка. В данном случае условие 8819=8819 всегда истинно (возвращает 1), поэтому ELT(1,1) вернёт строку '1'. Это простейший пример. В реальной атаке вместо 1 могло бы стоять выражение, извлекающее имя таблицы, версию СУБД или хеши паролей. Например, ELT(8819=8819, (SELECT table_name FROM information_schema.tables LIMIT 1)).

Комментарий в конце

Последовательность -- - (дефис, дефис, пробел, дефис) — это комментарий в SQL. В MySQL комментарий начинается с -- (два дефиса и пробел). Добавочный дефис часто используется для обхода фильтров, которые могут удалять стандартные комментарии. Всё, что идёт после этого, игнорируется базой данных, что позволяет сохранить синтаксическую правильность запроса.

Цель атаки

Основная цель — заставить сервер выполнить произвольный SQL-код и вернуть результат в сообщении об ошибке. Это может привести к:

  • Получению конфиденциальных данных (логины, пароли, персональные данные пользователей).
  • Изменению или удалению информации в базе.
  • Обходу аутентификации и авторизации.
  • Выполнению административных операций над СУБД.

Конкретно эта строка с EXTRACTVALUE и ELT — типичный пример error-based инъекции, когда атакующий «вытаскивает» данные посимвольно или целыми строками через ошибки.

Как распознать атаку

Признаки SQL-инъекции в логах:

  • Наличие SQL-ключевых слов (SELECT, UNION, OR, AND) в параметрах запроса.
  • Использование функций, специфичных для СУБД (EXTRACTVALUE, UPDATEXML, CONCAT, ELT).
  • Шестнадцатеричные последовательности (0x7e) и комментарии (--, #).
  • Аномально длинные строки в полях ввода.

Если вы обнаружили подобные записи, это сигнал о попытке взлома. Необходимо срочно проверить безопасность приложения.

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

Существует несколько надёжных методов защиты:

  1. Параметризованные запросы (prepared statements). Самый эффективный способ. Данные передаются отдельно от SQL-кода, и СУБД не интерпретирует их как команды.
  2. Хранимые процедуры. Если они написаны корректно, также снижают риск.
  3. Экранирование специальных символов. Например, с помощью функций вроде mysqli_real_escape_string в PHP. Но этот метод уступает параметризации.
  4. Валидация и фильтрация входных данных. Проверяйте типы, длины, допустимые символы.
  5. Ограничение прав пользователя БД. Не давайте приложению прав на удаление таблиц или доступ к системным каталогам.
  6. Регулярный аудит и сканирование уязвимостей. Используйте инструменты статического анализа и пентесты.

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

Пример безопасного кода

Вместо конкатенации строк в запросе:

$query = "SELECT * FROM users WHERE name = '$name'";

используйте подготовленные выражения (на примере PDO в PHP):

$stmt = $pdo->prepare("SELECT * FROM users WHERE name = :name");
$stmt->execute(['name' => $name]);

Такой подход гарантирует, что даже если злоумышленник введёт ' OR EXTRACTVALUE(...)-- -, это будет воспринято как обычная строка, а не как SQL-код.

Заключение

Строка ' OR EXTRACTVALUE(8819,CONCAT(0x7e,((SELECT (ELT(8819=8819,1)))),0x7e))-- - — это не случайный набор символов, а целенаправленная попытка эксплуатации уязвимости SQL-инъекции. Понимание механики таких атак помогает разработчикам и администраторам своевременно выявлять угрозы и принимать меры. Используйте параметризованные запросы, ограничивайте права БД и следите за логами — это значительно снизит риск успешного взлома.

Источники