【问题标题】:Always return a 404 when you decide to return a 403当您决定返回 403 时,始终返回 404
【发布时间】: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.

标签: security http .htaccess http-status-code-403


【解决方案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 之类的东西进行测试时也是如此。我也在寻找解决方案。终于找到了我可以使用的东西!

      【讨论】:

        猜你喜欢
        • 2015-11-10
        • 2014-07-08
        • 2021-09-03
        • 2016-12-08
        • 2021-06-27
        • 2017-07-20
        • 2018-12-05
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多