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

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

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

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

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

Рассмотрим каждый фрагмент запроса подробно.

1. Обратная кавычка и закрывающая скобка: `)`

Этот фрагмент используется для завершения оригинального SQL-запроса, в который внедряется инъекция. Обратная кавычка (`) закрывает идентификатор (например, имя столбца или таблицы), а закрывающая скобка ) — открытую ранее функцию или подзапрос. Таким образом, атакующий «выравнивает» синтаксис, чтобы его код был корректно воспринят парсером SQL.

2. Логический оператор AND

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

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

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

В контексте SQL-инъекции EXTRACTVALUE используется для генерации ошибки, содержащей результат подзапроса. Если XPath-выражение некорректно, MySQL выдаёт сообщение об ошибке, в которое подставляется вычисленное значение.

4. Аргументы EXTRACTVALUE: 9716 и CONCAT(...)

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

5. CONCAT и шестнадцатеричные литералы 0x7e

CONCAT() объединяет строки. 0x7e — это шестнадцатеричное представление символа тильды (~). Тильда используется как разделитель, чтобы облегчить извлечение данных из сообщения об ошибке. Например, ошибка может выглядеть так: XPATH syntax error: '~1~'.

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

ELT() — функция MySQL, возвращающая N-й элемент из списка строк. Синтаксис: ELT(N, str1, str2, ...). В данном случае ELT(9716=9716,1) возвращает 1, потому что условие 9716=9716 истинно (равно 1). Это простейший пример: атакующий мог бы заменить 1 на любой другой запрос, например, (SELECT password FROM users LIMIT 1), чтобы извлечь пароли.

Весь подзапрос (SELECT (ELT(...))) возвращает результат, который затем передаётся в CONCAT.

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

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

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

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

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

После подстановки инъекции запрос преобразуется в:

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

MySQL выполняет функцию EXTRACTVALUE с некорректным XPath (потому что CONCAT возвращает строку, не являющуюся валидным XPath). Возникает ошибка вида:

XPATH syntax error: '~1~'

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

Чем опасна такая инъекция?

  • Утечка конфиденциальных данных: злоумышленник может прочитать всю базу, включая персональные данные пользователей.
  • Обход аутентификации: с помощью инъекции можно войти в систему под администратором без пароля.
  • Модификация и удаление данных: в некоторых случаях возможны команды UPDATE или DELETE.
  • Полный контроль над сервером: при определённых конфигурациях возможна загрузка файлов и выполнение команд ОС.

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

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

Заключение

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

Источники