Что это за строка?
Строка ' AND EXTRACTVALUE(6073,CONCAT(0x7e,((SELECT (ELT(6073=6073,1)))),0x7e))-- - — это классический пример error-based SQL-инъекции (инъекции на основе ошибок) для СУБД MySQL. Такие конструкции используют для извлечения данных из базы через вывод сообщения об ошибке. Злоумышленник внедряет вредоносный SQL-код в уязвимый параметр веб-приложения, и сервер возвращает текст ошибки, содержащий результат выполнения подзапроса.
В данном случае применяется функция EXTRACTVALUE() — одна из функций для работы с XML в MySQL. Она извлекает значение из XML-строки по указанному XPath-выражению. Если XPath-выражение некорректно, MySQL генерирует ошибку, в тексте которой отображается переданный аргумент. Это и позволяет атакующему «вытащить» нужные данные.
Разбор по частям
Рассмотрим каждый элемент запроса:
' AND ... -- -— закрывает предыдущее строковое значение в уязвимом параметре, добавляет логическое условиеANDи комментирует остаток исходного SQL-запроса. Два дефиса с пробелом или без — стандартный комментарий в MySQL.EXTRACTVALUE(6073, ...)— первый аргумент — произвольное число (идентификатор), второй — XML-фрагмент, который формируется динамически.CONCAT(0x7e, ((SELECT (ELT(6073=6073,1)))), 0x7e)— конкатенация символа~(0x7e), результата подзапроса и снова~. Символ~используется как маркер, чтобы отделить полезную нагрузку в сообщении об ошибке.SELECT (ELT(6073=6073,1))— подзапрос, возвращающий 1, если условие6073=6073истинно, и NULL в противном случае. ФункцияELT()возвращает N-й элемент из списка; здесь список состоит из одного элемента — числа 1.
В результате MySQL пытается интерпретировать строку вида ~1~ как XPath. Поскольку это невалидный XPath, возникает ошибка: XPATH syntax error: '~1~'. В реальной атаке вместо 1 подставляется выражение, извлекающее, например, имя базы данных, версию СУБД или хеши паролей.
Как это работает на практике
Предположим, уязвимый запрос выглядит так:
SELECT * FROM articles WHERE id = '$_GET[id]'
Если передать в параметр id нашу строку, итоговый запрос примет вид:
SELECT * FROM articles WHERE id = '' AND EXTRACTVALUE(6073,CONCAT(0x7e,((SELECT (ELT(6073=6073,1)))),0x7e))-- -'
MySQL выполнит подзапрос, получит 1, сформирует строку ~1~, попытается разобрать её как XPath и выдаст ошибку. Приложение, если оно не скрывает ошибки, отобразит её пользователю. Атакующий увидит XPATH syntax error: '~1~' и поймёт, что инъекция работает.
Для извлечения реальных данных вместо ELT(6073=6073,1) подставляют, например, SELECT database() или SELECT version(). Тогда в ошибке появится имя текущей базы данных или версия MySQL.
Почему EXTRACTVALUE, а не UNION?
Метод error-based через EXTRACTVALUE применяют, когда:
- Приложение возвращает сообщения об ошибках СУБД (или их часть) в ответе.
- Использование
UNION SELECTневозможно из-за несоответствия количества столбцов или типов данных. - Нужно обойти фильтры, которые блокируют ключевые слова вроде
UNIONилиSELECT(хотяSELECTздесь тоже присутствует).
Функция EXTRACTVALUE доступна в MySQL начиная с версии 5.1.5. В более новых версиях (8.0+) она помечена как устаревшая, но всё ещё работает. Аналогичный эффект дают UPDATEXML() и GTID_SUBSET().
Чем опасна такая инъекция
Успешная эксплуатация error-based SQL-инъекции позволяет злоумышленнику:
- Получить версию СУБД, имя текущей базы данных, имя пользователя, под которым работает приложение.
- Извлечь структуру таблиц: названия таблиц и столбцов через
information_schema. - Похитить конфиденциальные данные: логины, пароли (в виде хешей), персональные данные клиентов, номера банковских карт.
- В некоторых случаях — выполнить произвольные команды на сервере, если у пользователя БД есть соответствующие привилегии (например,
FILEдля записи файлов).
Даже если приложение не показывает ошибки напрямую, атакующий может использовать слепые методы (boolean-based, time-based), но error-based даёт самый быстрый результат.
Как защититься
Основной способ предотвращения SQL-инъекций — использование параметризованных запросов (prepared statements). В этом случае пользовательский ввод передаётся отдельно от SQL-кода и не может изменить структуру запроса. Пример на PHP с PDO:
$stmt = $pdo->prepare('SELECT * FROM articles WHERE id = :id');
$stmt->execute(['id' => $_GET['id']]);
Дополнительные меры:
- Отключить вывод ошибок СУБД в production-окружении. Сообщения об ошибках должны логироваться, а не отображаться пользователю.
- Использовать ORM или query builder, которые по умолчанию экранируют параметры.
- Применять принцип наименьших привилегий для учётной записи БД: запретить доступ к
information_schema, если он не нужен, и не давать правFILE. - Регулярно обновлять СУБД и веб-приложение, чтобы закрыть известные уязвимости.
- Проводить аудит кода и пентесты для выявления подобных дыр.
Важно: error-based SQL-инъекция — не просто теоретическая угроза. По данным OWASP, инъекции входят в топ-10 критических рисков веб-приложений. Даже одна незакрытая точка входа может привести к полной компрометации базы данных.
Заключение
Строка ' AND EXTRACTVALUE(6073,CONCAT(0x7e,((SELECT (ELT(6073=6073,1)))),0x7e))-- - — это шаблон error-based SQL-инъекции для MySQL. Она демонстрирует, как через вызов функции EXTRACTVALUE с заведомо некорректным XPath можно заставить СУБД вывести произвольные данные в сообщении об ошибке. Понимание этого механизма помогает разработчикам и специалистам по безопасности правильно выстраивать защиту: использовать параметризованные запросы, скрывать ошибки и ограничивать права пользователей БД.
Комментарии
—Войдите, чтобы оставить комментарий