Введение

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

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

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

Функция EXTRACTVALUE

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

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

Рассмотрим запрос ") AND EXTRACTVALUE(8202,CONCAT(0x7e,((SELECT (ELT(8202=8202,1)))),0x7e))-- - поэтапно.

  • ") — закрывает ранее открытую скобку и строковый литерал в уязвимом запросе. Это необходимо, чтобы внедряемый код стал частью SQL-выражения.
  • AND — логический оператор, присоединяющий наше условие к оригинальному запросу.
  • EXTRACTVALUE(8202, ...) — первый аргумент 8202 — это произвольное число, которое будет использоваться как XML-фрагмент. На самом деле важен второй аргумент.
  • CONCAT(0x7e, ((SELECT (ELT(8202=8202,1)))), 0x7e) — конкатенация тильды (0x7e), результата подзапроса и ещё одной тильды.
  • SELECT (ELT(8202=8202,1)) — подзапрос, возвращающий 1, если условие 8202=8202 истинно. ELT(N, str1, str2, ...) возвращает N-ю строку из списка. Здесь список состоит из одного элемента «1».
  • -- - — комментарий, который отсекает оставшуюся часть оригинального SQL-запроса.

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

Зачем это нужно атакующему?

Основная цель — получить данные из базы. Подставляя в ELT или вместо него другие подзапросы, злоумышленник может посимвольно извлекать информацию: имена таблиц, колонок, логины, пароли. Например, конструкция SELECT table_name FROM information_schema.tables LIMIT 0,1 позволит узнать первую таблицу в базе.

Подобные инъекции часто встречаются в задачах на CTF и в отчётах о пентестах. Они опасны тем, что не требуют вывода данных на экран — достаточно, чтобы ошибка отображалась в ответе сервера.

Пример эксплуатации

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

$query = "SELECT * FROM articles WHERE id = '$id'";

Если передать $id = '") AND EXTRACTVALUE(8202,CONCAT(0x7e,(SELECT database()),0x7e))-- -', то итоговый SQL станет:

SELECT * FROM articles WHERE id = '") AND EXTRACTVALUE(8202,CONCAT(0x7e,(SELECT database()),0x7e))-- -'

MySQL вернёт ошибку с именем текущей базы данных. Аналогично можно извлечь версию, пользователя и другие данные.

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

  1. Используйте подготовленные выражения (prepared statements). Это самый надёжный способ: параметры запроса передаются отдельно от SQL-кода и не интерпретируются как часть инструкции.
  2. Экранируйте специальные символы. Если prepared statements недоступны, применяйте функции экранирования, например mysqli_real_escape_string.
  3. Ограничьте права пользователя БД. Веб-приложение должно работать с минимально необходимыми привилегиями — обычно только SELECT, INSERT, UPDATE, DELETE для конкретных таблиц.
  4. Отключите вывод ошибок MySQL в production. Сообщения об ошибках не должны попадать в ответ сервера. Логируйте их, но не показывайте пользователю.
  5. Используйте WAF. Веб-application firewall может блокировать подозрительные конструкции, такие как EXTRACTVALUE или UPDATEXML.

Заключение

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

Источники