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 уже пропускается код:
Итого, получаем полноценный вектор эксплуатации:
1 |
/waf-bypass.php?page=BYPASS%00")});alert(1);$(document).ready(function%20(){%2f%2f |
Вот как результат выглядит на странице:
Причина
Ошибка таится в модуле постфильтрации для защиты от 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).