web.config
我没有使用重写规则,而是一直使用螺旋猿用于模拟 Apache 的.htaccess
功能。
我有一个大型的通用.htaccess
文件,它被应用于整个服务器,作为限制访问传递命令(如联合、删除等)的功能的一部分。
但是,我遇到了一个问题,其中一行代码产生了误报并阻止了对原本正确的 URL 的访问。
失败的 URL 是:http://example.com/union-contracts
使用以下命令web.config
,所有缺失的 URL 都将被推送至index.php
。
<httpErrors errorMode="Custom" existingResponse="Replace">
<remove statusCode="404" subStatusCode="-1" />
<error statusCode="404" path="/index.php" responseMode="ExecuteURL" />
</httpErrors>
返回 403 的 htaccess 规则
RewriteCond %{QUERY_STRING} (;|<|>|'|"|\)|%0A|%0D|%22|%27|%3C|%3E|%00).*(/\*|union|select|insert|drop|delete|update|cast|create|char|convert|alter|declare|order|script|set|md5|benchmark|encode) [NC]
RewriteRule . - [F,L]
最后,我想继续阻止 union,例如,我只需要修改误报行。请注意,我也不希望在我的规则-contracts
中进行硬编码。.htaccess
在记住 URL 是如何生成的之后,我能够在 XAMPP 中的 htaccess 中复制该问题。
在网站访问者端,当访问 URL 时,服务器会生成 404 错误。我过滤出 URL 的最后一部分,并根据该字符串检查数据库以查看它是否与已保存的 URL 匹配,如果匹配,我不会将 404 传递给浏览器,只有在找不到 URL 时才会传递。
当 IIS 生成 404 错误时,URL 变为:
index.php?404;http://example.com:80/union-contracts
但它不会以该格式传递到浏览器。
答案1
我在评论中表达了我的担忧,认为一定有“其他事情”发生了,但无论如何……
很难为一条本来就不应该(读作:“不能”)触发的规则写一个例外——这完全是猜测。毕竟,为什么例外感到荣幸?
由于以下几个“大”原因,该规则应该已经避免了给定的请求:
- 该请求不包含查询字符串。
- 条件中的正则表达式(条件模式) 与 URL 的任何部分都不匹配(即使它在查询字符串中)。
考虑到上面的#2,正则表达式已经包含足够的异常以不匹配给定的请求,那么我们如何实现“另一个”异常?
您可以修改条件模式为了避免出现连字符 ( -
) 跟在单词“union”后面的情况,请使用负面前瞻。 例如:
(;|<|>|'|"|\)|%0A|%0D|%22|%27|%3C|%3E|%00).*(/\*|union(?!-)|select|insert|drop|delete|update|cast|create|char|convert|alter|declare|order|script|set|md5|benchmark|encode)
因此,上述匹配Xunion
,但不匹配Xunion-
,其中X
是第一个字符序列之一交替组(即(;|<|>|'|"|\)|%0A|%0D|%22|%27|%3C|%3E|%00)
)。
或者,当以下任何一个关键字后面有连字符时:
(;|<|>|'|"|\)|%0A|%0D|%22|%27|%3C|%3E|%00).*(/\*|union|select|insert|drop|delete|update|cast|create|char|convert|alter|declare|order|script|set|md5|benchmark|encode)(?!-)
(更新:以下两个建议可能不起作用,因为看起来这些指令只处理后IIS 已重写了 URL。此时 URL 路径只是/index.php
,而不是/union-contracts
。)
或者,修改RewriteRule
,使其在 URL 路径以 开头时不匹配/union-
(尽管这可能会为规则试图阻止的 XSS 尝试提供后门)。例如:
RewriteRule !^/?union- - [F]
(至少在 Apache 上,使用L
该标志时不需要该标志- 它是隐含的。)F
或者,您可以同时创建另一条规则顶部,在现有规则之前,当请求以查询字符串开头且不包含查询字符串的 URL 时,将创建一个例外/union-
(尽管如果另一条规则可信的话,这似乎是矛盾的)。例如:
RewriteCond %{QUERY_STRING} ^$
RewriteRule ^/?union- - [L]
但是,如果文件后面还有其他规则需要以某种方式重写 URL,则这可能会“破坏”请求 - 因为这些不会发生。
我假设 Helicon-APE/mod_rewrite 在目录式上下文(例如,.htaccess
风格语法而不是服务器或者虚拟主机上下文)?尽管这不应该影响上述指令,但事实确实如此。
更新:当 IIS 生成 404 错误时,URL 变为:
index.php?404;http://example.com:80/union-contracts
啊,是的!那个 URL将要被原始条件捕获。因此,似乎 mod_rewrite 指令被处理了后web.config 中的 IIS“重写”!这确实使这些“安全”指令有些多余甚至不正确,因为它们应该根据客户端的初始请求运行。并且……
我过滤出 URL 的最后一部分,然后根据该字符串检查数据库,看它是否与已保存的 URL 匹配
由于您正在主动解析 URL 并仅过滤掉所需的部分,因此这些“安全”检查至少对于这些“404”请求来说似乎是多余的。 (事实上,根据可能直接请求的真实文件(即非 404 请求),这种性质的恶意查询字符串是否会对任何 URL 构成安全威胁?)
上述两个建议修改正则表达式状况排除连字符跟在“union”关键字后面的情况,或者任何关键字,仍然适用于此处,并且似乎可以解决眼前的问题。
您还可以在遇到表单的 URL 时中止所有检查index.php?404;
(即,在 IIS 重写之后)。(我假设所有 mod_rewrite 指令都是类似的“安全”检查?)
例如,将以下内容添加到顶部剧本.htaccess
,前现有指令:
RewriteCond %{QUERY_STRING} ^404;
RewriteRule ^/?index\.php - [L]
当遇到该表单的 URL 时,这应该可以防止任何进一步的处理/index.php?404;......
。(因为无论如何您都会在脚本中解析 URL。)