Введение

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

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

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

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

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

Рассмотрим анализируемую конструкцию по элементам:

  • ')))) — последовательность закрывающих скобок и кавычек. Она нужна, чтобы «закрыть» оригинальный запрос приложения и выйти за его пределы. Количество скобок подбирается экспериментально в зависимости от структуры уязвимого запроса.
  • AND — логический оператор, добавляющий условие к запросу. Внедряемая часть выполняется только если предыдущее выражение истинно.
  • EXTRACTVALUE(1428, CONCAT(0x7e, ((SELECT (ELT(1428=1428,1)))), 0x7e)) — вызов функции извлечения значения из XML. Первый аргумент — произвольное число (1428), второй — XPath-выражение, сформированное динамически.
  • CONCAT(0x7e, ..., 0x7e) — объединение строк. 0x7e — шестнадцатеричный код символа «~» (тильда). Тильда добавляется в начало и конец, чтобы XPath-выражение стало синтаксически некорректным и гарантированно вызвало ошибку.
  • ((SELECT (ELT(1428=1428,1))) — подзапрос, возвращающий результат функции ELT(). ELT(N, str1, str2, ...) возвращает N-ю строку из списка. Здесь 1428=1428 — всегда истинное условие, поэтому ELT(1,1) вернёт «1». В реальной атаке вместо «1» мог бы быть, например, номер версии MySQL или имя пользователя, полученные через другой подзапрос.
  • -- - — комментарий в SQL. Всё, что идёт после него, игнорируется. Это нужно, чтобы «отрезать» оставшуюся часть оригинального запроса и избежать синтаксической ошибки.

В результате выполнения такого запроса MySQL попытается вычислить XPath-выражение, начинающееся с символа «~», что недопустимо. Возникнет ошибка вида: XPATH syntax error: '~1~'. В сообщении об ошибке отобразится результат подзапроса — в нашем случае «1». Если бы подзапрос возвращал, например, @@version, в ошибке появилась бы версия СУБД.

Зачем нужна функция ELT

ELT() в MySQL возвращает строку по её номеру из списка аргументов. В контексте инъекции она используется для преобразования результата логического сравнения в число. Конструкция ELT(1428=1428,1) возвращает «1», потому что условие истинно. Если бы условие было ложным, ELT(0,1) вернул бы NULL. Это позволяет строить запросы, зависящие от условий, и извлекать данные побитно или посимвольно. В более сложных атаках вместо простого сравнения подставляются подзапросы, возвращающие символы из интересующих таблиц.

Как злоумышленники используют такие строки

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

Важно понимать: рассматриваемая строка сама по себе не является вирусом или вредоносной программой. Это лишь попытка эксплуатации уязвимости. Если ваше приложение вернуло такую ошибку или в логах появилась подобная запись, значит, кто-то пытался проверить систему на наличие SQL-инъекции. Необходимо срочно проверить безопасность кода и настроек сервера.

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

Основная рекомендация — использовать параметризованные запросы (prepared statements) и хранимые процедуры. Они разделяют код SQL и данные, поэтому внедрённые символы не могут изменить структуру запроса. Дополнительные меры:

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

Соблюдение этих правил сводит риск успешной SQL-инъекции к минимуму.

Заключение

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

Источники