Введение

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

Что такое error-based SQL-инъекция?

SQL-инъекция — это один из самых распространённых способов взлома веб-приложений. Злоумышленник внедряет свой SQL-код в запрос, который выполняет сервер базы данных. При error-based инъекции атакующий заставляет СУБД выдать сообщение об ошибке, содержащее полезные данные (например, версию MySQL, имя базы, логин пользователя).

В MySQL для этого часто используют функции EXTRACTVALUE() и UPDATEXML(). Они предназначены для работы с XML, но при некорректных аргументах возвращают ошибку, в текст которой можно «вклеить» результат подзапроса.

Разбор запроса по частям

Рассмотрим наш запрос детально:

')) AND EXTRACTVALUE(7001,CONCAT(0x7e,((SELECT (ELT(7001=7001,1)))),0x7e))-- -
  1. ')) — закрывает ранее открытые скобки и кавычки в уязвимом параметре. Это позволяет внедрить собственный SQL-код.
  2. AND — логический оператор, который добавляет условие к исходному запросу.
  3. EXTRACTVALUE(7001, ...) — функция MySQL для извлечения значения из XML-строки. Первый аргумент — XML-документ (здесь просто число 7001, что уже некорректно), второй — XPath-выражение.
  4. CONCAT(0x7e, ((SELECT (ELT(7001=7001,1)))), 0x7e) — конкатенация тильды (0x7e — это символ ~), результата подзапроса и ещё одной тильды. Тильды служат маркерами, чтобы потом легко найти данные в сообщении об ошибке.
  5. SELECT (ELT(7001=7001,1)) — подзапрос, который возвращает 1, если 7001=7001 (всегда истина). Функция ELT(N, str1, str2, ...) возвращает N-ю строку из списка. Здесь список состоит из одного элемента 1, поэтому возвращается 1. Это простейший пример; на практике вместо 1 подставляют подзапрос, извлекающий нужные данные (например, имя базы).
  6. -- - — комментарий, который отсекает оставшуюся часть оригинального SQL-запроса.

В результате MySQL пытается выполнить EXTRACTVALUE с некорректным XPath (потому что CONCAT возвращает строку, не являющуюся валидным XPath), и выдаёт ошибку вида: XPATH syntax error: '~1~'. В этом сообщении и оказываются данные, которые злоумышленник пытается извлечь.

Зачем нужны ELT и CONCAT?

Функция ELT() часто используется в error-based инъекциях для извлечения конкретных значений. Например, чтобы получить имя текущей базы данных, можно подставить:

ELT(1, database())

Тогда CONCAT сформирует строку ~имя_базы~, и она появится в ошибке. В нашем примере ELT(7001=7001,1) — это упрощённый тестовый вариант, который просто возвращает 1. Он используется для проверки уязвимости: если ошибка появляется, значит, инъекция возможна.

CONCAT собирает все части в одну строку. Символ 0x7e (тильда) выбран потому, что он редко встречается в обычных данных и легко заметен в сообщении об ошибке.

Как эксплуатируют такие инъекции?

После подтверждения уязвимости злоумышленник может извлекать любые данные: версию MySQL, имена таблиц и колонок, логины и пароли пользователей. Например, для получения версии СУБД используют:

AND EXTRACTVALUE(1, CONCAT(0x7e, (SELECT version()), 0x7e))

Для перебора данных применяют LIMIT и OFFSET. Так, чтобы получить имя второй таблицы, меняют limit 0,1 на 1,1 и так далее.

Важно понимать: error-based инъекции работают только тогда, когда веб-приложение выводит сообщения об ошибках базы данных пользователю. Если ошибки скрыты, злоумышленник может использовать blind-инъекции (например, через time-based или boolean-based техники).

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

Основные меры защиты:

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

Также рекомендуется проводить аудит кода и тестирование на проникновение, чтобы выявлять уязвимости до того, как ими воспользуются злоумышленники.

Заключение

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

Источники