Phi*_*ans 42 apache .htaccess mod-rewrite url-rewriting
.htaccess我今天更新了 Apache(至 2.4.56-1) ,以前可以正常工作的大量重写现在出现了 AH10411 错误,与查询中的空格有关。我正在努力寻找“适当”的解决方案。
用户单击一个链接,例如<a href='FISH%20J12345.6-78919'>clickme</a>- 您可以看到链接 URL 中的空格已被编码为%20。
.htaccess相关服务器目录中的文件包含并执行以下相关指令:
RewriteRule ^(FISH\s*J[0-9\.]+-?\+?[0-9]+)$ myPage.php?sourceName=$1 [L,QSA]
Run Code Online (Sandbox Code Playgroud)
(在上面我检查的是空格,而不是%20,因为浏览器似乎在符合此规则之前将其转换为空格)。
在我更新 Apache 之前,这一直有效;现在用户收到 403 错误,我的 Apache 错误日志报告:
AH10411:重写的查询字符串包含控制字符或空格
这似乎是一个新错误,因为谷歌搜索什么也没找到!
编辑我的页面(例如)将空格更改为下划线并正确处理它并不是真正的选择,因为该设计旨在支持用户能够直接使用他们关心的对象的名称输入 URL。到目前为止,我发现的唯一解决方法有点难看,即在正则表达式中分别捕获源名称的两个部分,因此:
RewriteRule ^(FISH)\s*(J[0-9\.]+-?\+?[0-9]+)$ myPage.php?sourceName=$1+$2 [L,QSA]
^ ^ ^^^
Run Code Online (Sandbox Code Playgroud)
(我$1%20$2最后尝试了一下,也导致了同样的错误。)
对此有更好的解决方案吗?即,当 URL 位于我想要捕获并作为参数传递给底层页面的字符串中时,我“应该”如何处理 URL 中的空格情况?
MrW*_*ite 37
(我最后尝试了$1%20$2,结果也很糟糕)。
这看起来像一个错误。对查询字符串中的空格进行编码应该是有效的。%20您还可以对查询字符串中的空格进行编码(如解决方法中所示)。+
在您的原始规则中,Apache 在进行内部重写时应该对空格进行编码(因为%20)(因为文字空格在 URL 中无效)。然而,Apache 似乎对编码空间犹豫不决(或者不在重写中自动编码 URL)?!
您可以尝试B在原始规则中使用该标志。该B标志告诉 mod_rewrite 在将反向引用应用于替换字符串之前对反向引用进行 URL 编码。然而,这似乎依赖于 Apache 对+查询字符串中的空格进行编码(与%20通常情况相反)。当然,在 Apache 的早期版本中,这只会导致 Apache 将空格编码为%20(not +),但是,由于版本 2.4.26 Apache 引入了一个新标志BNP( backrefnoplus) ,它明确通知 Apache不要使用+,所以您会认为默认情况下,它将使用+. (不幸的是,我现在不能自己测试这一点。)
例如:
RewriteRule ^(FISH\s*J[\d.]+-?\+?\d+)$ myPage.php?sourceName=$1 [B,QSA,L]
Run Code Online (Sandbox Code Playgroud)
(次要的一点......在正则表达式字符类中使用时不需要反斜杠转义文字点。我还将数字范围缩小为简写\d。)
旁白:最后一组数字(由子模式 表示)之前可以同时包含-和吗?看起来应该是其中之一(或者什么都不是)?例如。。+-?\+?[-+]?
对此有更好的解决方案吗?即,当 URL 位于我想要捕获并作为参数传递给底层页面的字符串中时,我“应该”如何处理 URL 中的空格情况?
并非如此(尽管您的解决方案并不严格正确 - 见下文)。在您的特定示例中,仅包含您不需要执行任何操作的空格,因为 mod_rewrite 应该自动对任何无效的 URL 进行 URL 编码。(有一个- - 标志可以显式阻止 mod_rewrite 执行此操作 - 有时需要防止已编码的字符被双重编码。)您始终可以在这种形式的 URL 重写中使用该标志(如上所述)。如果存在其他特殊字符,例如(查询字符串中的特殊字符),则需要使用该标志,否则该字符不会被 URL 编码(实际上会导致 URL 参数值被截断)。NEnoescapeBB&
Run Code Online (Sandbox Code Playgroud)RewriteRule ^(FISH)\s*(J[0-9\.]+-?\+?[0-9]+)$ myPage.php?sourceName=$1+$2 [L,QSA]
您的解决方案的一个问题是您在请求中允许 0 个(即“无”)或更多空格,并在生成的 URL 参数中强制使用单个空格。这与您的原始指令不同,原始指令将保留原始请求中的空格(或缺少空格)。
初始请求中可能有 0 个或多个空格吗?
如果是,并且需要保留这些内容,那么根据您需要的数量重复此规则可能会更容易。您可以实现搜索/替换,但这可能有点矫枉过正。
(在上面我检查的是空格,而不是 %20,因为浏览器似乎在符合此规则之前将其转换为空格)。
RewriteRule 模式匹配的 URL 路径首先进行 URL 解码(% 解码),这就是为什么您需要匹配文字空格而不是%20。这与“浏览器”无关。URL 路径中的任何文字空格%20“必须”进行 URL 编码,就像离开浏览器/用户代理的 HTTP 请求一样,否则它就是无效的。
有一条评论(自已删除),其中用户还在+URL 路径中传递了一个(文字加号),并且似乎期望将其按原样传递到查询字符串(通过内部重写),然后将其视为一个编码空间。然而,使用该B标志(如上所述)将导致文字+被 URL 编码,从而%2b保留文字+- 这通常是正确的行为。但是,如果应按+原样复制,从而将其视为结果查询字符串中的编码空间(而不是文字),那么您可以限制该标志将编码的+非字母数字字符(需要 Apache 2.4.26+)。BIE。排除+.
例如,您可以将编码限制为空格?。例如:
RewriteRule ^(.+)$ index.php?query=$1 "[B= ?,L]"
Run Code Online (Sandbox Code Playgroud)
+将不再在反向引用中编码,因此它在查询字符串中的特殊含义(作为编码空间)仍然适用。
注意:您不能仅对空格进行编码(因为空格不能用作B标志值参数中的最后一个字符),因此不能对附加?字符进行编码。因此,flags 参数需要用双引号括起来,因为空格是参数分隔符。
参考:
Hal*_*aar 16
这是最近的安全修复。
apache2 (2.4.52-1ubuntu4.4) jammy-security; urgency=medium
* SECURITY UPDATE: HTTP request splitting with mod_rewrite and mod_proxy
- debian/patches/CVE-2023-25690-1.patch: don't forward invalid query
strings in modules/http2/mod_proxy_http2.c,
modules/mappers/mod_rewrite.c, modules/proxy/mod_proxy_ajp.c,
modules/proxy/mod_proxy_balancer.c, modules/proxy/mod_proxy_http.c,
modules/proxy/mod_proxy_wstunnel.c.
- debian/patches/CVE-2023-25690-2.patch: Fix missing APLOGNO in
modules/http2/mod_proxy_http2.c.
- CVE-2023-25690
* SECURITY UPDATE: mod_proxy_uwsgi HTTP response splitting
- debian/patches/CVE-2023-27522.patch: stricter backend HTTP response
parsing/validation in modules/proxy/mod_proxy_uwsgi.c.
- CVE-2023-27522
-- Marc Deslauriers <marc.deslauriers@ubuntu.com> Wed, 08 Mar 2023 12:32:01 -0500
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
11477 次 |
| 最近记录: |