ModSecurity 3.0.17 закрывает семь уязвимостей, включая обход проверки имён загружаемых файлов

ModSecurity

Открытый проект OWASP ModSecurity раскрыл семь уязвимостей своего движка. Часть из них позволяет обойти правила фильтрации трафика, одна ведёт к отказу в обслуживании, ещё одна открывает наружу данные, которые фильтр обязан был скрыть. Затронуты обе ветки продукта: третья, известная как libmodsecurity3, и вторая. Администраторам предлагают обновиться до 3.0.17 либо до 2.9.15 в зависимости от установленной ветки. ModSecurity работает рядом с Apache, Nginx и Microsoft IIS, поэтому речь идёт о защитном слое множества сайтов, интернет-магазинов и внутренних систем.

Детали уязвимостей

Первая уязвимость высокого уровня опасности касается загрузки файлов составными запросами (multipart), когда тело обращения делится на несколько частей. Стандарт RFC 2231 разрешает указывать имя файла дважды: в обычном поле и в расширенном параметре, где отдельно прописаны кодировка и язык. Движок ModSecurity разбирает только обычное поле. Серверные платформы на Go, Python, Node.js и Java устроены иначе, они предпочитают расширенное значение. Исключением оказался PHP: он читает обычное поле и потому под обход не попадает. Злоумышленник отправляет безобидное имя в первом параметре и опасное во втором. Фильтр видит картинку с привычным расширением и пропускает запрос. Приложение записывает на диск файл под именем из расширенного параметра. Если каталог загрузок доступен через веб, следствием становится выполнение произвольного кода на сервере. Правила, которые блокируют исполняемые расширения и запрещённые типы файлов, в такой схеме не срабатывают.

Две уязвимости средней степени опасности затрагивают преобразования, на которые опираются сигнатуры. Одно из них удаляет комментарии, чтобы привести запрос к нормальному виду и найти внедрение SQL-кода или межсайтовый скриптинг. Ошибка в реализации приводит к тому, что два комментария подряд не вычищаются: первый исчезает, второй остаётся на месте. Вставки между ключевыми словами запроса доживают до правил и до приложения. Тот же участок кода читает один байт за границей буфера, если закрывающая последовательность стоит в самом конце строки. Второе преобразование расшифровывает значения в кодировке Base64, чтобы проверить их содержимое. При встрече с блоком, у которого испорчено выравнивание, движок стирает весь результат декодирования, а не только повреждённую часть. Признака ошибки при этом не появляется. Достаточно добавить одну лишнюю группу символов в любое место строки, и правило проверит пустое значение.

Третья уязвимость связана с библиотекой регулярных выражений PCRE2 и оператором глобального поиска совпадений. Правила фильтрации задают предел вычислений при разборе сложных шаблонов. Когда предел исчерпан, движок должен сообщить о неполной проверке и передать управление дополнительному правилу. Вместо этого ошибка превращается в обычный результат "совпадений нет". Запрос, который следовало отклонить, проходит насквозь. Проявляется проблема там, где правила применяют глобальный поиск к данным от пользователя и полагаются на признак исчерпания предела. Проект относит её к среднему уровню опасности.

Уязвимость CVE-2026-73857 связана с разбором XML-тела запроса. Обработчик обращается к указателю, который не получил значения, и записывает по адресу, подобранному атакующим. Одного подготовленного обращения достаточно, чтобы уронить рабочий процесс веб-сервера, вытащить содержимое памяти или изменить ход выполнения программы вплоть до запуска чужого кода. Условие для атаки узкое: разбор XML в параметры запроса должен быть включён, а по умолчанию он выключен. Проблема появилась в версии 3.0.15 и живёт в 3.0.16 и в текущей ветке разработки. Более ранние выпуски третьей ветки и вторая ветка не затронуты.

Ещё одна уязвимость высокого уровня опасности позволяет обойти проверку тела ответа. Настройки перечисляют типы содержимого, которые подлежат разбору, и сравнение идёт по точному совпадению символов. Сервер, вернувший тип с заглавными буквами вместо строчных, не попадает в список. Проверка тела ответа пропускается целиком, правила не срабатывают, а ответ уходит клиенту как есть. В журнале остаётся запись о том, что разбор не проводился. По умолчанию в перечень входят только HTML, простой текст и XML, поэтому ответы в формате JSON не проверяются вовсе. Практический результат - утечка паролей к базе данных, ключей и отладочной информации, которую фильтр должен был задержать. Номер уязвимости - CVE-2026-73856.

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

Не у всех опубликованных отчётов есть CVE-идентификаторы. Проект пояснил, что запросы на их присвоение отправлены через GitHub и остаются необработанными. Отсутствие номера не означает, что проблема безвредна, речь идёт лишь о бюрократической задержке. Администраторам стоит обновиться до 3.0.17 или 2.9.15, проверить правила обработки загрузок, протестировать обнаружение данных в кодировке Base64 и попыток прятать полезную нагрузку в комментариях. Разбор XML в параметры запроса лучше держать выключенным, если он не нужен приложению. За появлением остальных номеров имеет смысл следить по бюллетеням проекта.

Все семь проблем лежат в одном слое: в разборе входных данных и в их приведении к нормальному виду перед сверкой с сигнатурами. Межсетевой экран для веб-приложений остаётся полезным инструментом, но его собственные парсеры и преобразования становятся такой же поверхностью атаки, как и защищаемое приложение. Пока обновления не установлены, доверять фильтру как единственной преграде не стоит.

Ссылки

Комментарии: 0