Что такое SQL-инъекция через EXTRACTVALUE?
SQL-инъекция (SQLi) остаётся одной из самых опасных уязвимостей веб-приложений. Согласно OWASP Top 10, она стабильно входит в список критических рисков. Один из методов эксплуатации — error-based SQL-инъекция, при которой злоумышленник заставляет базу данных выдать сообщение об ошибке, содержащее полезные данные. Функция EXTRACTVALUE() в MySQL часто используется для этой цели.
В запросе пользователя '))) AND EXTRACTVALUE(9853,CONCAT(0x7e,((SELECT (ELT(9853=9853,1)))),0x7e))-- - демонстрируется именно такая атака. Давайте разберём её по частям.
Анатомия инъекции
Начнём с начала строки: '))) — это попытка закрыть ранее открытые кавычки и скобки в уязвимом SQL-запросе. Злоумышленник предполагает, что исходный запрос выглядит примерно так:
SELECT * FROM users WHERE id = (('...'))
Три закрывающие скобки и одинарная кавычка позволяют выйти из контекста строкового литерала и добавить собственное условие.
Далее идёт AND EXTRACTVALUE(9853,CONCAT(0x7e,((SELECT (ELT(9853=9853,1)))),0x7e)). Функция EXTRACTVALUE(XML_document, XPath_expression) возвращает фрагмент XML по заданному XPath. Если XPath-выражение некорректно, MySQL выдаёт ошибку, в тексте которой отображается переданное значение. Это и есть канал утечки данных.
Первый аргумент 9853 — произвольное число, которое должно быть валидным XML-документом? На самом деле нет: MySQL ожидает XML-строку, но если передать число, оно преобразуется в строку. Однако в данном случае важен второй аргумент.
CONCAT(0x7e, ((SELECT (ELT(9853=9853,1)))), 0x7e) формирует строку, начиная и заканчивая символом ~ (0x7e). Внутри — подзапрос SELECT (ELT(9853=9853,1)). Функция ELT(N, str1, str2, ...) возвращает N-ю строку из списка. Здесь 9853=9853 — всегда истина (1), поэтому ELT(1,1) вернёт 1. Это простейший тест: если инъекция работает, в ошибке появится строка ~1~.
Завершающая часть -- - — комментарий, который отсекает остаток оригинального запроса. Пробел после двух дефисов обязателен в MySQL.
Как это работает на практике
Предположим, уязвимый запрос:
SELECT * FROM articles WHERE id = '$_GET[id]'
Передав 1' AND EXTRACTVALUE(1,CONCAT(0x7e,(SELECT version()),0x7e))-- -, злоумышленник получит ошибку вида:
XPATH syntax error: '~5.7.33~'
Так он узнает версию СУБД. Аналогично можно извлечь имя базы данных, таблицы, логины и пароли. В нашем примере с ELT(9853=9853,1) проверяется сама возможность инъекции — это разведочный запрос.
Важно: EXTRACTVALUE удалена в MySQL 8.0.17, но во многих устаревших системах (5.7 и ниже) она всё ещё доступна. Это делает технику актуальной для пентеста старых приложений.
Последствия успешной атаки
Error-based инъекция через EXTRACTVALUE позволяет:
- Получить версию MySQL, имя пользователя, базу данных.
- Извлечь содержимое таблиц (например, логины и хеши паролей).
- Обойти аутентификацию, если запрос используется в форме входа.
- В некоторых случаях — выполнить произвольный код через
INTO OUTFILE.
По данным OWASP, SQL-инъекции приводят к утечкам миллионов записей ежегодно. Даже одна уязвимая точка может скомпрометировать всю базу.
Как защититься от SQL-инъекций
Главный метод — параметризованные запросы (prepared statements). Они разделяют код и данные, поэтому ввод пользователя никогда не интерпретируется как SQL.
Пример на PHP с PDO:
$stmt = $pdo->prepare('SELECT * FROM articles WHERE id = :id');
$stmt->execute(['id' => $_GET['id']]);
Дополнительные меры:
- Использовать ORM (Doctrine, Hibernate) с автоматической экранизацией.
- Валидировать и фильтровать входные данные (белые списки).
- Ограничить права пользователя БД: только необходимые операции.
- Отключить вывод ошибок СУБД на продакшене.
- Регулярно обновлять MySQL и фреймворки.
Если вы тестируете собственное приложение на проникновение, можно использовать sqlmap — он автоматически определяет и эксплуатирует error-based инъекции, включая EXTRACTVALUE.
Заключение
Запрос '))) AND EXTRACTVALUE(9853,CONCAT(0x7e,((SELECT (ELT(9853=9853,1)))),0x7e))-- - — это учебный пример error-based SQL-инъекции. Он показывает, как через ошибку функции EXTRACTVALUE можно извлечь данные. Понимание таких техник необходимо для безопасной разработки: используйте параметризацию, минимизируйте привилегии и не выводите детали ошибок клиенту.
Комментарии
—Войдите, чтобы оставить комментарий