当您决定返回 403 时,始终返回 404

Posted

技术标签:

【中文标题】当您决定返回 403 时,始终返回 404【英文标题】:Always return a 404 when you decide to return a 403 【发布时间】:2012-05-17 14:23:58 【问题描述】:

这里已经发布了几个关于在特殊情况下返回 404 而不是 403 的问题(例如,.ht* 文件或某个目录),但我不知道如何简单地替换 all 403 响应(“好吧,它存在,但你仍然需要找到方法进入”)和 404(“抱歉,从未听说过”)。我希望有一个简单的解决方案,不需要更新 .htaccess 的正则表达式或其他位以匹配站点更改,只需一个简单的指令:“每当您决定返回 403 时,就返回 404”适用到整个站点,无论配置更改如何。

然后,如果*** .htaccess 包含“Options -Indexes”,并且任何给定目录不包含 index.html(或等效),那么裸目录 URL 将返回 404,但如果我添加了 index.html该目录,相同的裸目录 URL 将返回 index.html,无需更新任何 .htaccess 文件。

我什至不在乎,如果我曾经为目录设置密码,错误的密码是否返回 404(因为 404 -> 403 映射)。在这种情况下,我不会通过返回 404 来隐藏任何内容,但这也不会造成任何伤害。但是,如果有一种方法可以撤消针对特殊情况的一般 403->404 映射(而不是针对特殊情况执行此操作),那可能会更有用。

当然,如果我忽略了某些东西,请纠正我。

编辑:德拉特。我试图在这里写一个高质量的问题,但我在第二段中对“Options -Indexes”行为的描述结果是错误的。没有该行,如果目录中存在裸目录 URL,则会显示“index.html”;否则,它会显示目录的内容。 (如果 index.html 存在,则 /dir 到 /dir/index.html 的转发是 Web 主机的默认设置,除非我弄错了。)添加“Options -Indexes”行会阻止它在公共场合晾晒我的衣服(返回 403,而不是 404,但仍然比暴露 dir 内容更好),但现在即使 index.html 存在,裸目录 URL 也会返回 403。

我希望裸目录 URL“mysite.com/mydir”如果存在则显示 /mydir/index.html,如果不存在则显示“404”,但显然它不仅仅是用 404 替换 403。

【问题讨论】:

您可以发布您当前的配置(.htaccess 和 Apache 配置文件)吗? 实际上,我还没有任何 .htaccess,也没有自己的 Apache 配置文件 (httpd.conf?)。这是一个新的共享 Web 主机,我正试图弄清楚如何进行设置。我假设我的 .htaccess 将包含“Options -Indexes”行,但我什至不确定。 我遇到了同样的问题并使用了重写条件和重写规则。 See my answer to a similar question. 【参考方案1】:

要在此处完成更好的答案之一(如@WebChemist 和@JennyD 所述),解决此问题的一个好方法是从用于处理403 错误的文档中返回404 Not Found。就我个人而言,我会执行以下操作:

.htaccess 在 Web 根目录中(相关摘录):

ErrorDocument 400 /http-errors.php
ErrorDocument 403 /http-errors.php
ErrorDocument 404 /http-errors.php

http-errors.php 在 Web 根目录中(精简的工作示例):

<?php

$status = $_SERVER['REDIRECT_STATUS'];
// If it's a 403, just bump it up to a 404
if ( $status == 403 ) $status++;

$codes = array(
  400 => array( '400 Bad Request', 'The request cannot be fulfilled due to...' ),
  404 => array( '404 Not Found', 'The resource you requested was not found...' ),
  500 => array( '500 Internal Server Error', 'The request was unsuccessful...' )
);

$title = $codes[$status][0];
$message = $codes[$status][1];

header( $_SERVER['SERVER_PROTOCOL'] . ' ' . $title );
echo "<h1>$title</h1>\n<p>$message</p>";

【讨论】:

通过使用ErrorDocument 403 指令,Apache 尚未发送 403 标头 - 对吗?我之所以问,是因为在阅读 headers_sent() 函数时,我发现标头是在构造整个响应之前发送的。虽然普通用户不会注意到,但我可能不希望黑客看到 403 响应,然后是 404。【参考方案2】:

你可以很容易地做一个假的 403 -> 404 通过做

ErrorDocument 403 /404.php

其中 404.php 是您格式化的 404 响应页面,但仍会在响应标头中返回 403。如果要返回 404 标头,可以制作带有返回 404 代码的标头重定向的 403 页面,但重定向可能仍然可见....

不确定您是否可以用纯 .htaccess 进行全面的 403->404 替换

编辑:

玩了一下,你可以尝试 2 个纯 .htaccess 方法:

1) 使任何以斜杠结尾的 url 重定向到索引页面,例如:

RewriteRule ^(.*)/$ /$1/index.php [NC,L]

因此,如果您确实有索引页面,它将显示,但如果没有,它将在缺少索引页面请求时显示 404。如果您省略 [R],则该 url 仍将显示为 / 非 index.php 规范的 SEO 友好 url :) 不能说这不会在其他地方造成问题..

2)

在重写规则中,您可以使用 r=404 返回 404 代码。

RewriteRule ^(.*)/$ - [R=404, NC,L]

然而 RewriteCond %REQUEST_FILENAME !-f 要么 RewriteCond %REQUEST_FILENAME -d

没有帮助,这意味着即使存在索引页面,所有尾随斜杠也会 404。您可以通过在其他 RewriteCond 规则中指定要保护(或忽略)的文件夹来解决此问题,但这并不完全是“自动的”,因为您必须添加 RewriteCond 规则,因为更多文件夹被添加到保护|忽略

【讨论】:

是的,标头可能是最大的问题,因为漏洞利用通常是自动化的。 认为如果您编辑 404.php 脚本以包含状态代码,这可能会起作用。但它的魔力超出了我之前的尝试...... 测试了编辑的示例代码,这些方法将返回 404 的标头响应【参考方案3】:

这是我的 .htaccess 文件中的一个 sn-p,该文件位于我已阻止但允许从 LAN 计算机访问的目录中。每次都返回 404 错误!!

# Turn rewrite engine on
RewriteEngine on
RewriteOptions Inherit

# Make it for a specific directory
# RewriteBase /phpMyAdmin 

# Block everyone except me
RewriteCond %REMOTE_HOST !^192.168.2
RewriteRule .? - [R=404,L]

【讨论】:

【参考方案4】:

据我所知,没有这么简单的指令。这仍然是可能的,但它比你想象的要复杂一些。

您可以使用 ErrorDocument 指令设置对脚本的 403 响应,然后让该脚本以 404 响应而不是 403 响应来响应。 apache.org 有一些提示可能会有所帮助

【讨论】:

【参考方案5】:

即使可能没有一揽子方法来让 403 错误报告 404 错误,但仍有希望。

我怀疑您真正想要的是确保 /~root(以及任何其他现有的非 HTTP 用户)不返回 403,而是返回 404。

Apache 中的 UserDir 指令按设计返回 403。我认为目前无法改变。但是——“UserDir”指令可以在同一个 Apache 文件中多次使用,如下所示:

用户目录 public_html UserDir 禁用 root someuser1 someuser1

该配置将允许使用 UserDir,但也会向所有试图嗅探您系统的人报告珍贵的 404 响应标头。

我从以下链接中找到了这个提示:

http://www.if-not-true-then-false.com/2010/enable-apache-userdir-with-selinux-on-fedora-centos-red-hat-rhel/

我自己在 RHEL 6.3 下的 Apache 2.2.15 中对其进行了测试,并且它可以工作——即使在使用 curl 之类的东西进行测试时也是如此。我也在寻找解决方案。终于找到了我可以使用的东西!

【讨论】:

以上是关于当您决定返回 403 时,始终返回 404的主要内容,如果未能解决你的问题,请参考以下文章

当结果 api 返回 null 或 /403/404/500/503 状态时,Flutter 在小部件中抛出消息

JavaScript 图像预加载和 403 错误

部署时,动态网页始终返回404

对 .htaccess 的请求应返回 404 而不是 403

有没有办法强制 apache 返回 404 而不是 403?

拒绝访问:403 还是 404?