Что это за строка?
Строка %' AND EXTRACTVALUE(6486,CONCAT(0x7e,((SELECT (ELT(6486=6486,1)))),0x7e))-- - — это классический пример error-based SQL-инъекции для СУБД MySQL. Она предназначена для извлечения данных из базы через вывод сообщения об ошибке. Подобные конструкции часто встречаются в отчётах сканеров уязвимостей и в эксплойтах, нацеленных на веб-приложения, которые небезопасно обрабатывают пользовательский ввод.
Внешне строка выглядит как бессмысленный набор символов, но каждый её элемент имеет строгое назначение. Разберём её по частям.
Анатомия запроса
1. Начальный фрагмент %'
Символ % часто используется в SQL-шаблонах LIKE. Здесь он, скорее всего, является частью исходного запроса, в который внедряется инъекция. Апостроф ' закрывает строковый литерал, позволяя злоумышленнику добавить собственный SQL-код. Например, если уязвимый запрос выглядит как SELECT * FROM users WHERE name LIKE '%...%', то подстановка %' AND ... разрывает строку и добавляет условие.
2. Функция EXTRACTVALUE(6486, CONCAT(...))
EXTRACTVALUE — это встроенная функция MySQL (до версии 8.0), предназначенная для извлечения значения из XML-документа по заданному XPath-выражению. Синтаксис: EXTRACTVALUE(XML_document, XPath_expression). Если XPath-выражение синтаксически некорректно, MySQL генерирует ошибку, в тексте которой отображается переданный фрагмент. Это и есть основа error-based инъекции.
В нашем случае первым аргументом передаётся число 6486 — оно не является корректным XML-документом, но это не важно: злоумышленник использует функцию исключительно как «генератор ошибок».
3. CONCAT(0x7e, ..., 0x7e)
Функция CONCAT объединяет строки. 0x7e — это шестнадцатеричное представление символа тильды ~. Тильда выбрана не случайно: она не является допустимым символом в XPath-выражении, поэтому её наличие гарантированно вызывает ошибку синтаксиса. Это нужно, чтобы MySQL вывел сообщение об ошибке, содержащее полезную нагрузку.
4. Подзапрос (SELECT (ELT(6486=6486,1)))
Внутренний подзапрос возвращает результат выражения ELT(6486=6486,1). Функция ELT(N, str1, str2, ...) возвращает N-ю строку из списка. Здесь N — это результат сравнения 6486=6486, который всегда истинен и равен 1. Следовательно, ELT(1,1) вернёт строку '1'. Таким образом, подзапрос возвращает строку '1'.
В реальной атаке вместо ELT(6486=6486,1) подставляются вызовы вроде (SELECT DATABASE()) или (SELECT GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema=DATABASE()), чтобы извлечь имя текущей базы данных или список таблиц. В нашем примере используется безобидная заглушка, чтобы продемонстрировать структуру.
5. Комментарий -- -
Два дефиса с пробелом (или -- -) — это комментарий в MySQL. Он «отрезает» оставшуюся часть оригинального запроса, чтобы синтаксис оставался корректным. Пробел после дефисов обязателен в некоторых реализациях, отсюда и дополнительный дефис.
Как это работает целиком
Соберём логику:
- Апостроф закрывает строку в уязвимом запросе.
- Добавляется условие
AND EXTRACTVALUE(6486, CONCAT(0x7e, (SELECT (ELT(6486=6486,1))), 0x7e)). - Внутри
CONCATформируется строка вида~1~(тильда, результат подзапроса, тильда). EXTRACTVALUEпытается интерпретировать эту строку как XPath-выражение, но тильды недопустимы, поэтому возникает ошибка.- MySQL возвращает сообщение об ошибке, в котором фигурирует переданная строка, например:
XPATH syntax error: '~1~'. - Злоумышленник видит результат выполнения подзапроса (в данном случае
1) в тексте ошибки.
Если заменить ELT(6486=6486,1) на полезный запрос, например (SELECT DATABASE()), то в ошибке отобразится имя текущей базы данных. Такой метод позволяет извлекать произвольные данные посимвольно или целыми строками, если использовать GROUP_CONCAT.
Зачем это нужно злоумышленнику?
Error-based инъекции — один из самых быстрых способов получить информацию из базы, когда приложение выводит сообщения об ошибках СУБД на страницу. В отличие от blind-инъекций, где данные приходится угадывать по битам, здесь результат приходит напрямую в тексте ошибки. Это экономит время и упрощает эксплуатацию.
Описанная конструкция с EXTRACTVALUE и CONCAT(0x7e,...) стала классикой благодаря своей надёжности: она работает на многих версиях MySQL, где функция EXTRACTVALUE ещё не удалена. В MySQL 8.0.17 и новее эта функция помечена как устаревшая, но во многих реальных системах всё ещё используются старые версии.
Как защититься?
Лучший способ — не допускать попадания пользовательского ввода в SQL-запросы без обработки. Основные меры:
- Параметризованные запросы (prepared statements) — самый надёжный метод. Данные передаются отдельно от кода запроса, и СУБД не интерпретирует их как SQL.
- Экранирование специальных символов — если параметризация невозможна, используйте функции экранирования, предоставляемые драйвером БД (например,
mysqli_real_escape_stringв PHP). - Отключение вывода ошибок СУБД — не показывайте пользователям сообщения об ошибках базы данных. Логируйте их, но не выводите в браузер.
- Принцип наименьших привилегий — учётная запись, от имени которой работает приложение, должна иметь только необходимые права. Это ограничит ущерб в случае успешной инъекции.
- Регулярное обновление СУБД — новые версии MySQL удаляют опасные функции и закрывают известные уязвимости.
Итог
Строка %' AND EXTRACTVALUE(6486,CONCAT(0x7e,((SELECT (ELT(6486=6486,1)))),0x7e))-- - — это учебный пример error-based SQL-инъекции. Она демонстрирует, как злоумышленник может использовать функцию EXTRACTVALUE и символ тильды для вызова ошибки, в тексте которой утекают данные. Понимание таких конструкций помогает разработчикам и специалистам по безопасности лучше защищать свои приложения.
Комментарии
—Войдите, чтобы оставить комментарий