1.1 Манипуляция синтаксисом для обхода WAF и IPS
Искусство мимикрии: обход WAF через синтаксические аномалии
Представьте себе современный Web Application Firewall (WAF) как элитного вышибалу в закрытом клубе. У него есть четкий список нежелательных лиц — «черный список» сигнатур, таких как UNION SELECT, OR 1=1 или information_schema. Если вы попытаетесь войти в парадную дверь с этими фразами на футболке, вас мгновенно заблокируют. Однако этот вышибала — не человек, а алгоритм, который мыслит строго в рамках заложенных в него паттернов. Если вы переоденетесь так, что станете неузнаваемы для его правил, но при этом останетесь собой для «охраны внутри» (самой базы данных), доступ будет открыт. Проблема большинства пентестеров уровня Middle заключается в избыточном доверии к автоматизированным инструментам вроде sqlmap, чьи стандартные тамперы давно известны производителям средств защиты.
Настоящее мастерство эксплуатации SQL-инъекций начинается там, где заканчиваются стандартные векторы. В условиях глубоко эшелонированной обороны ваша задача — не просто найти уязвимость, а доставить полезную нагрузку через «узкое горлышко» инспектора трафика. Для этого необходимо использовать фундаментальные различия в том, как парсит строку WAF и как это делает конкретный SQL-движок (MySQL, PostgreSQL или MSSQL). Мы будем использовать неоднозначности синтаксиса, особенности обработки кодировок и логические лазейки в протоколе HTTP, чтобы превратить очевидную атаку в легитимный, на первый взгляд, шум.
Анатомия обмана: комментарии, пробелы и невидимые символы
Первая линия обороны WAF — это поиск пробельных символов и ключевых слов в связке. Большинство сигнатур настроены на поиск паттерна SELECT <space> FROM. Но что, если мы скажем базе данных то же самое, не используя ни одного пробела? В MySQL для этого идеально подходят многострочные комментарии в стиле Си /**/, но современные IPS легко их детектируют. Более продвинутый метод — использование специфического синтаксиса /*!50000SELECT*/. Это «исполняемый комментарий», который MySQL интерпретирует как код, если версия сервера выше или равна 5.00.00, в то время как WAF может видеть в этом просто безобидный блок комментариев.
Однако настоящая магия начинается при манипуляции непечатными символами. Различные СУБД позволяют использовать в качестве разделителей токены, которые WAF просто игнорирует или считает частью строкового литерала. Например, в PostgreSQL и MSSQL можно использовать символы новой строки, табуляции или даже вертикальной табуляции (%0B) между ключевыми словами. В некоторых конфигурациях MySQL символ точки или обратного апострофа может служить разделителем, который ломает регулярное выражение фильтра: SELECT.column_name.FROM.table_name. Если фильтр ожидает пробел, такая конструкция пройдет сквозь него, а парсер базы данных успешно выполнит запрос, отбросив лишние точки как элементы именования схем.
Не стоит забывать и о «мусорных» данных внутри комментариев. Сигнатурный анализ часто ограничен производительностью: WAF не может анализировать бесконечно длинные строки. Наполнение комментария огромным количеством случайных символов /* + 1000 символов шума */ может привести к тому, что анализатор «сдастся» и пропустит остаток пакета, чтобы не вызывать задержек в работе приложения. Это классическая атака на истощение ресурсов инспектора, где полезная нагрузка прячется в самом конце перегруженного буфера.
Вариативность кодировок и HTTP Parameter Pollution
Второй мощный пласт техник — использование несоответствий в интерпретации кодировок. Когда браузер отправляет данные, WAF должен их декодировать, чтобы проверить на наличие угроз. Но что, если мы отправим данные в кодировке, которую WAF не понимает или интерпретирует неверно? Использование двойного URL-кодирования (%2527 вместо %27) — это классика, которая до сих пор работает на плохо настроенных системах. Более изощренный подход — использование Unicode-символов, которые при нормализации в базе данных превращаются в опасные символы. Например, некоторые версии драйверов при конвертации из UTF-8 в Latin-1 могут превращать символ ¿ в обычную кавычку или другие управляющие знаки.
Техника HTTP Parameter Pollution (HPP) заслуживает отдельного внимания. Она основана на том, как разные веб-серверы обрабатывают повторяющиеся параметры в GET или POST запросе. Представьте запрос id=1&id=SELECT&id=password.
- ASP.NET объединит их в
1,SELECT,password. - PHP возьмет только последний:
password. - WAF может проверить только первый параметр
id=1и посчитать его безопасным.
Разбивая полезную нагрузку на части и распределяя её по нескольким одноименным параметрам, вы создаете ситуацию, в которой WAF видит разрозненные фрагменты («SELECT», «FROM», «users»), которые по отдельности не являются вредоносными. Однако после того, как приложение склеит эти части, база данных получит полнофункциональный деструктивный запрос. Это требует глубокого понимания стека технологий жертвы: вы должны точно знать, как именно серверное приложение собирает параметры воедино.
Практический кейс: Обход фильтрации через синтаксис функций
Рассмотрим сценарий, где WAF блокирует слово UNION. Мы можем попытаться заменить его на эквивалентные по логике конструкции, которые не входят в стандартные списки блокировок. В некоторых случаях использование подзапросов в блоке WHERE или FROM позволяет извлечь данные без использования UNION. Но если нам все же нужен именно этот оператор, мы можем прибегнуть к обфускации самого слова. В MySQL это может выглядеть как UnIoN (смена регистра — база нечувствительна, а простейший фильтр может быть чувствителен) или использование альтернативных функций для конкатенации строк, если фильтруется вывод.
Еще один эффективный метод — использование встроенных функций для сокрытия строк. Вместо того чтобы писать SELECT 'password', мы пишем SELECT CHAR(112, 97, 115, 115, 119, 111, 114, 100). Здесь нет ни одной кавычки и ни одного подозрительного слова на английском. Если WAF не умеет выполнять базовые арифметические операции или декодировать функцию CHAR(), атака пройдет успешно. В базах данных типа MSSQL можно использовать EXEC(0x...), передавая всю полезную нагрузку в шестнадцатеричном виде. Для системы защиты это выглядит как передача бинарного контента (например, картинки), а для СУБД это команда на выполнение закодированного скрипта.
Практическое задание
Ваша задача — отработать навыки конструирования скрытых нагрузок. Попробуйте выполнить следующие шаги в лабораторной среде или на тестовом стенде:
- Сформируйте запрос для извлечения версии базы данных (например,
@@versionилиversion()), используя вместо пробелов любые другие допустимые символы (комментарии, непечатные знаки). - Подготовьте вектор атаки, который не содержит ключевых слов
SELECTиUNIONв явном виде (используйте кодированиеHEX,CHARили строковые функции вродеREVERSE('NOINU')). - Исследуйте поведение стенда при передаче параметров с одинаковыми именами. Выясните, как ваш локальный сервер (Apache/PHP или Nginx/Python) обрабатывает
?id=1&id=2.
Чек-лист ключевых идей урока
- WAF и база данных — это два разных парсера. Успех атаки кроется в использовании их разночтений.
- Исполняемые комментарии (
/*! ... */) — мощный инструмент для специфических атак на MySQL. - Непечатные символы (
%00,%0B,%0D%0A) могут служить разделителями, невидимыми для регулярных выражений. - HTTP Parameter Pollution позволяет дробить нагрузку, обходя лимиты анализаторов.
- Использование функций
CHAR(),HEX(),CONV()иBASE64()скрывает смысл запроса от сигнатурного поиска. - Всегда проверяйте, как целевой стек (язык + сервер) нормализует входные данные перед передачей в СУБД.
В этом уроке мы научились обманывать «внешний контур» защиты, работая с синтаксисом и протоколами передачи. Однако иногда уязвимость скрыта не в том, что мы отправляем сейчас, а в том, как приложение использует наши данные позже. В следующем уроке мы перейдем к одной из самых коварных техник — Second-Order SQLi, где мы внедрим код, который сработает не сразу, а в самый неожиданный для системы момент.