Что это за строка?
Строка %" AND EXTRACTVALUE(6040,CONCAT(0x7e,((SELECT (ELT(6040=6040,1)))),0x7e))-- - представляет собой классический пример error-based SQL-инъекции для СУБД MySQL. Она предназначена для извлечения данных из базы через вывод сообщения об ошибке. Подобные конструкции часто встречаются в отчётах об уязвимостях и пентестах.
Внешне это выглядит как бессмысленный набор символов, но каждый элемент здесь имеет строгое назначение. Давайте разберём её по частям.
Разбор компонентов
1. Начало: %"
Символ % часто используется в URL-кодировании, но в данном контексте это, скорее всего, часть полезной нагрузки, которая попала в строку запроса. Далее идёт " — закрывающая кавычка, которая разрывает исходное строковое значение в SQL-запросе. Это типичный приём для внедрения в параметры, где ожидается строка в кавычках.
2. AND
Логический оператор AND добавляется, чтобы внедряемое условие было истинным и не нарушало синтаксис исходного запроса. Если исходный запрос был SELECT ... WHERE id = '...', то после подстановки получается WHERE id = '%" AND ... — и часть с AND выполняется только если первое условие истинно (или ложно, в зависимости от логики).
3. EXTRACTVALUE(6040, CONCAT(...))
EXTRACTVALUE — это функция MySQL для работы с XML. Она извлекает значение из XML-строки по указанному XPath-выражению. Синтаксис: EXTRACTVALUE(XML_document, XPath_expression). Если XPath-выражение некорректно, MySQL генерирует ошибку, в тексте которой может содержаться переданное значение.
В нашем случае первый аргумент — 6040 (просто число, которое будет преобразовано в строку XML). Второй аргумент — CONCAT(0x7e, ..., 0x7e) — конкатенация символа ~ (0x7e в hex) с некоторым выражением и снова ~. Символ ~ используется как маркер, чтобы в сообщении об ошибке было легко найти извлечённые данные.
4. CONCAT(0x7e, ((SELECT (ELT(6040=6040,1)))), 0x7e)
Здесь 0x7e — это шестнадцатеричное представление символа ~ (тильда). CONCAT объединяет тильду, результат подзапроса и снова тильду.
Подзапрос: (SELECT (ELT(6040=6040,1))). ELT — функция MySQL, которая возвращает N-й элемент из списка. ELT(N, str1, str2, ...) возвращает str1, если N=1, str2, если N=2, и т.д. В данном случае 6040=6040 — это выражение, которое всегда истинно (1). Значит, ELT(1, 1) вернёт 1. То есть подзапрос возвращает число 1. Это простейший пример; в реальной атаке вместо 1 могло бы быть имя пользователя, пароль или другая конфиденциальная информация, полученная через подзапрос.
5. Завершение: -- -
Два дефиса -- начинают комментарий в SQL. Всё, что идёт после них, игнорируется. Пробел после -- (или дефис в данном случае) нужен, чтобы некоторые парсеры корректно распознали комментарий. Это позволяет отсечь остаток оригинального запроса, который мог бы вызвать синтаксическую ошибку.
Как это работает целиком
Предположим, уязвимый запрос выглядит так:
SELECT * FROM users WHERE username = '$input';
Если в $input передать нашу строку, то запрос станет:
SELECT * FROM users WHERE username = '%" AND EXTRACTVALUE(6040,CONCAT(0x7e,((SELECT (ELT(6040=6040,1)))),0x7e))-- -';
После закрывающей кавычки и AND выполняется функция EXTRACTVALUE. Так как второй аргумент не является корректным XPath (начинается с ~), MySQL выдаст ошибку вида:
XPATH syntax error: '~1~'
В этом сообщении мы видим ~1~ — это и есть результат подзапроса, обрамлённый тильдами. Если бы вместо 1 был, например, database(), мы бы увидели имя текущей базы данных. Таким образом, злоумышленник может извлекать произвольные данные, вызывая ошибки.
Зачем это нужно?
Error-based SQL-инъекции — мощный инструмент в руках атакующего, когда другие методы (union-based, blind) не работают. Они позволяют быстро получить информацию о структуре базы, учётных данных и т.д. Однако современные СУБД и фреймворки часто отключают вывод подробных ошибок, что делает такие атаки менее эффективными.
Как защититься?
- Используйте параметризованные запросы (prepared statements). Это самый надёжный способ предотвратить SQL-инъекции.
- Экранируйте пользовательский ввод. Но помните, что экранирование не панацея.
- Отключайте вывод ошибок СУБД на продакшене. Ошибки должны логироваться, но не показываться пользователю.
- Применяйте принцип наименьших привилегий. Учётная запись приложения должна иметь только необходимые права.
- Регулярно обновляйте СУБД и фреймворки. Многие уязвимости закрываются в новых версиях.
Заключение
Строка %" AND EXTRACTVALUE(6040,CONCAT(0x7e,((SELECT (ELT(6040=6040,1)))),0x7e))-- - — это учебный пример эксплуатации error-based SQL-инъекции в MySQL. Понимание таких конструкций помогает разработчикам и специалистам по безопасности лучше защищать свои приложения. Никогда не используйте подобные техники против систем, на которые у вас нет разрешения.
Комментарии
—Войдите, чтобы оставить комментарий