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

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

SQL-инъекция (SQLi) — один из самых распространённых способов атаки на веб-приложения. Злоумышленник внедряет в пользовательский ввод специальные символы или целые SQL-конструкции, которые меняют логику выполняемого запроса. Это позволяет читать, изменять или удалять данные, а иногда и полностью захватывать контроль над сервером.

По данным OWASP, SQL-инъекции стабильно входят в топ-10 критических уязвимостей. Ошибки возникают, когда разработчики конкатенируют пользовательский ввод с SQL-запросом без должной обработки.

Разбор строки инъекции

Рассмотрим фрагмент ))) AND EXTRACTVALUE(9135,CONCAT(0x7e,((SELECT (ELT(9135=9135,1)))),0x7e))-- - по частям.

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

В реальной атаке вместо 9135=9135 подставляется условие, проверяющее данные (например, SUBSTRING(version(),1,1)='5'). Если условие истинно, ELT вернёт 1, и в ошибке EXTRACTVALUE появится строка ~1~. Если ложно — ELT вернёт NULL или 0, и ошибка будет другой. По этим сообщениям атакующий побайтово извлекает информацию.

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

Функция EXTRACTVALUE(XML_document, XPath_expression) требует, чтобы XPath был синтаксически правильным. Если передать строку, не являющуюся корректным XPath (например, содержащую символ ~), MySQL сгенерирует ошибку вида:

ERROR 1105 (HY000): XPATH syntax error: '~1~'

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

Зачем нужен ELT?

ELT(N, str1, str2, ...) возвращает N-й элемент из списка строк. В нашем случае используется один элемент — 1. Конструкция ELT(9135=9135,1) — это трюк: сравнение 9135=9135 всегда истинно (1), поэтому ELT вернёт 1. В реальной инъекции на месте 9135=9135 стоит проверяемое условие, а вместо 1 может быть, например, version() или database().

Пошаговый пример атаки

  1. Злоумышленник находит точку входа — параметр, который попадает в SQL-запрос без экранирования.
  2. Подставляет конструкцию с EXTRACTVALUE, чтобы вызвать ошибку и увидеть её текст.
  3. Меняет условие в ELT, чтобы извлечь имя базы, версию, имена таблиц и т.д.
  4. Автоматизирует процесс с помощью sqlmap или ручного перебора.

Важно: подобные методы работают только на MySQL и MariaDB. В других СУБД (PostgreSQL, MS SQL) используются иные приёмы.

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

Основная причина успеха таких атак — отсутствие параметризации запросов. Вот ключевые меры защиты:

  • Используйте подготовленные выражения (prepared statements). Это самый надёжный способ. Параметры передаются отдельно от SQL-кода, и внедрить что-либо в структуру запроса невозможно.
  • Экранируйте специальные символы. Если по каким-то причинам параметризация недоступна, применяйте функции экранирования, предоставляемые драйвером БД.
  • Отключите вывод подробных ошибок в production. Сообщения об ошибках не должны попадать к пользователю — это лишает атакующего обратной связи.
  • Ограничьте права пользователя БД. Приложение должно работать под учётной записью с минимально необходимыми привилегиями.
  • Используйте WAF. Веб-прикладной брандмауэр может блокировать типовые сигнатуры SQLi, но не является панацеей.

Вывод

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

Источники