Введение

В запросе пользователя указана строка: ")))) AND EXTRACTVALUE(8659,CONCAT(0x7e,((SELECT (ELT(8659=8659,1)))),0x7e))-- -. Это типичный пример попытки эксплуатации уязвимости SQL-инъекции типа error-based. В данной статье мы разберём, что означает каждый элемент этой конструкции, как она работает и какие меры защиты существуют.

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

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

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

Разбор конструкции EXTRACTVALUE

Функция EXTRACTVALUE() в MySQL (и MariaDB) предназначена для извлечения значения из XML-строки по заданному XPath-выражению. Синтаксис: EXTRACTVALUE(XML_frag, XPath_expr). Если XML-фрагмент не является корректным XML, функция генерирует ошибку. Именно это свойство и используется в error-based инъекциях.

В нашем примере: EXTRACTVALUE(8659, CONCAT(0x7e, (SELECT (ELT(8659=8659,1))), 0x7e)). Первый аргумент — число 8659, которое не является XML-документом, поэтому функция гарантированно вызовет ошибку. Второй аргумент — это XPath-выражение, которое формируется динамически с помощью CONCAT.

Функция CONCAT

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

Функция ELT и подзапрос

ELT(N, str1, str2, ...) возвращает N-ю строку из списка. В примере ELT(8659=8659, 1) — условие 8659=8659 всегда истинно, поэтому возвращается 1 (первый элемент). Если бы условие было ложным, вернулось бы NULL. Это простейший пример, демонстрирующий технику. В реальных атаках вместо 8659=8659 может стоять условие, проверяющее, например, первый символ имени пользователя.

Подзапрос (SELECT (ELT(...))) возвращает результат в CONCAT. Затем EXTRACTVALUE пытается разобрать полученную строку как XPath. Поскольку строка содержит символы, недопустимые в XPath (например, ~), возникает ошибка, в тексте которой будет отображено переданное значение. Так злоумышленник может извлечь данные из базы.

Комментарий в конце

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

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

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

Как защититься?

Основной способ защиты от SQL-инъекций — использование параметризованных запросов (prepared statements). В этом случае пользовательский ввод передаётся отдельно от SQL-кода и не может изменить структуру запроса.

  • Параметризация запросов — самый надёжный метод.
  • Экранирование специальных символов — менее надёжно, но может использоваться в legacy-коде.
  • Валидация входных данных — проверка типов, длины, допустимых символов.
  • Ограничение прав пользователя БД — не давайте приложению лишних привилегий.
  • Скрытие сообщений об ошибках — не показывайте пользователю детали ошибок БД.
  • Использование WAF — веб-приложения firewall могут блокировать известные атаки.

Также рекомендуется регулярно обновлять СУБД и фреймворки, проводить аудит кода и использовать сканеры уязвимостей.

Заключение

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

Источники