mod_rewrite 匹配编码的 URL
Posted
技术标签:
【中文标题】mod_rewrite 匹配编码的 URL【英文标题】:mod_rewrite match encoded URL 【发布时间】:2021-11-23 12:20:24 【问题描述】:在我的 Apache 配置中,当查询字符串参数包含特定值时,我想返回 403。一切正常,除非客户端查询字符串以十六进制编码。如何在不输入文字十六进制字符串的情况下使其匹配?
RewriteEngine On
RewriteCond %QUERY_STRING mykey=myval [NC]
RewriteRule .* - [F,L]
然后测试一下:
# Works fine, returns 403
curl -I 'http://localhost/?mykey=myval'
# Does not work, returns 200:
curl -I 'http://localhost/?mykey=%6d%79%76%61%6c'
curl -I 'http://localhost/?%6d%79%6b%65%79=%6d%79%76%61%6c'
谢谢
【问题讨论】:
【参考方案1】:QUERY_STRING
服务器变量保持 % 编码(就像它在请求中一样),与 RewriteRule
模式 匹配的 URL 路径不同,后者是 % 解码的。
但是,在 Apache 2.4 上,您可以使用带有 RewriteCond
指令的 Apache 表达式在进行比较之前对 QUERY_STRING
进行 URL 解码。例如:
RewriteCond expr "unescape(%QUERY_STRING) =~ /mykey=myval/"
RewriteRule ^ - [F]
这将成功匹配?mykey=myval
、?mykey=%6d%79%76%61%6c
和?%6d%79%6b%65%79=%6d%79%76%61%6c
形式的请求。
使用F
时不需要L
标志,因为它是隐含的。如果您只需要在任何 URL 路径上成功(实际上不匹配任何内容),则正则表达式 ^
比 .*
效率略高。
请注意,正则表达式mykey=myval
匹配查询字符串中的任何位置的字符串,因此它可以成功匹配anymykey=myval
和mykey=myvalany
,这可能有问题,也可能没有问题。要消除这种歧义并仅匹配查询字符串中的“key=value”对,那么您需要使用像 (?:^|&)mykey=myval(?:&|$)
这样的正则表达式。
【讨论】:
很好的使用expr
指令
你是 Apache 忍者,谢谢 :) 我很好奇,开发人员是否有理由为这种情况保留查询字符串 %-encoded 而不是 RewriteRule
具有 %-decoded ?我意识到保持未转义的价值是“真实”价值,但一些针对网络管理员的“虚拟证明”保护措施可以帮助数百万人。常见场景:站点管理员想要阻止对 URL 的访问,但不知道恶意用户可以对查询字符串进行简单的 % 编码以绕过 RewriteCond
。以上是关于mod_rewrite 匹配编码的 URL的主要内容,如果未能解决你的问题,请参考以下文章
PHP Mod_rewrite 和 URL 编码符号 - 只能使用其中一个,但不能同时使用?