In English: https://blog.deteact.com/bitrix-waf-bypass/

UPD: Присвоен идентификатор CVE-2020-13758

Бывает, что при проведении XSS отражённого типа параметры попадают прямо в тело тега script. Обычно это означает, что эксплуатация тривиальна: не помешает кодирование скобок, не помешают многие фаерволы, в том числе ныне почивший Chrome XSS Auditor. Но в CMS Bitrix на этот случай есть свой встроенный проактивный фильтр (WAF), принцип работы которого при защите от XSS аналогичен XSS Auditor.

WAF bypass

При фаззинге сервиса Mail.ru в рамках Bug Bounty столкнулся с такой точкой входа, где GET параметр попадал в тело тега <script>…</script>. Но сделать простой PoC не удалось, поскольку приложение было построено с использованием Bitrix, и был активирован модуль WAF.

Любые попытки вставить какой-нибудь интересный код заканчивались заменой всего скрипта на заглушку <!— deleted by Bitrix WAF —>.

Оказалось, что для нейтрализации этой защиты достаточно передать в уязвимом параметре null byte (%00).

Для демонстрации развернём тестовое приложение на CMS Bitrix с активированным модулем WAF и добавим следующий код в одну из страниц (/waf-bypass.php):

Если в уязвимый параметр page передать кавычку (закрывающую строку) и вызов alert (как и любой другой функции), то WAF вырезает весь скрипт:

В ходе фаззинга выяснилось, что обойти защиту очень просто — до закрывающейся кавычки вводим null byte (%00) и WAF уже пропускается код:

Итого, получаем полноценный вектор эксплуатации:

Вот как результат выглядит на странице:

Причина

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

При этом по какой-то причине из значений параметров вырезается нулевой байт, так что в нашем случае при сравнении тела страницы с параметрами не будет выявлено вхождений (ведь в теле есть \x00, а в параметрах нет).

Уязвимая строка в файле ./bitrix/modules/security/classes/general.post_filter.php/post_filter.php, где в методе addVariable происходит вырезание нулевого байта chr(0):

Сам поиск пользовательских данных в теле скрипта происходит в функции isDangerBody, и здесь в функцию findInArray передаётся нетронутое значение $body и массив параметров, из которых вырезан нулевой байт:

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

Конкретно в данном случае для исправления ошибки в самом WAF можно убрать вызов str_replace из функции addVariable. При этом на всякий случай стоит добавить проверку на наличие нулевого байта в содержимом (не зря же разработчики Bitrix когда-то добавили этот вызов str_replace).

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *