Введение

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

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

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

Основные функции, используемые в атаке

  • EXTRACTVALUE(XML_frag, XPath_expr) — функция MySQL для извлечения значения из XML-фрагмента по XPath-выражению. Если XPath-выражение содержит недопустимые символы, MySQL генерирует ошибку, включающую эти символы.
  • CONCAT(str1, str2, ...) — объединяет строки. В контексте инъекции используется для формирования строки, которая попадёт в сообщение об ошибке.
  • ELT(N, str1, str2, ...) — возвращает N-ю строку из списка. Если N=1, возвращается первая строка. В примере ELT(4456=4456,1) условие 4456=4456 всегда истинно (1), поэтому возвращается строка '1'.
  • SELECT — подзапрос, который может быть заменён на любой другой запрос для извлечения данных из базы.
  • -- - — комментарий, который отсекает оставшуюся часть оригинального SQL-запроса, чтобы не нарушать синтаксис.

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

Давайте разберём эту строку по частям.

1. Начальные символы ')))

Эти символы, скорее всего, являются закрывающими скобками и кавычкой из оригинального запроса, который внедряется. Например, если уязвимый запрос выглядит как SELECT * FROM users WHERE id = ('$input'), то злоумышленник подставляет ')) ) AND ..., чтобы закрыть кавычку и скобки, а затем добавить своё условие. Точное количество скобок зависит от контекста, но в данном случае три закрывающие скобки и одна кавычка — это попытка «выровнять» синтаксис.

2. AND EXTRACTVALUE(4456, CONCAT(0x7e, ((SELECT (ELT(4456=4456,1)))), 0x7e))

Это ядро инъекции. Рассмотрим по порядку:

  • 4456 — первый аргумент EXTRACTVALUE. Это может быть произвольное число, которое не влияет на результат, так как первый аргумент должен быть XML-строкой. Однако MySQL ожидает строку, и если передать число, оно будет преобразовано. Но главное — второй аргумент.
  • CONCAT(0x7e, ((SELECT (ELT(4456=4456,1)))), 0x7e) — второй аргумент EXTRACTVALUE, который должен быть XPath-выражением. Здесь 0x7e — это шестнадцатеричное представление символа тильды (~). CONCAT объединяет тильду, результат подзапроса и снова тильду. Подзапрос SELECT (ELT(4456=4456,1)) возвращает '1', так как условие истинно. Таким образом, XPath-выражение становится ~1~.

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

3. -- -

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

Как это работает на практике

Предположим, уязвимый запрос: SELECT * FROM articles WHERE id = '1'. Злоумышленник подставляет вместо 1 строку '))) AND EXTRACTVALUE(4456,CONCAT(0x7e,((SELECT (ELT(4456=4456,1)))),0x7e))-- -. Итоговый запрос:

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

После закрытия кавычки и скобок (если они были) добавляется условие AND EXTRACTVALUE(...). Поскольку EXTRACTVALUE вызывает ошибку, запрос не выполняется, но в ответе сервера (или в логах) появляется сообщение об ошибке, содержащее результат подзапроса. В нашем случае это '1'.

Злоумышленник может заменить ELT(4456=4456,1) на любой другой подзапрос, например, (SELECT version()) или (SELECT password FROM users LIMIT 1), чтобы извлечь конфиденциальные данные. Например:

AND EXTRACTVALUE(4456,CONCAT(0x7e,(SELECT version()),0x7e))

Тогда ошибка будет содержать версию MySQL.

Меры защиты

Чтобы предотвратить такие атаки, необходимо:

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

Заключение

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

Источники