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

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

Подобные строки часто встречаются в логах веб-серверов, в отчётах систем обнаружения вторжений (IDS) и в учебных материалах по информационной безопасности. Они не являются обычным пользовательским вводом, а представляют собой попытку атаки на веб-приложение, которое небезопасно обрабатывает параметры запроса.

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

Чтобы понять, как работает этот эксплойт, разберём его на составляющие.

1. Начало: %'

Символ % часто используется как подстановочный знак в SQL-запросах с LIKE. Апостроф ' закрывает строковый литерал в исходном запросе. Вместе %' — это попытка «сломать» синтаксис запроса, чтобы внедрить собственный код. Например, если приложение выполняет запрос вида:

SELECT * FROM users WHERE name LIKE '%[ввод]%'

то при подстановке %' запрос становится синтаксически незавершённым, и злоумышленник может добавить свою логику.

2. Оператор OR

Логическое «ИЛИ» позволяет обойти условия фильтрации. Если хотя бы одна часть выражения истинна, запрос вернёт данные. В error-based инъекциях OR часто используется для вызова функции, которая гарантированно выполнится и вызовет ошибку с полезной нагрузкой.

3. Функция EXTRACTVALUE(2016, CONCAT(...))

EXTRACTVALUE() — это функция MySQL для работы с XML. Она извлекает значение из XML-строки по указанному XPath-выражению. Синтаксис: EXTRACTVALUE(XML_document, XPath_expression).

В нашем случае первый аргумент — 2016 (число, которое не является корректным XML), второй — результат CONCAT(0x7e, ((SELECT (ELT(2016=2016,1)))), 0x7e).

Когда EXTRACTVALUE получает некорректный XML, MySQL генерирует ошибку и включает в сообщение часть переданного XPath-выражения. Это позволяет злоумышленнику «вытащить» данные через текст ошибки.

4. CONCAT(0x7e, ..., 0x7e)

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

5. Подзапрос (SELECT (ELT(2016=2016,1)))

ELT(N, str1, str2, ...) возвращает N-ю строку из списка. Если N=1, возвращается первая строка. Здесь 2016=2016 — всегда истинное условие, которое возвращает 1 (в MySQL TRUE = 1). Таким образом, ELT(1, 1) вернёт 1.

В реальной атаке вместо 1 подставляется подзапрос, извлекающий данные, например: (SELECT password FROM users LIMIT 1). Но в данном примере показан «безопасный» шаблон, который просто возвращает число 1 — вероятно, для тестирования уязвимости.

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

Двойной дефис с пробелом (или -- -) в MySQL означает начало комментария до конца строки. Это позволяет «отрезать» оставшуюся часть оригинального запроса, чтобы синтаксис стал корректным.

Как работает error-based SQL-инъекция

Error-based инъекция — это метод, при котором злоумышленник заставляет базу данных вернуть данные в тексте ошибки. MySQL при неправильном использовании функций, таких как EXTRACTVALUE или UPDATEXML, включает в сообщение об ошибке фрагмент переданного XPath. Это позволяет посимвольно извлекать содержимое базы.

Пример реальной атаки: вместо ELT(2016=2016,1) подставляется (SELECT table_name FROM information_schema.tables LIMIT 1). Тогда в ошибке появится имя первой таблицы. Меняя LIMIT, можно перебрать все таблицы, столбцы и данные.

Пример уязвимого запроса

Рассмотрим гипотетический уязвимый код на PHP:

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

Если пользователь передаст %' OR EXTRACTVALUE(2016,CONCAT(0x7e,((SELECT (ELT(2016=2016,1)))),0x7e))-- -, итоговый запрос станет:

SELECT * FROM products WHERE name LIKE '%%' OR EXTRACTVALUE(2016,CONCAT(0x7e,((SELECT (ELT(2016=2016,1)))),0x7e))-- -%'

MySQL выполнит EXTRACTVALUE и вернёт ошибку, например: XPATH syntax error: '~1~'. В реальной атаке вместо 1 было бы значение из базы.

Последствия успешной инъекции

  • Утечка конфиденциальных данных (пароли, персональные данные, номера карт).
  • Полное чтение структуры базы данных через information_schema.
  • В некоторых случаях — модификация или удаление данных.
  • Компрометация всего веб-приложения и сервера.

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

Основной метод защиты — использование подготовленных выражений (prepared statements) с параметризацией запросов. Это исключает возможность внедрения SQL-кода, так как данные передаются отдельно от запроса.

Дополнительные меры:

  • Экранирование специальных символов с помощью mysqli_real_escape_string (устаревший, но всё ещё используемый метод).
  • Валидация и фильтрация входных данных (белые списки, ограничение длины, типов).
  • Использование ORM и Query Builder, которые автоматически параметризуют запросы.
  • Отключение вывода ошибок MySQL в production-окружении (display_errors = Off).
  • Применение WAF (Web Application Firewall) для блокировки подозрительных запросов.
  • Регулярное обновление СУБД и библиотек.

Заключение

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

Источники