Что такое '))) AND EXTRACTVALUE(5251,CONCAT(0x7e,((SELECT (ELT(5251=5251,1)))),0x7e))-- -
Это типичный пример error-based SQL-инъекции (SQL-инъекция, основанная на ошибках) — техники атаки на веб-приложения, при которой злоумышленник внедряет в уязвимый SQL-запрос код, заставляющий базу данных вернуть сообщение об ошибке, содержащее полезные для атакующего данные. В данном случае используется функция MySQL EXTRACTVALUE(), которая извлекает данные из XML-документа по XPath-выражению. При некорректном XPath-выражении MySQL генерирует ошибку, в текст которой попадает результат подзапроса. Это позволяет атакующему «прочитать» информацию из базы данных через сообщения об ошибках.
Строка '))) AND EXTRACTVALUE(5251,CONCAT(0x7e,((SELECT (ELT(5251=5251,1)))),0x7e))-- - состоит из нескольких частей, каждая из которых выполняет свою задачу. Разберём её по элементам.
Разбор элементов полезной нагрузки
1. Закрывающие скобки и кавычки: ')))
В начале строки идут символы '))). Они нужны, чтобы «закрыть» ранее открытые в уязвимом запросе кавычки и скобки, тем самым сделав внедряемый код синтаксически корректным. Количество закрывающих символов зависит от структуры исходного SQL-запроса, который атакует злоумышленник. Это типичный приём при ручном поиске уязвимостей или при использовании автоматизированных инструментов (например, sqlmap).
2. Оператор AND
AND — логический оператор, который позволяет присоединить дополнительное условие к исходному запросу. Если исходный запрос был истинным, то после добавления AND с внедрённым выражением общий результат может измениться. В error-based инъекциях AND часто используют для того, чтобы внедряемое выражение выполнилось только при определённых условиях, но главное — чтобы оно было вычислено и вызвало ошибку.
3. Функция EXTRACTVALUE(5251, ...)
EXTRACTVALUE() — это встроенная функция MySQL (до версии 8.0.17 включительно, в более новых версиях она удалена), предназначенная для работы с XML. Она принимает два строковых аргумента: фрагмент XML-разметки и XPath-выражение. Функция возвращает текст первого текстового узла, который является дочерним для элемента или элементов, соответствующих XPath-выражению.
В нашем случае первым аргументом передаётся число 5251. Это не случайное число — оно используется как часть условия в подзапросе (ELT(5251=5251,1)). Само по себе число не является корректным XML-документом, но MySQL пытается его интерпретировать. Второй аргумент — сложное выражение CONCAT(0x7e,((SELECT (ELT(5251=5251,1)))),0x7e).
4. CONCAT(0x7e, ..., 0x7e)
CONCAT() объединяет строки. Здесь 0x7e — это шестнадцатеричное представление символа ~ (тильда). Тильда используется как маркер, чтобы в сообщении об ошибке было легко найти внедрённые данные. Между двумя тильдами вставляется результат подзапроса ((SELECT (ELT(5251=5251,1)))).
5. Подзапрос с ELT и условием 5251=5251
ELT(N, str1, str2, ...) — функция MySQL, которая возвращает N-ную строку из списка. В данном случае ELT(5251=5251,1) вычисляет логическое выражение 5251=5251, которое всегда истинно (равно 1). Затем ELT(1, 1) возвращает первый элемент списка — число 1. Таким образом, подзапрос возвращает 1.
В реальной атаке вместо 1 могло бы быть имя базы данных, таблицы, логин администратора или хеш пароля. Например, злоумышленник мог бы использовать SELECT database() или SELECT user(), чтобы получить эти данные. Но в данном примере показан «безопасный» вариант с константой, который просто демонстрирует работу техники.
6. Комментарий -- -
Символы -- - — это комментарий в SQL. Всё, что идёт после них, игнорируется базой данных. Это нужно, чтобы «отрезать» оставшуюся часть исходного запроса, которая могла бы помешать выполнению внедрённого кода. Пробел после двух дефисов обязателен в некоторых СУБД (включая MySQL), поэтому часто пишут -- - или --+.
Как работает error-based SQL-инъекция через EXTRACTVALUE
Механизм следующий:
- Злоумышленник находит параметр, который попадает в SQL-запрос без должной обработки.
- Он внедряет конструкцию, которая заставляет СУБД выполнить подзапрос, возвращающий нужные данные.
- Эти данные передаются в функцию
EXTRACTVALUE()в составе XPath-выражения. Поскольку данные не являются корректным XPath, MySQL генерирует ошибку. - В тексте ошибки MySQL отображает переданное значение (например,
XPATH syntax error: '~1~'). - Атакующий видит результат в ответе сервера и может извлекать данные посимвольно или целыми строками.
Аналогичные функции, которые могут использоваться для error-based инъекций: UPDATEXML(), GTID_SUBSET(), EXP() (в некоторых версиях), а также extractvalue() в комбинации с concat().
Пример уязвимого запроса
Предположим, на сайте есть страница product.php?id=1, и в коде выполняется запрос:
SELECT * FROM products WHERE id = '$id'
Если параметр id не фильтруется, злоумышленник может подставить:
1' AND EXTRACTVALUE(5251,CONCAT(0x7e,(SELECT database()),0x7e))-- -
В ответе сервера появится ошибка вида:
XPATH syntax error: '~имя_базы_данных~'
Таким образом, атакующий узнает имя текущей базы данных. Далее он может извлекать имена таблиц, столбцов и сами данные.
Зачем злоумышленники используют именно EXTRACTVALUE
Функция EXTRACTVALUE() удобна для error-based инъекций по нескольким причинам:
- Она гарантированно вызывает ошибку при некорректном XPath, а текст ошибки содержит переданные данные.
- Она доступна в большинстве версий MySQL (до 8.0.17) и MariaDB.
- Она позволяет извлекать данные в удобном виде, ограничиваясь лишь длиной сообщения об ошибке (обычно 32 символа, но можно обойти через
substringилиmid).
Стоит отметить, что в MySQL 8.0.17 и выше функции EXTRACTVALUE() и UPDATEXML() были удалены, поэтому error-based инъекции через них перестали работать на новых версиях. Однако многие серверы до сих пор используют старые версии MySQL или MariaDB, где эти функции доступны.
Как защититься от error-based SQL-инъекций
Основные меры защиты:
- Использовать подготовленные выражения (prepared statements) с параметризацией. Это самый надёжный способ, так как данные не попадают в текст SQL-запроса.
- Экранировать специальные символы с помощью функций вроде
mysqli_real_escape_string()илиPDO::quote(), но это менее надёжно, чем подготовленные выражения. - Включить вывод ошибок в лог, а не на страницу. Это не устраняет уязвимость, но затрудняет эксплуатацию, так как атакующий не видит текст ошибки.
- Использовать ORM или query builder, которые по умолчанию применяют параметризацию.
- Регулярно обновлять СУБД до версий, где опасные функции удалены или исправлены.
- Применять WAF (Web Application Firewall) для фильтрации подозрительных запросов, хотя это не является панацеей.
Важно понимать, что error-based инъекция — лишь один из многих типов SQL-инъекций. Существуют также union-based, blind (boolean и time-based), out-of-band. Поэтому защита должна быть комплексной.
Заключение
Строка '))) AND EXTRACTVALUE(5251,CONCAT(0x7e,((SELECT (ELT(5251=5251,1)))),0x7e))-- - — это не случайный набор символов, а тщательно сконструированная полезная нагрузка для эксплуатации уязвимости SQL-инъекции. Она демонстрирует, как с помощью функции EXTRACTVALUE() можно заставить базу данных вернуть данные в сообщении об ошибке. Понимание таких техник необходимо как специалистам по информационной безопасности для проведения пентестов, так и разработчикам для написания защищённого кода. Помните: лучшая защита — это параметризованные запросы и внимательное отношение к пользовательскому вводу.
Комментарии
—Войдите, чтобы оставить комментарий