Введение

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

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

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

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

Разбор строки %"))) AND EXTRACTVALUE(9432,CONCAT(0x7e,((SELECT (ELT(9432=9432,1)))),0x7e))-- -

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

1. Начало: %")))

Символы %"))) — это попытка закрыть предыдущий SQL-запрос и внедрить свой код. Знак процента (%) часто используется в URL-кодировании, но здесь он может быть частью исходного запроса. Кавычка (") и закрывающие скобки ))) предназначены для того, чтобы «разорвать» оригинальный запрос и добавить условие AND. Например, если уязвимый запрос выглядит как SELECT * FROM users WHERE id = '$input', то подстановка %"))) AND ... может превратить его в SELECT * FROM users WHERE id = '%"))) AND ..., что приведёт к синтаксической ошибке, но с внедрённым кодом.

2. Оператор AND

Логический оператор AND используется для добавления дополнительного условия к запросу. В контексте инъекции он позволяет присоединить вызов функции EXTRACTVALUE к основному запросу.

3. Функция EXTRACTVALUE

EXTRACTVALUE(XML_document, XPath_expression) — это встроенная функция MySQL, предназначенная для извлечения значения из XML-документа по заданному XPath-выражению. Однако она имеет особенность: если XPath-выражение содержит недопустимые символы, MySQL генерирует ошибку, в тексте которой отображается переданное значение. Именно это свойство и эксплуатируется злоумышленниками.

В нашем случае первый аргумент — 9432 (произвольное число, часто используемое как идентификатор), а второй — CONCAT(0x7e,((SELECT (ELT(9432=9432,1)))),0x7e).

4. Функция CONCAT и шестнадцатеричные литералы

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

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

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

В данном примере ELT(9432=9432,1) — это упрощённая демонстрация. На практике вместо 1 указывается подзапрос, возвращающий конфиденциальную информацию.

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

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

Как работает атака целиком

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

SELECT * FROM products WHERE category = '$cat'

Злоумышленник передаёт в параметр cat строку %"))) AND EXTRACTVALUE(9432,CONCAT(0x7e,((SELECT (ELT(9432=9432,1)))),0x7e))-- -. После подстановки запрос принимает вид:

SELECT * FROM products WHERE category = '%"))) AND EXTRACTVALUE(9432,CONCAT(0x7e,((SELECT (ELT(9432=9432,1)))),0x7e))-- -'

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

Важно отметить, что в реальных атаках вместо 9432 и 1 могут быть другие числа и подзапросы, адаптированные под конкретную цель.

Последствия успешной SQL-инъекции

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

  • Утечка конфиденциальных данных (пароли, персональная информация, платёжные реквизиты).
  • Изменение или удаление данных в базе.
  • Получение доступа к другим системам через базу данных.
  • Отказ в обслуживании (DoS) путём выполнения ресурсоёмких запросов.

Именно поэтому важно своевременно обнаруживать и устранять такие уязвимости.

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

Существует несколько эффективных мер защиты:

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

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

Заключение

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

Помните: безопасность — это процесс, а не одноразовое действие. Регулярно обновляйте свои знания и инструменты, чтобы противостоять современным угрозам.

Источники