Что это за строка?

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

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

Закрывающая скобка )

Символ ) пытается закрыть ранее открытую скобку в исходном запросе. Это нужно, чтобы «разорвать» легитимную конструкцию и добавить свою логику. Например, если уязвимый параметр подставляется в условие WHERE id = (SELECT ...), закрывающая скобка позволяет выйти за пределы подзапроса.

Оператор OR

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

Функция EXTRACTVALUE()

EXTRACTVALUE(XML_document, XPath_expression) — встроенная функция MySQL, предназначенная для извлечения значения из XML-документа по XPath-выражению. Однако при некорректном XPath она генерирует ошибку, текст которой содержит переданные данные. Злоумышленники эксплуатируют это: если передать в качестве XPath строку, содержащую результат подзапроса, СУБД вернёт ошибку с этим результатом. Таким образом, функция становится каналом для «слепого» вывода данных.

Конкатенация CONCAT(0x7e, ... ,0x7e)

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

Подзапрос (SELECT (ELT(7731=7731,1)))

ELT(N, str1, str2, ...) возвращает строку по её номеру. Выражение 7731=7731 всегда истинно (возвращает 1), поэтому ELT(1,1) вернёт строку '1'. В реальных атаках на месте этого условия может быть проверка данных, например, SUBSTRING((SELECT password FROM users LIMIT 1),1,1)='a'. Если условие истинно, ELT вернёт 1, и ошибка будет содержать ~1~; если ложно — ELT вернёт NULL или произойдёт другая ошибка. Так злоумышленник может побитово или посимвольно извлекать информацию.

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

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

Как это работает в атаке

Предположим, уязвимый запрос выглядит так: SELECT * FROM articles WHERE id = ('$input'). Если передать $input = ') OR EXTRACTVALUE(7731,CONCAT(0x7e,((SELECT (ELT(7731=7731,1)))),0x7e))-- -, то после подстановки получится:

SELECT * FROM articles WHERE id = (') OR EXTRACTVALUE(7731,CONCAT(0x7e,((SELECT (ELT(7731=7731,1)))),0x7e))-- -')

Закрывающая скобка и OR добавляют новое условие. Функция EXTRACTVALUE вызывает ошибку, так как второй аргумент не является корректным XPath. В тексте ошибки MySQL отобразит переданное значение, например: XPATH syntax error: '~1~'. По этому сообщению атакующий понимает, что условие истинно, и может продолжить извлечение данных.

Цели и последствия

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

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

  • Параметризованные запросы (prepared statements): главный способ предотвращения SQL-инъекций. Они разделяют код и данные, поэтому ввод пользователя никогда не интерпретируется как SQL-код.
  • Экранирование специальных символов: используйте функции экранирования, предоставляемые драйвером БД, но не полагайтесь только на них.
  • Отключение вывода ошибок БД в production: сообщения об ошибках не должны попадать к конечному пользователю. Логируйте их, но показывайте общее сообщение.
  • Принцип наименьших привилегий: учётная запись, используемая приложением для подключения к БД, должна иметь только необходимые права.
  • Регулярное обновление СУБД и фреймворков: закрывайте известные уязвимости.
  • Использование WAF: веб-application firewall может блокировать подозрительные payload, но не заменяет исправление кода.

Заключение

Рассмотренная строка — типичный пример error-based SQL-инъекции для MySQL, эксплуатирующей функцию EXTRACTVALUE и маркеры ~ для извлечения данных через сообщения об ошибках. Понимание механики таких атак помогает разработчикам и администраторам правильно выстраивать защиту: использовать параметризованные запросы, скрывать ошибки БД и следовать лучшим практикам безопасности.

Источники