Что это за строка?
Запрос пользователя содержит конструкцию OR EXTRACTVALUE(9720,CONCAT(0x7e,((SELECT (ELT(9720=9720,1)))),0x7e))-- -. Это не случайный набор символов, а тщательно сконструированная SQL-инъекция, использующая механизм ошибок функций MySQL для извлечения данных. Подобные строки часто встречаются в логах веб-серверов, в отчётах систем обнаружения вторжений (IDS) и в учебных материалах по кибербезопасности.
В данной статье мы разберём, что означает каждый элемент этой конструкции, как работает error-based SQL-инъекция и какие меры защиты необходимо применять, чтобы подобные атаки не достигли цели.
Разбор составных частей
OR — логический оператор
Ключевое слово OR используется для изменения логики исходного SQL-запроса. Если злоумышленник может вставить его в условие WHERE, то запрос вернёт все строки таблицы, даже если исходное условие было ложным. Это может привести к обходу аутентификации или несанкционированному доступу к данным.
EXTRACTVALUE(9720, CONCAT(...)) — функция, вызывающая ошибку
EXTRACTVALUE() — это встроенная функция MySQL, предназначенная для извлечения значения из XML-документа. Она принимает два аргумента: XML-строку и XPath-выражение. Если XPath-выражение некорректно, функция генерирует ошибку, в текст которой попадает переданное значение. Именно это свойство эксплуатируется в error-based инъекциях: злоумышленник формирует такой второй аргумент, чтобы в сообщении об ошибке появились данные из базы.
В нашем случае первый аргумент — число 9720 (не является корректным XML), а второй — результат CONCAT(0x7e, ((SELECT (ELT(9720=9720,1)))), 0x7e). Функция CONCAT объединяет строки: 0x7e — это шестнадцатеричное представление символа ~ (тильда), который используется как разделитель, чтобы облегчить извлечение данных из сообщения об ошибке.
ELT(9720=9720,1) — условный выбор
ELT() возвращает N-й элемент из списка строк. В данном случае выражение 9720=9720 всегда истинно (1), поэтому ELT(1, 1) вернёт строку '1'. Это простейший пример; в реальной атаке вместо ELT(9720=9720,1) мог бы стоять подзапрос, извлекающий конфиденциальные данные, например, имя пользователя и пароль из таблицы users.
-- - — комментарий
Два дефиса и пробел (-- ) в MySQL означают начало однострочного комментария. Всё, что идёт после них, игнорируется парсером. Это позволяет злоумышленнику «отрезать» оставшуюся часть оригинального запроса, чтобы синтаксис стал корректным. Дефис в конце (-) часто добавляют для надёжности, чтобы комментарий точно начался, даже если после -- не будет пробела.
Как работает error-based SQL-инъекция
Цель такой атаки — заставить базу данных вернуть сообщение об ошибке, содержащее полезные данные. Поскольку приложение выводит ошибки на страницу (или они попадают в логи), атакующий может их прочитать. В нашем примере:
- База данных выполняет
EXTRACTVALUE(9720, CONCAT(0x7e, (SELECT ...), 0x7e)). - Первый аргумент
9720не является допустимым XML, поэтому функция пытается разобрать его и терпит неудачу. - В процессе разбора MySQL формирует сообщение об ошибке, в которое включает второй аргумент — строку, начинающуюся и заканчивающуюся тильдой.
- Атакующий видит что-то вроде:
XPATH syntax error: '~1~'— и понимает, что подзапрос вернул1.
Меняя подзапрос, злоумышленник может побайтово извлекать любые данные: имена таблиц, столбцов, логины, хеши паролей и т.д. Это один из классических методов, описанных в базах знаний по SQL-инъекциям, например, в проекте OWASP.
Опасность и последствия
Успешная error-based инъекция может привести к полной компрометации базы данных. Злоумышленник получает доступ к персональным данным пользователей, коммерческой тайне, а в некоторых случаях — к выполнению произвольных команд на сервере (если СУБД работает с избыточными привилегиями). Поэтому так важно понимать механизм атаки и своевременно закрывать уязвимости.
Как защититься
Основная причина успеха подобных инъекций — недостаточная фильтрация пользовательского ввода и конкатенация строк при построении SQL-запросов. Вот ключевые меры защиты:
- Параметризованные запросы (prepared statements). Используйте их везде, где возможно. Они разделяют код и данные, поэтому внедрение SQL-кода становится невозможным.
- Экранирование специальных символов. Если параметризация недоступна, применяйте функции экранирования, предоставляемые драйвером БД (например,
mysqli_real_escape_stringв PHP). - Валидация и белые списки. Проверяйте типы данных, ограничивайте длину и допустимые символы для всех входных параметров.
- Отключение подробных сообщений об ошибках. На production-серверах не выводите ошибки БД пользователю. Логируйте их, но не показывайте.
- Принцип наименьших привилегий. Учётная запись, от имени которой работает приложение, должна иметь только необходимые права. Не используйте root для веб-приложений.
- Регулярное обновление СУБД и фреймворков. Устаревшие версии могут содержать уязвимости, облегчающие эксплуатацию.
Кроме того, рекомендуется использовать веб-application firewall (WAF), который может блокировать типовые сигнатуры SQL-инъекций, но полагаться только на него нельзя — это лишь дополнительный слой защиты.
Заключение
Конструкция OR EXTRACTVALUE(9720,CONCAT(0x7e,((SELECT (ELT(9720=9720,1)))),0x7e))-- - — это наглядный пример error-based SQL-инъекции, эксплуатирующей особенности функций MySQL. Понимание того, как работают такие атаки, помогает разработчикам и администраторам строить надёжную защиту. Помните: безопасность базы данных — это не одна мера, а комплексный подход, включающий безопасный код, правильную настройку сервера и постоянный мониторинг.
Комментарии
—Войдите, чтобы оставить комментарий