Что такое SQL-инъекция и при чём тут EXTRACTVALUE
SQL-инъекция (SQLi) уже много лет не покидает список OWASP Top 10. Это одна из самых распространённых и разрушительных уязвимостей веб-приложений. Злоумышленник внедряет произвольный SQL-код в запрос, который приложение отправляет в базу данных, и получает доступ к данным, которые видеть не должен. В приведённом запросе ')) OR EXTRACTVALUE(1763,CONCAT(0x7e,((SELECT (ELT(1763=1763,1)))),0x7e))-- - используется именно такая атака — на MySQL. Давайте разберём её по частям.
Анатомия payload'а
Строка начинается с ')). Это попытка «закрыть» исходный запрос, который, вероятно, выглядел как SELECT ... WHERE param = ('значение'). Две закрывающие скобки и апостроф позволяют выйти за пределы строкового литерала и добавить собственный код. Далее идёт OR — логический оператор, который делает условие истинным, если правая часть верна. Затем вызывается функция EXTRACTVALUE(1763, CONCAT(...)).
Функция EXTRACTVALUE
EXTRACTVALUE(XML_fragment, XPath_expression) — это встроенная функция MySQL, предназначенная для извлечения данных из XML. Она принимает два аргумента: фрагмент XML и выражение XPath. Если XPath-выражение некорректно или не соответствует XML-структуре, MySQL генерирует ошибку, в текст которой попадает часть переданных данных. Именно это и используется в атаке: злоумышленник заставляет базу выдать ошибку, содержащую результат подзапроса.
Конкатенация и тильды
Второй аргумент — CONCAT(0x7e, ((SELECT (ELT(1763=1763,1)))), 0x7e). 0x7e — это шестнадцатеричное представление символа тильды ~. Тильды служат маркерами, чтобы в сообщении об ошибке было легко найти начало и конец извлечённых данных. Внутри конкатенации стоит подзапрос SELECT (ELT(1763=1763,1)).
Функция ELT и условие 1763=1763
ELT(N, str1, str2, ...) возвращает N-ю строку из списка. Если N=1, возвращается первая строка. В нашем случае условие 1763=1763 всегда истинно, поэтому ELT получает на вход 1 и возвращает 1. Это простейший пример — по сути, подзапрос возвращает число 1. В реальной атаке вместо 1 могла бы стоять, например, (SELECT user()) или (SELECT password FROM users LIMIT 1). Тогда EXTRACTVALUE выбросит ошибку вида XPATH syntax error: '~root@localhost~', и атакующий увидит имя пользователя базы данных.
Комментарий в конце
Завершающая последовательность -- - — это комментарий в MySQL. Два дефиса с пробелом (или с любым символом после них) игнорируют всё, что идёт дальше в исходном запросе. Это нужно, чтобы «отрезать» остатки оригинального SQL-кода и не сломать синтаксис.
Как это работает на практике
Предположим, уязвимый запрос выглядит так:
SELECT * FROM products WHERE category = ('$input')
При подстановке нашего payload'а вместо $input получается:
SELECT * FROM products WHERE category = ('') OR EXTRACTVALUE(1763,CONCAT(0x7e,((SELECT (ELT(1763=1763,1)))),0x7e))-- -')
База данных выполняет запрос, доходит до EXTRACTVALUE, та пытается разобрать строку ~1~ как XML и терпит неудачу. В ответе приложения (если ошибки не подавляются) появится сообщение с текстом ~1~. Это подтверждает, что инъекция работает. Дальше атакующий заменяет 1 на нужный подзапрос и посимвольно извлекает данные.
Зачем это нужно злоумышленнику
Метод основан на ошибках (error-based SQL injection). Он удобен тем, что не требует слепого перебора и позволяет быстро получить информацию: версию MySQL, текущего пользователя, имена таблиц и колонок, а затем и сами данные. В связке с information_schema можно вытащить структуру всей базы.
Как защититься
- Параметризованные запросы (prepared statements). Это главный и самый надёжный способ. Данные передаются отдельно от SQL-кода, и внедрение становится невозможным.
- Валидация и фильтрация ввода. Если параметр ожидает число — проверяйте, что это число. Если строку — ограничивайте допустимые символы.
- Экранирование спецсимволов. Используйте встроенные функции драйвера БД, а не собственные регулярки.
- Отключение вывода ошибок в продакшене. Сообщения об ошибках не должны попадать к пользователю — это затрудняет эксплуатацию error-based атак.
- Принцип наименьших привилегий. Учётная запись приложения не должна иметь прав на чтение системных таблиц и лишних баз.
- Регулярные сканирования и WAF. Автоматические сканеры и веб-прикладные экраны помогают выявить и заблокировать типовые payload'ы.
Автоматизация: sqlmap
Ручной разбор полезен для понимания, но на практике пентестеры часто используют sqlmap. Эта утилита автоматически определяет тип инъекции, подбирает payload'ы (включая EXTRACTVALUE) и извлекает данные. Однако знание того, как устроена конкретная инъекция, помогает быстрее настроить инструмент и понять его вывод.
Вывод
Payload ')) OR EXTRACTVALUE(1763,CONCAT(0x7e,((SELECT (ELT(1763=1763,1)))),0x7e))-- - — это классический пример error-based SQL-инъекции в MySQL. Он использует функцию EXTRACTVALUE для генерации ошибки, содержащей результат подзапроса, обёрнутый в тильды. Защита от таких атак строится на параметризации запросов, строгой валидации и скрытии ошибок. Если вы разработчик — никогда не конкатенируйте пользовательский ввод в SQL-запросы.
Комментарии
—Войдите, чтобы оставить комментарий