Строка ") AND EXTRACTVALUE(7825,CONCAT(0x7e,((SELECT (ELT(7825=7825,1)))),0x7e))-- - — это типичный пример error-based SQL-инъекции для СУБД MySQL. Такие конструкции используются злоумышленниками для извлечения данных из базы через вывод сообщения об ошибке. В этой статье мы детально разберём, как работает этот запрос, какие функции задействованы и как защититься от подобных атак.
Что такое error-based SQL-инъекция?
SQL-инъекция — это один из самых распространённых способов взлома веб-приложений, при котором вредоносный код внедряется в SQL-запрос через пользовательский ввод. Error-based инъекция — это разновидность, при которой злоумышленник заставляет базу данных выдать сообщение об ошибке, содержащее полезные данные (например, версию СУБД, имена таблиц, содержимое полей).
Для реализации таких атак часто используются функции, которые вызывают ошибку с контролируемым текстом. В MySQL это, в частности, EXTRACTVALUE() и UPDATEXML().
Разбор строки инъекции
Рассмотрим запрос по частям:
")— закрывает предыдущую конструкцию в уязвимом запросе, например, строковый литерал и скобку. Это позволяет внедрить свой код.AND EXTRACTVALUE(7825,CONCAT(0x7e,((SELECT (ELT(7825=7825,1)))),0x7e))— основная часть, вызывающая ошибку.-- -— комментарий, который отсекает остаток оригинального запроса.
Функция EXTRACTVALUE
EXTRACTVALUE(XML_fragment, XPath_expression) извлекает значение из XML-документа по заданному XPath-выражению. Если XPath-выражение синтаксически неверно, MySQL генерирует ошибку, в текст которой попадает переданный фрагмент. Это и используется для вывода данных.
Например,EXTRACTVALUE(1, CONCAT(0x7e, (SELECT version()), 0x7e))вызовет ошибку видаXPATH syntax error: '~5.7.33~', где 5.7.33 — версия сервера.
В нашем случае первым аргументом идёт число 7825 — это произвольный XML-фрагмент (не является корректным XML, но это не важно). Второй аргумент — результат CONCAT.
Функция CONCAT и шестнадцатеричные литералы
CONCAT(0x7e, ((SELECT (ELT(7825=7825,1)))), 0x7e) объединяет три строки:
0x7e— шестнадцатеричное представление символа~(тильда).- Результат подзапроса
(SELECT (ELT(7825=7825,1))). - Снова
0x7e.
Тильда используется как маркер, чтобы в сообщении об ошибке чётко выделить выводимые данные.
Функция ELT и условие 7825=7825
ELT(N, str1, str2, ...) возвращает N-ю строку из списка. В данном случае ELT(7825=7825, 1) — выражение 7825=7825 всегда истинно (возвращает 1), поэтому ELT вернёт первую строку — 1. Это простейший пример; в реальных атаках на месте 1 может быть подзапрос, извлекающий данные (например, имя пользователя, хеш пароля).
Условие 7825=7825 нужно лишь для демонстрации работы — оно всегда истинно. Злоумышленники часто используют подобные тавтологии для проверки уязвимости или для обхода фильтров.
Зачем это нужно злоумышленнику?
Цель — заставить сервер вернуть в ответе HTTP страницу с ошибкой, содержащей результат выполнения подзапроса. Например, если вместо ELT(7825=7825,1) подставить SELECT password FROM users LIMIT 1, то в тексте ошибки появится пароль. Таким образом можно посимвольно извлекать любые данные из базы.
Подобные инъекции опасны тем, что не требуют слепого перебора и дают быстрый результат. Они работают, если приложение выводит ошибки СУБД на страницу.
Как защититься от error-based SQL-инъекций?
Основные меры:
- Использовать подготовленные выражения (prepared statements) с параметризацией запросов. Это самый надёжный способ, так как данные не попадают в тело SQL-запроса.
- Отключить вывод ошибок СУБД в продакшене. Ошибки должны логироваться, а пользователь видеть общее сообщение.
- Проводить валидацию и экранирование всех входных данных, особенно тех, что попадают в SQL.
- Использовать ORM (например, Doctrine, Hibernate), которые по умолчанию применяют параметризацию.
- Регулярно обновлять СУБД и применять патчи безопасности.
- Внедрить WAF (Web Application Firewall) для фильтрации подозрительных запросов.
Важно понимать, что экранирование спецсимволов (например, через mysql_real_escape_string) не всегда спасает, если неправильно настроена кодировка или допущены логические ошибки в запросах. Поэтому параметризация — золотой стандарт.
Пример уязвимого кода и его исправление
Рассмотрим фрагмент на PHP:
$id = $_GET['id'];
$query = "SELECT * FROM products WHERE id = '$id'";
$result = mysqli_query($conn, $query);
Если передать id=1' AND EXTRACTVALUE(7825,CONCAT(0x7e,(SELECT version()),0x7e))-- -, то выполнится инъекция. Исправленный вариант:
$stmt = $conn->prepare("SELECT * FROM products WHERE id = ?");
$stmt->bind_param("i", $_GET['id']);
$stmt->execute();
Здесь параметр ? гарантирует, что ввод не изменит структуру запроса.
Распространённые мифы
- Миф: если сайт не выводит ошибки, то error-based инъекция невозможна. Реальность: существуют слепые методы (blind SQL injection), которые работают и без вывода ошибок, хотя и медленнее.
- Миф: EXTRACTVALUE — единственная функция для error-based атак. Реальность: также используются UPDATEXML, GTID_SUBSET, JSON_KEYS и другие.
Заключение
Строка ") AND EXTRACTVALUE(7825,CONCAT(0x7e,((SELECT (ELT(7825=7825,1)))),0x7e))-- - — это учебный пример эксплуатации error-based SQL-инъекции в MySQL. Понимание механизма таких атак помогает разработчикам и администраторам правильно выстраивать защиту. Главные рекомендации: используйте параметризованные запросы, скрывайте ошибки от пользователей и проводите регулярный аудит безопасности.
Комментарии
—Войдите, чтобы оставить комментарий