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

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

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

Разбор по частям

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

1. Начало: %')

Символ % — это URL-кодированный пробел (или просто часть исходного значения, например, в поисковом запросе). Далее идут закрывающая кавычка ' и закрывающая скобка ). Это попытка «закрыть» ранее открытые кавычки и скобки в оригинальном SQL-запросе, чтобы внедрить свой код. Предполагается, что уязвимый параметр вставляется в запрос внутри кавычек и скобок, например: WHERE id = ('значение').

2. OR

Логический оператор OR делает условие всегда истинным (если правая часть вернёт истину), что позволяет обойти аутентификацию или получить все записи. В данном случае он также служит для внедрения функции, которая вызовет ошибку.

3. EXTRACTVALUE(6404,CONCAT(...))

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

Первый аргумент 6404 — это произвольное число, которое не является валидным XML. Второй аргумент — результат CONCAT, который и попадёт в сообщение об ошибке.

4. CONCAT(0x7e,((SELECT (ELT(6404=6404,1)))),0x7e)

CONCAT объединяет несколько строк. 0x7e — это шестнадцатеричное представление символа ~ (тильда). Он используется как разделитель, чтобы облегчить поиск выводимых данных в тексте ошибки.

Внутри CONCAT находится подзапрос (SELECT (ELT(6404=6404,1))). ELT — функция, возвращающая N-й элемент из списка. Здесь 6404=6404 — всегда истинное условие (равно 1), поэтому ELT(1,1) вернёт 1. Это простейшая проверка работоспособности инъекции. В реальной атаке вместо 1 подставляется подзапрос, извлекающий данные, например, имя пользователя или хеш пароля.

5. Завершение: -- -

-- — это комментарий в SQL. Всё, что идёт после него, игнорируется базой данных. Пробел после -- и дефис добавлены для надёжности, чтобы комментарий точно сработал в разных СУБД и настройках.

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

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

SELECT * FROM users WHERE username = '$user' AND password = '$pass';

Если в параметр $user подставить нашу строку, запрос станет таким:

SELECT * FROM users WHERE username = '%') OR EXTRACTVALUE(6404,CONCAT(0x7e,((SELECT (ELT(6404=6404,1)))),0x7e))-- -' AND password = '...';

База данных попытается выполнить EXTRACTVALUE с некорректным XML (число 6404), что вызовет ошибку. В тексте ошибки будет что-то вроде:

XPATH syntax error: '~1~'

Таким образом, атакующий видит результат выполнения вложенного запроса. Меняя ELT(6404=6404,1) на подзапрос, например (SELECT password FROM users LIMIT 1), он может извлечь пароли.

Зачем это нужно злоумышленникам?

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

Как защититься?

  • Используйте параметризованные запросы (prepared statements). Это самый надёжный способ: данные передаются отдельно от SQL-кода, и внедрение становится невозможным.
  • Экранируйте специальные символы. Если параметризация недоступна, применяйте функции экранирования, например mysqli_real_escape_string.
  • Отключите вывод ошибок БД на продакшене. Сообщения об ошибках не должны попадать к пользователю — это скрывает результаты инъекций.
  • Регулярно обновляйте СУБД. В MySQL 8.0.17 и новее функции EXTRACTVALUE и UPDATEXML удалены, что затрудняет классические error-based атаки, но не отменяет необходимости общей защиты.
  • Используйте WAF (Web Application Firewall). Он может блокировать подозрительные строки, содержащие EXTRACTVALUE, CONCAT и другие характерные конструкции.

Распространённые вариации

Вместо EXTRACTVALUE злоумышленники могут использовать UPDATEXML, GTID_SUBSET, EXP (в MySQL 5.7) или функции других СУБД: CAST в PostgreSQL, UTL_INADDR в Oracle. Синтаксис может отличаться, но принцип один: вызвать ошибку, содержащую данные.

Строка %') OR EXTRACTVALUE(6404,CONCAT(0x7e,((SELECT (ELT(6404=6404,1)))),0x7e))-- - — это «учебный» пример, где вместо реального подзапроса стоит заглушка ELT(6404=6404,1). В реальной атаке на её месте был бы код для кражи информации.

Вывод

Если вы встретили такую строку в логах или в поле ввода — это попытка взлома. Не паникуйте, но проверьте, защищено ли ваше приложение. Для разработчиков это напоминание о важности параметризованных запросов и скрытия ошибок базы данных. Для обычных пользователей — повод убедиться, что сайт, где вы вводите данные, использует HTTPS и современные методы защиты.

Источники