我正在尝试调试 ModSecurity 的一个问题。在 Apache 2.4.33 上使用 ModSecurity 2.9.2。我尽可能简化了情况,但遇到了障碍。我正在虚拟主机配置中工作。以下是我正在尝试做的事情:
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"
我确实被 503 http 代码阻止了,所以我知道 SecAction 正在被处理。考虑到这两点,唯一的可能性是 ModSec 未能按应有的方式设置环境变量,但我不知道为什么会这样。
编辑#1
由于某种原因,“拒绝”设置现在不再阻止页面处理。因此,我仍然会获得状态代码集,或者如果我保留“拒绝”但删除“状态”指令,我会得到 403 代码,我认为这是“拒绝”的默认设置,但页面本身仍会加载。不确定这是否与未设置环境变量的原因相同。
答案1
事实证明,这是由于 mod_rewrite 的内部重写造成的,因为在 Symfony2 应用程序的上下文中运行它,它会重写对其 app.php 控制器的所有请求。在将所有内容重写为 index.php 的 CMS(如 wordpress)中,或者在内部重写 URL 的其他 URL 美化方案中,也会发生同样的事情。(请注意,这不是浏览器重定向的问题,因为浏览器重定向会导致整个新请求,只是内部重写。)基本上,在最后一次重写完成后,apache htaccess 和配置逻辑会再次运行,并且在该运行中会设置最终的环境变量等。因此,如果在重写之前设置了变量,则之后它将不可用(就像我尝试在此处的问题中设置标题时一样)。
尽管问题中的这两条线是相邻的......
SecAction "pass,setenv:TESTPAGE=1,nolog,id:10001001"
Header always set X-Debug "IsTest" env=TESTPAGE
由于我没有指定阶段,因此默认情况下第一行在请求主体阶段(modsec 阶段 2)运行。之后将重写 app.php(由于未显示的 .htaccess 规则)。因此,当设置 Header 时,变量不再存在。
但是,所有重写前的变量仍然可用,带有“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”语句中使用 OR 逻辑;如果可以,请发表评论!)
编辑:至于“拒绝”不再起作用,这在某种程度上也是由于重定向造成的。Mod Security 默认抛出 500 错误,但默认 500 错误页面 500.shtml 不存在。因此,框架拦截该请求并将其发送回 app.php,然后 app.php 查看请求 URL,并继续加载最初请求的页面,尽管存在错误。如果配置的 ErrorDocument 存在,则拒绝正常工作并显示该文档。