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

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

В данном конкретном примере внедряется функция EXTRACTVALUE, которая в MySQL предназначена для работы с XML-данными. Однако из-за особенностей обработки ошибок её можно использовать для получения данных из базы. Число 8237 в вызове функции — это произвольный идентификатор, который может меняться в разных вариантах эксплойта (например, 8635, 2711).

Как работает этот эксплойт?

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

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

Внутри CONCAT выполняется подзапрос SELECT (ELT(8237=8237,1)). Функция ELT возвращает N-й элемент из списка. Здесь условие 8237=8237 всегда истинно, поэтому ELT вернёт 1. Это простейший случай, но в реальных атаках вместо 1 может быть подставлен другой запрос, например, (SELECT password FROM users LIMIT 1).

Зачем нужны 0x7e и EXTRACTVALUE?

Функция EXTRACTVALUE в MySQL при некорректном XML-документе генерирует ошибку, в тексте которой отображается переданная строка. Если в строке есть символы, недопустимые для XML (например, тильда ~), MySQL выдаст сообщение вида: XPATH syntax error: '~1~'. Именно это и нужно атакующему: в сообщении об ошибке он увидит результат выполнения подзапроса, обёрнутый в тильды.

Символ 0x7e — это шестнадцатеричное представление тильды. Тильда выбрана потому, что она редко встречается в обычных данных и легко заметна в выводе ошибки. Таким образом, злоумышленник может извлечь любые данные: версию СУБД, имена таблиц, логины и пароли пользователей.

Важно: этот метод работает только в том случае, если веб-приложение выводит сообщения об ошибках базы данных на страницу. В противном случае атака не даст результата.

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

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

SELECT * FROM articles WHERE title LIKE '%' + user_input + '%'

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

SELECT * FROM articles WHERE title LIKE '%%'))) AND EXTRACTVALUE(8237,CONCAT(0x7e,((SELECT (ELT(8237=8237,1)))),0x7e))-- -%'

СУБД выполнит внедрённую часть, и в случае ошибки выведет сообщение, содержащее результат подзапроса. В нашем примере это будет ~1~. В более сложных атаках вместо 1 подставляются имена таблиц и полей.

Чем опасны такие инъекции?

Error-based SQL-инъекции позволяют злоумышленнику:

  • получить доступ к конфиденциальным данным (пароли, персональные данные, номера кредитных карт);
  • изменить или удалить информацию в базе;
  • выполнить произвольные команды на сервере (в некоторых конфигурациях);
  • получить полный контроль над приложением.

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

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

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

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

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

Заключение

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

Источники