Введение

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

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

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

Существует несколько разновидностей SQL-инъекций: основанные на ошибках (error-based), на времени (time-based), на логических выражениях (boolean-based), а также UNION-инъекции. Рассматриваемая строка относится к error-based инъекциям, так как её цель — заставить базу данных вернуть данные в тексте сообщения об ошибке.

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

Давайте последовательно разберём каждый элемент запроса.

1. Последовательность скобок и апострофов: '))))

Эти символы используются для «закрытия» исходного SQL-запроса, в который внедряется код. В зависимости от контекста (например, запрос вида SELECT * FROM users WHERE id = ('...')), злоумышленник подбирает количество скобок и кавычек, чтобы корректно завершить оригинальное выражение и добавить своё. Четыре закрывающие скобки и апострофы могут соответствовать вложенным функциям или условиям в уязвимом запросе.

2. Оператор AND

Логический оператор AND используется для объединения условий. В данном случае он позволяет добавить новое выражение к оригинальному запросу, не нарушая его синтаксис. Если исходный запрос возвращал истину, то после добавления AND с внедрённой функцией результат может измениться, что и наблюдает атакующий.

3. Функция EXTRACTVALUE(2457, CONCAT(...))

EXTRACTVALUE — это функция в MySQL (и некоторых других СУБД), предназначенная для извлечения значения из XML-документа. Она принимает два аргумента: XML-строку и XPath-выражение. Однако в контексте SQL-инъекций эта функция используется иначе: если второй аргумент содержит некорректный XPath, база данных генерирует ошибку, в тексте которой отображается переданное значение. Это позволяет злоумышленнику получить данные, которые в обычной ситуации не выводятся.

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

4. Функция CONCAT и hex-маркеры 0x7e

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

5. Подзапрос (SELECT (ELT(2457=2457,1)))

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

Таким образом, подзапрос возвращает 1, и итоговая строка для EXTRACTVALUE выглядит как ~1~. При попытке обработать её как XPath возникает ошибка, в тексте которой появляется ~1~. Атакующий, анализируя ответ сервера, понимает, что инъекция сработала.

6. Комментарий -- -

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

Как работает error-based инъекция?

Механизм прост: злоумышленник формирует запрос таким образом, чтобы база данных вернула ошибку, содержащую полезные данные. В случае с EXTRACTVALUE и аналогичной функцией UPDATEXML ошибка возникает из-за некорректного XPath-выражения. СУБД включает в сообщение об ошибке переданную строку, что и позволяет извлечь информацию.

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

Зачем злоумышленнику такая сложная конструкция?

На первый взгляд, строка кажется избыточной: зачем использовать ELT с заведомо истинным условием, если можно просто передать число? Дело в том, что это тестовый payload. Он позволяет проверить, уязвимо ли приложение, без риска получить ошибку синтаксиса. Если сервер возвращает ошибку с символом ~, значит, инъекция возможна. В дальнейшем атакующий заменит ELT(2457=2457,1) на подзапрос, извлекающий реальные данные (например, имена таблиц, пароли пользователей).

Кроме того, использование ELT и CONCAT с hex-маркерами — это типичный приём, встречающийся в автоматизированных инструментах (sqlmap) и публичных эксплойтах. Он позволяет обходить некоторые фильтры, так как не содержит явных ключевых слов вроде SELECT в чистом виде (хотя здесь SELECT присутствует).

Последствия успешной атаки

Если злоумышленнику удаётся эксплуатировать уязвимость, он может:

  • Получить доступ к конфиденциальным данным (логины, пароли, персональные данные, платёжная информация).
  • Изменять или удалять записи в базе данных.
  • Выполнять административные операции, если уязвимый аккаунт базы данных обладает высокими привилегиями.
  • Использовать сервер для дальнейших атак (например, через LOAD_FILE или INTO OUTFILE).

Поэтому так важно уделять внимание безопасности веб-приложений и баз данных.

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

Основные меры защиты хорошо известны и описаны в рекомендациях OWASP:

  1. Параметризованные запросы (prepared statements). Это самый надёжный способ: SQL-код и данные передаются раздельно, поэтому внедрение невозможно.
  2. Экранирование специальных символов. Если по каким-то причинам нельзя использовать параметризацию, необходимо экранировать все пользовательские данные с помощью функций СУБД (например, mysql_real_escape_string).
  3. Валидация и фильтрация ввода. Проверяйте типы данных, ограничивайте длину, используйте белые списки допустимых символов.
  4. Принцип минимальных привилегий. Учётная запись, от имени которой работает приложение, должна иметь только необходимые права. Не используйте root для веб-приложений.
  5. Отключение вывода ошибок СУБД. Сообщения об ошибках должны логироваться, но не отображаться пользователю.
  6. Регулярное обновление и аудит. Следите за обновлениями СУБД и фреймворков, проводите сканирование уязвимостей.

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

Заключение

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

Источники