Введение

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

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

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

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

Разбор пейлоада по частям

Рассмотрим каждый элемент запроса:

  • ' — одинарная кавычка, закрывающая строковый литерал в уязвимом запросе. Это позволяет выйти за пределы исходного значения и добавить собственный SQL-код.
  • OR — логический оператор, который делает условие всегда истинным (если хотя бы одна часть верна). В данном случае используется для того, чтобы запрос выполнился, даже если исходное условие ложно.
  • EXTRACTVALUE(8370, CONCAT(...)) — функция MySQL, извлекающая значение из XML-документа. Первый аргумент — XML-строка (здесь число 8370, которое будет преобразовано в строку), второй — XPath-выражение. Если XPath-выражение некорректно, генерируется ошибка, содержащая это выражение.
  • CONCAT(0x7e, ((SELECT (ELT(8370=8370,1)))), 0x7e) — конкатенация трёх частей: символа тильды (0x7e в шестнадцатеричном виде), результата подзапроса и ещё одной тильды. Тильда используется как разделитель, чтобы облегчить извлечение данных из сообщения об ошибке.
  • SELECT (ELT(8370=8370,1)) — подзапрос, возвращающий результат функции ELT. ELT(N, str1, str2, ...) возвращает N-ю строку из списка. Здесь 8370=8370 — всегда истинное условие (1), поэтому ELT(1, 1) вернёт строку '1'. В реальной атаке вместо этого подзапроса мог бы быть, например, SELECT password FROM users LIMIT 1.
  • -- - — комментарий, который обрезает оставшуюся часть исходного запроса. Пробел после -- обязателен в MySQL, а дефис добавлен для надёжности.

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

Зачем нужен ELT и условие 8370=8370

Функция ELT используется для управления логикой: если условие истинно, возвращается первый элемент списка, иначе — NULL. В простейшем случае 8370=8370 всегда истинно, поэтому возвращается '1'. Это демонстрационный пейлоад, который показывает работоспособность инъекции. В реальной атаке злоумышленник заменил бы этот подзапрос на извлечение конкретных данных, например:
EXTRACTVALUE(8370,CONCAT(0x7e,(SELECT username FROM users LIMIT 1),0x7e))

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

Как эксплуатируется уязвимость

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

  1. Злоумышленник находит параметр, который попадает в SQL-запрос (например, ?id=1).
  2. Подставляет пейлоад вместо ожидаемого значения.
  3. Сервер выполняет запрос, возникает ошибка, и её текст возвращается в ответе.
  4. Атакующий анализирует сообщение и постепенно извлекает данные (имена таблиц, столбцов, содержимое).

Важно отметить, что error-based инъекции работают только при включённом выводе ошибок. В production-окружениях ошибки БД часто скрываются, что затрудняет атаку, но не делает её невозможной (существуют другие техники, например, blind SQLi).

Меры защиты

Чтобы предотвратить подобные атаки, необходимо:

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

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

Заключение

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

Источники