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

SQL-инъекция — один из самых распространённых способов атаки на веб-приложения. Злоумышленник встраивает в пользовательский ввод специальные конструкции, которые меняют логику SQL-запроса. Существует несколько разновидностей: union-based, blind, time-based и error-based. Последняя, о которой пойдёт речь, основана на принудительном вызове ошибки базы данных, в тексте которой «протаскиваются» нужные хакеру данные.

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

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

EXTRACTVALUE

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

CONCAT и 0x7e

CONCAT объединяет строки. 0x7e — это шестнадцатеричное представление символа «~» (тильда). Тильда используется как маркер-разделитель: она недопустима в XPath-выражении, поэтому гарантированно вызывает ошибку, а её обрамление позволяет легко найти внедрённые данные в сообщении об ошибке.

SELECT и ELT

ELT(N, str1, str2, ...) возвращает N-ю строку из списка. В нашем случае ELT(8792=8792,1) вернёт «1», так как условие 8792=8792 истинно. На практике вместо этого подзапроса подставляют реальный запрос к таблицам information_schema или пользовательским данным, например: SELECT table_name FROM information_schema.tables LIMIT 1.

Комментарий -- -

Двойной дефис с пробелом — это комментарий в MySQL. Он «отрезает» остаток оригинального запроса, чтобы синтаксис оставался корректным.

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

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

SELECT * FROM users WHERE id = '$id';

Если передать в параметр $id строку 1 AND EXTRACTVALUE(8792,CONCAT(0x7e,(SELECT version()),0x7e))-- -, то база выполнит:

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

В ответе сервер вернёт ошибку вида: XPATH syntax error: '~5.7.34~'. Таким образом, атакующий узнаёт версию СУБД. Аналогично можно извлекать имена таблиц, колонок и даже хеши паролей.

Чем опасна такая инъекция?

  • Позволяет получить полный доступ к структуре базы данных.
  • Даёт возможность читать конфиденциальную информацию: логины, пароли, персональные данные.
  • В некоторых конфигурациях (при наличии прав FILE) может привести к записи файлов на сервер и выполнению кода.
  • Ошибки, возвращаемые СУБД, помогают обойти «слепые» сценарии и ускорить эксплуатацию.

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

1. Подготовленные выражения (prepared statements)

Самый надёжный способ — использовать параметризованные запросы. Данные передаются отдельно от SQL-кода и не могут изменить его структуру. Это работает в PDO (PHP), JDBC (Java), psycopg2 (Python) и других библиотеках.

2. Экранирование и валидация

Если по каким-то причинам prepared statements недоступны, необходимо строго валидировать входные данные: приводить к ожидаемому типу, проверять по белому списку, использовать функции экранирования (например, mysqli_real_escape_string).

3. Отключение подробных сообщений об ошибках

В production-окружении никогда не показывайте пользователю текст ошибок СУБД. Это лишает атакующего обратной связи и делает error-based инъекции бесполезными.

4. Принцип наименьших привилегий

Учётная запись, от имени которой работает приложение, должна иметь только необходимые права. Запретите доступ к information_schema и mysql, если он не нужен.

5. Регулярные обновления и WAF

Своевременно обновляйте СУБД и фреймворки. Веб-приложения-экраны (WAF) могут блокировать известные сигнатуры атак, но не заменяют правильного кодирования.

Заключение

Конструкция AND EXTRACTVALUE(8792,CONCAT(0x7e,((SELECT (ELT(8792=8792,1)))),0x7e))-- - — это не безобидный набор символов, а рабочий инструмент хакера. Понимание механики таких атак помогает разработчикам и администраторам своевременно закрывать уязвимости. Главный вывод: используйте параметризованные запросы, скрывайте ошибки и не доверяйте пользовательскому вводу.

Источники