apache rewriterule 默认不匹配查询字符串(如?key=secret),必须用rewritecond %{query_string}检查;%{query_string}值为原始编码格式,需按编码后形式正则匹配,且须配合[f]标志返回403。

Apache RewriteCond 为什么匹配不到 URL 参数
直接用 RewriteRule 匹配不到 ?key=secret 这类参数,因为默认只处理路径部分(/path),不包含查询字符串。必须显式用 RewriteCond 检查 %{QUERY_STRING} 变量。
常见错误是写成:RewriteRule ^/admin.*\?token=.* - [F] —— 这根本不会生效,? 在正则里不是字面量,且 RewriteRule 不解析查询串。
- 所有参数过滤必须通过
RewriteCond %{QUERY_STRING}配合RewriteRule实现 -
%{QUERY_STRING}值是原始未解码的(比如空格是+,中文是%E4%BD%A0),正则要按编码后形式写 - 如果想匹配多个参数组合(如同时含
token和debug),需用多个RewriteCond并用[AND]
过滤含敏感参数的请求并返回 403
典型场景:屏蔽带 phpinfo、passwd、env 等参数名或值的请求。关键是用 [F] 标志,且确保规则在正确作用域(.htaccess 或虚拟主机配置中)生效。
示例:拒绝任何含 cmd= 或 exec= 的请求
RewriteCond %{QUERY_STRING} (cmd|exec)= [NC]
RewriteRule ^ - [F]
-
[NC]必须加,否则大小写敏感(CMD=就绕过了) -
^ -表示“匹配任意路径,不做重写,只执行标志”,比写具体路径更安全 - 放在
.htaccess时,需确认AllowOverride FileInfo已启用,否则整个规则被忽略
只过滤特定路径下的参数(如 /api/)
避免全局误杀,应限制作用范围。不能只靠 RewriteCond,得让 RewriteRule 的模式先匹配路径,再结合条件判断参数。
示例:仅当请求路径以 /api/ 开头,且参数含 debug=true 时拦截
RewriteCond %{QUERY_STRING} debug=true [NC]
RewriteRule ^/api/ - [F]
- 注意顺序:
RewriteCond必须紧挨着它对应的RewriteRule,中间不能插其他规则 - 路径匹配用
^/api/而非^api/,否则可能匹配到/xapi/这类意外路径 - 如果应用跑在子目录(如
https://example.com/app/),RewriteRule的模式要对应上下文路径,.htaccess中通常用相对路径^api/,但需配合RewriteBase
过滤参数值中的 base64 编码或十六进制绕过
攻击者常把敏感词 base64 编码(如 cmd=Y2F0IC9ldGMvcGFzc3dk)或 hex 编码(cmd=%63%61%74%20%2f%65%74%63%2f%70%61%73%73%77%64)来绕过简单关键词匹配。Apache 默认不自动解码查询字符串,所以得手动覆盖。
- 无法用纯
RewriteCond解码 base64,但可匹配常见编码特征,例如:RewriteCond %{QUERY_STRING} [a-zA-Z0-9+/]{20,}={0,2}(粗筛 base64 样式) - 对 hex 编码,可用
%{THE_REQUEST}变量,它包含原始 HTTP 请求行(含未解码的 URL),例如:RewriteCond %{THE_REQUEST} \.php\?[^\ ]*cmd=[^\ ]* - 真正防住编码绕过,得配合外部脚本或改用 ModSecurity,Rewrite 模块能力有限
参数过滤这事,越往后越容易漏——URL 编码变体多、大小写混用、分隔符替换(cmd=xxx → cmd%3Dxxx)、参数顺序干扰……别指望几行 RewriteCond 覆盖所有情况。









