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

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

Как работает payload

Разберём по частям:

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

Почему возникает ошибка?

Функция EXTRACTVALUE() ожидает, что второй аргумент будет корректным XPath-выражением. Строка, начинающаяся с тильды (~), не является валидным XPath, поэтому MySQL генерирует ошибку вида: XPATH syntax error: '~1~'. В этом сообщении и оказывается результат подзапроса — в данном случае '1'. Злоумышленник может заменить ELT(4154=4154,1) на любой другой подзапрос, например (SELECT version()), чтобы извлечь версию СУБД, или (SELECT password FROM users LIMIT 1) для кражи хешей паролей.

Зачем нужны 0x7e и ELT?

Символ ~ (0x7e) служит маркером начала и конца выводимых данных. Это помогает атакующему легко найти результат в тексте ошибки, особенно если сервер добавляет собственные сообщения. Функция ELT() в данном примере — простейший способ вернуть заранее известное значение (1), чтобы проверить работоспособность инъекции. В реальных атаках вместо неё подставляют подзапросы, извлекающие конфиденциальную информацию.

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

Основная причина уязвимости — передача пользовательских данных в SQL-запрос без должной обработки. Вот ключевые меры защиты:

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

Пример уязвимого кода

Рассмотрим фрагмент на PHP, который может привести к такой инъекции:

$id = $_GET['id'];
$query = "SELECT * FROM products WHERE category = ('$id')";
$result = mysqli_query($conn, $query);

Если пользователь передаст в параметр id значение ') AND EXTRACTVALUE(4154,CONCAT(0x7e,((SELECT (ELT(4154=4154,1)))),0x7e))-- -, то итоговый запрос станет таким:

SELECT * FROM products WHERE category = ('') AND EXTRACTVALUE(4154,CONCAT(0x7e,((SELECT (ELT(4154=4154,1)))),0x7e))-- -')

MySQL выполнит подзапрос и вызовет ошибку, которая раскроет результат. Злоумышленник может постепенно извлекать данные посимвольно или целыми строками.

Вывод

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

Источники