ModSecurity: не работает setenv в SecAction
Я пытаюсь отладить проблему с ModSecurity. Использование ModSecurity 2.9.2 на Apache 2.4.33. Я максимально упростил ситуацию, но наткнулся на стену. Я работаю в конфигурации виртуального хоста. Вот что я пытаюсь сделать:
SecAction "pass,setenv:TESTPAGE=1,nolog,id:10001001"
Header always set X-Debug "IsTest" env=TESTPAGE
Без других правил это всегда должно устанавливать заголовок X-Debug, но это не так. Чтобы попытаться выяснить, почему, сначала я удалил SecAction и просто сделал это:
RewriteRule .* - [E=TESTPAGE]
Header always set X-Debug "IsTest" env=TESTPAGE
Конечно же, заголовок был установлен в этом случае, так что я знаю, что заголовки работают и переменные среды могут быть установлены / проверены. Тогда я попробовал это:
SecAction "deny,status:503,setenv:TESTPAGE=1,nolog,id:10001001"
И действительно, меня заблокировали http-кодом 503, поэтому я знаю, что SecAction обрабатывается. Учитывая эти две вещи, единственная возможность состоит в том, что ModSec не может установить переменную среды, как это должно быть, но я не знаю ни одной причины, почему это должно иметь место.
Редактировать #1
По какой-то причине настройка "запретить" больше не блокирует обработку страницы. Таким образом, я все еще получаю набор кодов состояния или, если я сохраняю "deny", но удаляю директиву "status", я получаю код 403, который, как я полагаю, используется по умолчанию для "deny", но сама страница все еще загружается. Не уверен, что это имеет ту же причину, что и переменная окружения не установлена.
1 ответ
Оказалось, что это произошло из-за внутренней перезаписи mod_rewrite, из-за выполнения этого в контексте приложения Symfony2, которое перезаписывает все запросы к своему контроллеру app.php. То же самое происходит в CMS, такой как WordPress, который переписывает все в index.php, или в других схемах предварительного преобразования URL-адресов, которые переписывают URL-адреса внутри. (Обратите внимание, что это не проблема с перенаправлениями браузера, поскольку они приводят к появлению всего нового запроса, только с внутренними перезаписями.) По существу, после того, как завершается ваше последнее переписывание, логика apache htaccess и configuration снова запускается, и она при этом запускается что ваши конечные переменные окружения и тому подобное установлены. Так что, если переменная была установлена до перезаписи, она не будет доступна позже (например, когда я пытаюсь установить заголовок в вопросе здесь).
Хотя эти две строки в вопросе смежны...
SecAction "pass,setenv:TESTPAGE=1,nolog,id:10001001"
Header always set X-Debug "IsTest" env=TESTPAGE
Первая строка выполняется во время фазы тела запроса (modsec Phase 2) в соответствии с настройками по умолчанию, так как я не указал фазу. Перезапись в app.php (из-за не показанного правила.htaccess) происходит позже. И поэтому, когда заголовок установлен, переменная больше не присутствует.
Однако все переменные перед перезаписью по-прежнему доступны с префиксом redirect_. Чтобы это исправить, мне нужно написать так:
SecAction "pass,setenv:TESTPAGE=1,nolog,id:10001001"
Header always set X-Debug "IsTest" env=REDIRECT_TESTPAGE
Или, если я не уверен, будет ли запрос перенаправлен, я мог бы использовать обе версии:
SecAction "pass,setenv:TESTPAGE=1,nolog,id:10001001"
Header always set X-Debug "IsTest" env=TESTPAGE
Header always set X-Debug "IsTest" env=REDIRECT_TESTPAGE
(Может быть способ объединить их; не уверен, что вы можете использовать логику ИЛИ в выражениях apache 'env; пожалуйста, прокомментируйте, если так!)
Изменить: Относительно "Отказ" больше не работает, это также было связано с перенаправлениями в некотором роде. Мод безопасности по умолчанию выдавал ошибку 500, но страницы ошибок по умолчанию 500.shtml не существовало. Поэтому среда перехватывала этот запрос и отправляла его обратно в app.php, который затем просматривал URL-адрес запроса и продолжал загружать первоначально запрошенную страницу, несмотря на ошибку. Если настроенный ErrorDocument существует, deny работает правильно, и этот документ отображается.