Введение

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

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

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

Существует несколько техник эксплуатации: UNION-based, blind (слепая), time-based и error-based. Наш запрос относится к последней — error-based SQLi, при которой атакующий заставляет СУБД выдать сообщение об ошибке, содержащее полезную информацию.

Разбор конструкции EXTRACTVALUE

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

Синтаксис: EXTRACTVALUE(4245, CONCAT(0x7e, ((SELECT (ELT(4245=4245,1)))), 0x7e)).

  • 4245 — произвольное число, играющее роль XML-фрагмента. Может быть любым, главное — чтобы функция вызвалась.
  • CONCAT(0x7e, ..., 0x7e) — конкатенация символа тильды (~, код 0x7e) с результатом подзапроса и ещё одной тильдой. Тильда используется как маркер, чтобы в сообщении об ошибке легко было найти внедрённые данные.
  • (SELECT (ELT(4245=4245,1))) — подзапрос, возвращающий значение. ELT(N, str1, str2, ...) возвращает N-ю строку из списка. Здесь 4245=4245 — всегда истина (1), поэтому ELT(1, 1) вернёт 1. В реальной атаке вместо этой заглушки подставляется подзапрос, извлекающий данные (например, имя пользователя, хэш пароля, название таблицы).
  • ) AND ... -- - — закрывающая скобка и логический оператор AND, внедряемые в оригинальный SQL-запрос. Двойной дефис с пробелом (-- -) — комментарий в MySQL, который отсекает оставшуюся часть исходного запроса.

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

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

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

SELECT * FROM users WHERE id = 'ПОЛЬЗОВАТЕЛЬСКИЙ_ВВОД';

Атакующий подставляет вместо ввода:

1') AND EXTRACTVALUE(4245,CONCAT(0x7e,((SELECT version())),0x7e))-- -

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

SELECT * FROM users WHERE id = '1') AND EXTRACTVALUE(4245,CONCAT(0x7e,((SELECT version())),0x7e))-- -';

СУБД выполнит подзапрос SELECT version(), получит, например, 8.0.32, сформирует XPath-выражение ~8.0.32~, и EXTRACTVALUE выдаст ошибку: XPATH syntax error: '~8.0.32~'. Атакующий увидит версию MySQL в ответе сервера.

Аналогично можно извлечь имена таблиц, колонок, логины, пароли — всё, что позволяет синтаксис подзапроса. Для этого достаточно заменить version() на другой запрос, например:

(SELECT table_name FROM information_schema.tables WHERE table_schema=database() LIMIT 0,1)

Опасность и последствия

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

  • Полному раскрытию структуры базы данных.
  • Краже конфиденциальной информации (персональные данные, пароли, платёжные реквизиты).
  • Обходу аутентификации и повышению привилегий.
  • Изменению или удалению данных.
  • В некоторых случаях — выполнению произвольных команд на сервере (при наличии соответствующих прав).

Важно отметить, что для эксплуатации не требуется глубоких знаний: существует множество автоматизированных инструментов (sqlmap, jSQL Injection и др.), которые сами подбирают нужные конструкции.

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

Основной метод защиты — использование параметризованных запросов (prepared statements). Они разделяют код SQL и данные, поэтому внедрённые конструкции не интерпретируются как часть запроса. Пример на PHP с PDO:

$stmt = $pdo->prepare('SELECT * FROM users WHERE id = :id');
$stmt->execute(['id' => $userId]);

Дополнительные меры:

  1. Валидация и фильтрация всех входных данных (белые списки, приведение типов).
  2. Экранирование специальных символов, если параметризация невозможна (например, mysqli_real_escape_string).
  3. Ограничение прав пользователя базы данных: не давайте приложению прав на чтение information_schema или выполнение опасных функций.
  4. Отключение вывода подробных ошибок СУБД в production-окружении (display_errors = off).
  5. Использование WAF (Web Application Firewall) для блокировки подозрительных запросов.
  6. Регулярное обновление СУБД и фреймворков.

Заключение

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

Источники