Почему правила WAF не остановили SQL-инъекцию
WAF может отсеять часть вредоносных запросов, но не доказывает, что приложение защищено от SQL-инъекций. Я разбираю три причины пропусков: правила без настройки под сайт, неверные ожидания от нормализации и поспешное включение блокировки. Покажу, что смотреть в журнале и где исправлять саму причину.
Что WAF делает, а чего не может
Я рассматриваю WAF как фильтр перед веб-приложением: он анализирует запросы по набору правил и может остановить те, которые подходят под обнаруживаемые шаблоны атак. Это полезная граница, но у фильтра нет полного знания о том, какой смысл приложение придаёт каждому полю формы. Строка, которая выглядит подозрительно для общего правила, может быть обычным поисковым запросом; вредоносное значение, собранное приложением в SQL небезопасным способом, может не совпасть с известной проверкой. Поэтому слово «установлен» не означает «проверен». При оценке я записываю, на каком участке стоит фильтр и какие части запроса он способен разобрать; эти возможности зависят от продукта и его политики. Если запрос проходит к приложению, это ещё не говорит, исполнило ли оно SQL и какие данные вернуло. Для вывода о последствиях нужны отдельные данные приложения и базы, а не догадка по одному совпадению фильтра.
WAF не меняет код, который собирает SQL, и не подтверждает безопасность запроса к базе. В приложении значения пользователя нужно передавать параметрами, отдельно от текста SQL, а не склеивать строку из фрагментов ввода. Кроме того, учётной записи приложения стоит выдавать только права, необходимые для его задач: если ошибка всё же случится, лишние права не должны прилагаться к ней бесплатным бонусом. Я использую WAF как дополнительный слой и проверяю его отдельно от защиты в коде. Именно разделение задач не даёт выдать фильтр за исправление уязвимости. Параметризация не отменяет проверку полномочий: чтение, изменение и удаление данных должны быть доступны только тем операциям, которым они действительно нужны. Я отдельно смотрю, не подключается ли сайт к базе с административной учётной записью и не использует ли общий пользователь приложения права, нужные только для обслуживания. Эти меры не делают SQL безопасным сами по себе, но сокращают ненужные возможности уязвимого приложения.
- WAF фильтрует HTTP-запросы по правилам.
- Код приложения по-прежнему отвечает за безопасный SQL.
- Права учётной записи БД ограничивают возможный ущерб.
Ошибка №1: считать базовые правила готовой защитой
Набор правил общего назначения — это стартовая политика, а не описание именно вашего сайта. Например, OWASP CRS — открытый набор типовых правил обнаружения атак для ModSecurity и совместимых WAF. Сам проект прямо предупреждает, что правила обычно приходится настраивать с учётом сайта и приложения. Из этого не следует, что любой профиль «по умолчанию» бесполезен: следует другое — его покрытие и влияние нужно проверять на своих маршрутах и обычных действиях пользователей. Универсальный список не знает, что у вас считается допустимым содержимым поиска, загрузки или API-запроса. Перед настройкой полезно выписать основные маршруты, HTTP-методы и форматы, которыми пользуется сайт, а затем проверить, какие из них охватывает политика. Если движок позволяет задавать обработку по пути или типу запроса, это настраивают по документации конкретного продукта. Так проще заметить незакрытый маршрут или несовпадение формата, чем спорить о том, «строгие» ли правила вообще. После крупных изменений приложения эту сверку повторяют.
Я проверяю, какие правила активны, какие части запроса конкретная реализация анализирует и что попало в журнал при совпадении. Если WAF поддерживает CRS, смотрю идентификатор совпавшего правила, его группу и данные, на которых оно сработало. Это переводит спор «защита включена или нет» в проверяемый вопрос: какой запрос дошёл до фильтра, какое правило его обработало и какое действие последовало. Не меняйте сразу весь набор после одного ложного срабатывания: сначала воспроизведите обычную операцию и определите узкое место. Правило нужно оценивать вместе с маршрутом и функцией приложения, а не по красивому статусу в панели. Для разбора сопоставляйте журнал с конкретным запросом: временем, маршрутом, параметром, идентификатором правила и действием, которое указал продукт. Запись об обнаружении и запись о блокировке означают разное; названия статусов сверяйте с документацией производителя. Если журнал показывает лишь сработавшее правило, это не доказательство успешной атаки и не доказательство того, что запрос остановлен. Такой разбор помогает выбрать точечную правку и объяснить её разработчику без предположений о поведении всего сайта.
Ошибка №2: считать нормализацию универсальным переключателем
Проверка кодирования зависит от конкретного WAF, версии движка, выбранного набора правил и способа передачи данных. Один продукт может иметь отдельные преобразования для отдельных правил; другой обрабатывает часть форматов иначе. Поэтому я не обещаю, что любой WAF автоматически декодирует Base64, все варианты URL-кодирования, Unicode и любые вложенные представления. Base64 — не универсальная упаковка запросов к приложению, а наличие символов в необычной записи само по себе ещё не доказывает ни SQL-инъекцию, ни обход фильтра. К примеру, URL-декодирование, разбор JSON и обработка тела формы — разные операции, а правила могут применять преобразования в заданной последовательности. Нельзя переносить описание одного движка на другой или считать, что любые вложенные преобразования выполняются автоматически. Для каждого входного формата выясните, какой компонент разбирает его и где именно включена нужная обработка. Это снимает популярное, но бесполезное ожидание единого переключателя «декодировать всё».
Проверять нужно не абстрактную «глубокую нормализацию», а фактический путь данных: как приложение принимает поле, какой формат разбирает, что из него получает правило и как это видно в журнале. Сопоставьте документацию выбранного WAF с настройками преобразования и парсинга; для формата, который движок не понимает, не приписывайте ему защиту на словах. Тестовые запросы выполняйте на стенде или с явным разрешением владельца, а затем проверяйте результат и в WAF, и в приложении. Один удачный тест показывает только поведение этого сценария, этой политики и этого пути данных. Я сравниваю штатный запрос с контрольным запросом на стенде и смотрю, что увидели приложение и WAF; не запускаю проверки на чужом ресурсе. Для повторяемости сохраняю обезличенные примеры запросов, название правила и результат после правки. Если политика не анализирует определённый тип содержимого, это фиксируют как ограничение защиты и передают владельцу приложения для решения на его стороне. Так вывод описывает реальную границу проверки, а не звучит как обещание, что фильтр понимает любые данные.
- Проверьте обработчики тех форматов, которые принимает приложение.
- Сверьте преобразования с документацией своего WAF.
- Не считайте один тест доказательством полной защиты.
Ошибка №3: включить блокировку и забыть о журнале
Начинать с наблюдения удобно, но режимы у разных продуктов устроены неодинаково. Например, в Azure Application Gateway режим Detection записывает совпадения в журнал и передаёт запрос дальше; он сам по себе запрос не блокирует. В Prevention WAF выполняет заданное политикой действие при совпадении. Значит, слово «мониторинг» описывает способ увидеть работу правил, а не защиту от атаки. Если оставить систему только в обнаружении, журнал будет полезен для настройки, но вредоносный запрос может продолжить путь к приложению. Включение обнаружения без последующего перехода к блокирующему действию оставляет приложение доступным для совпавших запросов. Поэтому ещё до настройки определите, кто читает журнал, как сообщают о важных событиях и где хранится конфигурация правил. Если записи не сохраняются или на них никто не реагирует, «режим наблюдения» быстро становится просто режимом отсутствия решения. Названия и возможности режимов проверяйте у своего поставщика, не ориентируясь на привычную подпись в другой панели.
Я собираю реальные рабочие сценарии: вход, поиск, формы, загрузку файлов, интеграции и API, затем проверяю записи о совпадениях и ложных срабатываниях. В Azure WAF журнал содержит, в частности, идентификатор правила, действие и детали совпадения; для других систем набор полей нужно сверить с их документацией. Если выяснилось, что легитимное поле вызывает ложное срабатывание, сначала рассмотрите узкое исключение для конкретного поля или правила. Глобально выключить проверку проще, чем разобраться, но вместе с раздражающим совпадением вы можете убрать и полезную проверку. Универсального срока «обучения» нет, да и автоматический режим обучения есть не у каждого продукта. Перед включением блокирующего действия я прогоняю не только контрольный SQLi-сценарий, но и основные разрешённые операции, из-за которых возможны ложные совпадения: поиск, вход, сохранение формы и отправку файла, если такие функции есть. Затем проверяю, что в журнале осталось достаточно данных для расследования и что изменения можно откатить. Период наблюдения выбирают по покрытию рабочих сценариев и изменчивости трафика: календарная неделя сама по себе ничего не гарантирует.
- Сверьте действие WAF с его фактическим режимом.
- Сопоставьте совпадения с привычными действиями на сайте.
- Сужайте исключения и проверяйте их повторно.
Условный пример: как разбирать одно срабатывание
Возьмём условный сценарий с компанией ООО «Дельта-Профиль»; это иллюстрация проверки, а не сообщение о подтверждённом инциденте. Пользователь отправляет поисковую форму, а журнал WAF показывает совпадение с правилом для конкретного параметра. Из этой записи нельзя заключить, что база уже прочитана, что была SQL-инъекция или что данные утекли. Она показывает только срабатывание правила на определённое содержимое запроса. Я сначала выясняю, какую страницу и функцию выполнял пользователь, затем сравниваю поле с настройкой правила и проверяю, что получил обработчик приложения. Если есть основания подозревать реальный доступ к данным, это отдельная задача реагирования: сохраняют журналы, проверяют события приложения и базы, а объём доступа определяют по имеющимся следам. Одно срабатывание WAF не позволяет ни подтвердить утечку, ни исключить её. В условном сценарии мы ограничиваем вывод тем, что показывает журнал, и не приписываем компании ущерб или спасение базы без доказательств. Это важное различие между проверкой настройки и расследованием инцидента.
Если обычный поиск ломается из-за ложного срабатывания, я не удаляю всю защиту и не объявляю систему «взломанной». Нужно выяснить, какой параметр и правило дали совпадение, оценить область политики и выбрать минимальное изменение. В документации Azure, например, описаны исключения для конкретных атрибутов запроса; широкое отключение правила может ослабить проверки для других сценариев. После изменения повторно проходят именно те функции, которые могли задевать исключение, и отдельно проверяют, что блокирующее правило всё ещё реагирует на контрольный тест. Результатом такого разбора будет проверяемое изменение политики, а не громкое обещание о полной неуязвимости. Исключение тоже требует проверки: в зависимости от продукта оно может относиться к полю, набору правил или более широкому участку политики. Сначала определите область действия и проверьте, не используется ли она другими страницами или приложениями. После узкой правки повторите штатный запрос, который давал ложное совпадение, и разрешённый контрольный тест, на котором правило должно сработать. Если после изменения проверка перестала видеть слишком широкий набор значений, исключение нужно сузить или отменить.
Как закрывать SQL-инъекцию и проверять WAF
Когда есть подозрение на SQL-инъекцию, я ищу причину в коде: где строится запрос, какие значения приходят от пользователя и отделены ли они от SQL-представления параметрами. Динамические имена таблиц, столбцов и направление сортировки нельзя безопасно передать как обычные значения параметров; для таких частей используют фиксированный список допустимых вариантов. Хранимая процедура тоже не спасает автоматически, если внутри неё собирают SQL небезопасной конкатенацией. После исправления проверяют вызывающий путь и похожие места, где тот же шаблон повторяется. Для значений формы используйте параметры драйвера базы, а допустимые имена сортировки или полей задавайте явным перечнем, выбранным приложением. Не считайте строковую очистку универсальной заменой этому разделению. Для поиска мест склейки SQL полезно проследить путь от поля ввода до конкретного вызова базы и проверить соседние ветви, включая обработчики отчётов и фильтров. Так исправление затрагивает источник проблемы, а не только один запрос, замеченный WAF.
Параллельно ограничивают права пользователя базы, которым пользуется приложение, и настраивают WAF как дополнительную проверку. Если применяется OWASP CRS, учитывают его общие правила и документированный механизм настройки исключений под конкретное приложение. Затем проверяют логи, тестируют легитимные функции и выполняют согласованные проверки защиты после изменения политики. Я сохраняю исходную конфигурацию, фиксирую изменённое правило и проверяю обновления набора правил по документации поставщика. Порядок простой: исправить небезопасный запрос, ограничить последствия учётными правами, проверить, что WAF видит нужные запросы, и убедиться, что исключение не стало дырой шире исходного срабатывания. Каждое изменение политики фиксируйте вместе с причиной, областью действия и проверенными сценариями; иначе следующая настройка может случайно вернуть старое исключение или отключить нужное правило. При обновлении набора правил повторяйте проверку тех маршрутов, которые приложение реально использует, и сравнивайте журнал до и после изменения. Если найденная ошибка относится к коду, передавайте разработчику точный путь данных и исправляйте источник; WAF не должен становиться единственным местом, где уязвимость «прикрыта».
- Передавайте значения SQL отдельными параметрами.
- Ограничьте права подключения приложения к базе.
- Проверьте журналы и повторите разрешённые тесты после настройки.
Частые вопросы
Гарантирует ли WAF защиту от SQL-инъекций?
Нет. WAF фильтрует запросы по возможностям продукта и его правилам, но не доказывает безопасность кода. Значения в SQL нужно передавать параметрами; WAF остаётся дополнительным слоем.
Режим Detection блокирует запросы?
Это зависит от продукта. В Azure Application Gateway Detection записывает совпадение в журнал и пропускает запрос дальше. Проверьте описание режима в документации своего WAF.
Как поступить с ложным срабатыванием?
Найдите совпавшее правило и поле в журнале, воспроизведите штатную операцию и рассмотрите узкое исключение. Широкое отключение правила может убрать проверку для других запросов.
Нужно ли обучать WAF ровно неделю?
Универсального срока нет. У некоторых продуктов есть функции обучения, у других их нет. Ориентируйтесь на покрытие основных сценариев приложения и анализ журналов, а не на фиксированное число дней.
Что надёжнее всего снижает риск SQL-инъекции?
Параметризованные запросы, безопасная обработка динамических частей SQL и минимально необходимые права учётной записи базы. WAF помогает фильтровать часть атак, но не заменяет эти меры.
Источники
- OWASP: SQL Injection Prevention Cheat Sheet — Первичный источник: параметризация значений SQL и ограничение привилегий учётной записи приложения. https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html
- OWASP CRS: Documentation — Официальная документация набора общих правил, совместимых с ModSecurity и другими WAF; описывает его роль как одного из уровней защиты. https://coreruleset.org/docs/
- OWASP CRS: Installation — Официальная инструкция указывает, что набор правил может требовать настройки исключений с учётом сайта и приложения. https://coreruleset.org/docs/1-getting-started/1-1-crs-installation/
- Microsoft Learn: Monitor logs for Azure WAF — Формат журналов Azure Application Gateway WAF: идентификатор правила, действие и детали совпадения. https://learn.microsoft.com/en-us/azure/web-application-firewall/ag/web-application-firewall-logs
- Microsoft Learn: Troubleshoot WAF false positives — Разбор исключений и ложных срабатываний; широкое отключение правила может открыть уязвимость для других сценариев. https://learn.microsoft.com/en-us/troubleshoot/azure/web-application-firewall/web-application-firewall-troubleshoot



