Что это за строка?

Строка %') AND EXTRACTVALUE(4784,CONCAT(0x7e,((SELECT (ELT(4784=4784,1)))),0x7e))-- - представляет собой классический пример error-based SQL-инъекции (инъекции на основе ошибок) для СУБД MySQL. Такие конструкции используются злоумышленниками для извлечения данных из базы данных через вывод сообщения об ошибке. В данном случае применяется функция EXTRACTVALUE, которая извлекает значение из XML-документа, но при некорректном XPath-выражении генерирует ошибку, содержащую переданные данные.

Подобные строки часто встречаются в отчётах об уязвимостях, при пентестах и в логах веб-серверов. Они не являются вредоносным кодом сами по себе, но служат инструментом для проверки наличия уязвимости и получения скрытой информации.

Как работает error-based SQL-инъекция?

Error-based SQL-инъекция — это техника, при которой атакующий заставляет базу данных вернуть результат SQL-запроса в виде сообщения об ошибке. Это возможно, если веб-приложение выводит ошибки СУБД на страницу. MySQL поддерживает несколько функций, генерирующих такие ошибки: EXTRACTVALUE, UPDATEXML, GTID_SUBSET и другие.

Рассмотрим разбираемую строку по частям:

  • %') — это попытка закрыть предыдущий SQL-запрос. Символ % часто используется в LIKE-запросах, а ' и ) закрывают строковый литерал и скобку. Таким образом, атакующий предполагает, что исходный запрос выглядит примерно так: SELECT * FROM users WHERE name LIKE '%...%'.
  • AND EXTRACTVALUE(4784,CONCAT(0x7e,((SELECT (ELT(4784=4784,1)))),0x7e)) — это внедряемая конструкция. Функция EXTRACTVALUE принимает два аргумента: XML-документ и XPath-выражение. В качестве первого аргумента передаётся число 4784 (произвольное), а второй аргумент формируется через CONCAT.
  • 0x7e — это шестнадцатеричное представление символа ~ (тильда). Тильда используется как маркер, чтобы облегчить поиск выводимых данных в сообщении об ошибке.
  • SELECT (ELT(4784=4784,1)) — это подзапрос, который возвращает 1, если условие 4784=4784 истинно. Функция ELT возвращает N-й элемент из списка; здесь список состоит из одного элемента 1. Фактически это заглушка, но в реальной атаке вместо 4784=4784 могло бы быть условие для извлечения данных, например, ASCII(SUBSTRING((SELECT password FROM users LIMIT 1),1,1)) > 100.
  • -- - — это комментарий, который отсекает оставшуюся часть исходного запроса, чтобы синтаксис был корректным.

Когда MySQL выполняет EXTRACTVALUE(4784, CONCAT(0x7e, (SELECT ...), 0x7e)), функция пытается интерпретировать второй аргумент как XPath. Поскольку ~1~ не является допустимым XPath, генерируется ошибка вида: XPATH syntax error: '~1~'. В этом сообщении и оказываются данные, которые злоумышленник пытается извлечь.

Зачем это нужно злоумышленнику?

Цель такой инъекции — получить информацию из базы данных, когда другие методы (например, UNION-based или blind SQL-инъекции) недоступны или неудобны. Error-based инъекция позволяет быстро извлекать данные посимвольно, если приложение выводит ошибки. В приведённом примере подзапрос возвращает просто 1, но в реальной атаке вместо этого может быть запрос к таблице с паролями, номерами карт или персональными данными.

Важно понимать, что подобные строки часто используются автоматическими сканерами уязвимостей (SQLmap, Burp Suite и др.) для проверки, уязвим ли сайт. Если в ответе сервера появляется ошибка с тильдами, сканер делает вывод, что инъекция возможна, и начинает эксплуатировать её дальше.

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

Основная причина успеха таких атак — недостаточная фильтрация пользовательского ввода и вывод ошибок СУБД на страницу. Вот ключевые меры защиты:

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

Пример работы в реальных условиях

Предположим, на сайте есть поиск по товарам, и запрос формируется так:

SELECT * FROM products WHERE name LIKE '%$search%'

Если пользователь введёт %') AND EXTRACTVALUE(4784,CONCAT(0x7e,((SELECT (ELT(4784=4784,1)))),0x7e))-- -, то итоговый запрос примет вид:

SELECT * FROM products WHERE name LIKE '%') AND EXTRACTVALUE(4784,CONCAT(0x7e,((SELECT (ELT(4784=4784,1)))),0x7e))-- -%'

База данных выполнит внедрённую часть и вернёт ошибку, если вывод ошибок включён. Злоумышленник увидит сообщение с тильдами и поймёт, что инъекция работает. Далее он может заменить ELT(4784=4784,1) на подзапрос, извлекающий, например, версию MySQL или имя текущей базы данных.

Распространённые мифы и заблуждения

  • Миф: Если сайт не выводит ошибки, то error-based инъекция невозможна. Реальность: Существуют blind-техники, основанные на времени или логических выражениях, которые работают и без вывода ошибок.
  • Миф: Достаточно экранировать кавычки. Реальность: В некоторых кодировках или при использовании определённых функций экранирование может быть обойдено. Надёжнее — параметризация.
  • Миф: SQL-инъекции — устаревшая проблема. Реальность: Они по-прежнему входят в топ-10 уязвимостей OWASP и активно эксплуатируются.

Заключение

Строка %') AND EXTRACTVALUE(4784,CONCAT(0x7e,((SELECT (ELT(4784=4784,1)))),0x7e))-- - — это не случайный набор символов, а тщательно сконструированный эксплойт для проверки и эксплуатации error-based SQL-инъекции в MySQL. Понимание принципов её работы помогает разработчикам и специалистам по безопасности лучше защищать веб-приложения. Если вы нашли подобную строку в логах своего сайта, это серьёзный повод провести аудит безопасности и убедиться, что все запросы к базе данных параметризованы, а вывод ошибок отключён.

Помните: безопасность — это процесс, а не однократное действие. Регулярно проверяйте свой код на уязвимости и следите за обновлениями безопасности.

Источники