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

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

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

Разбор составляющих запроса

1. Начальный апостроф и AND

Символ ' (одинарная кавычка) используется для разрыва строкового литерала в оригинальном SQL-запросе. После него добавляется AND — логический оператор, который позволяет присоединить дополнительное условие. Если исходный запрос был, например, SELECT * FROM users WHERE id = '1', то после подстановки получается SELECT * FROM users WHERE id = '1' AND EXTRACTVALUE(...).

2. Функция EXTRACTVALUE

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

3. CONCAT и 0x7e

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

4. SELECT (ELT(6190=6190,1))

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

5. Завершение -- -

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

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

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

SELECT * FROM articles WHERE id = '$_GET[id]'

Злоумышленник передаёт в id строку:

1' AND EXTRACTVALUE(6190,CONCAT(0x7e,((SELECT (ELT(6190=6190,1)))),0x7e))-- -

Итоговый запрос принимает вид:

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

MySQL выполняет функцию EXTRACTVALUE, которая пытается разобрать XPath-выражение ~1~. Поскольку это невалидный XPath, возникает ошибка:

XPATH syntax error: '~1~'

Эта ошибка возвращается в ответе сервера, и атакующий видит результат выполнения подзапроса. Заменив 1 на (SELECT password FROM users LIMIT 1), можно извлечь пароли пользователей.

Цели и опасность

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

Опасность заключается в том, что подобные атаки могут быть автоматизированы. Существуют инструменты (например, sqlmap), которые автоматически подбирают нужные функции и извлекают данные. Строка с EXTRACTVALUE — один из многих шаблонов, используемых такими инструментами.

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

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

  • Использовать подготовленные выражения (prepared statements) с параметризацией запросов. Это самый надёжный способ, так как данные не попадают в тело SQL-запроса.
  • Экранировать специальные символы при невозможности использовать подготовленные выражения. Однако экранирование не всегда спасает, если допущены ошибки в кодировке.
  • Отключить вывод ошибок СУБД в production-окружении. Ошибки должны логироваться, но не отображаться пользователю.
  • Ограничить права пользователя базы данных, от имени которого работает приложение. Не давайте ему доступ к системным таблицам и лишним базам.
  • Регулярно обновлять MySQL. В версии 8.0 функции EXTRACTVALUE и UPDATEXML были удалены, что делает такие инъекции неработоспособными.
  • Использовать WAF (Web Application Firewall) для фильтрации подозрительных запросов, хотя это не заменяет исправление уязвимостей.

Заключение

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

Источники