【问题标题】:Is this method good/secure enough for showing errors to users? - PHP这种方法是否足够好/安全,可以向用户显示错误? - PHP
【发布时间】:2009-02-19 10:56:05
【问题描述】:

我正在开发一个网站,由于用户输入或其他原因,我需要显示一些错误消息。 为此,我有一个名为 error.php 的页面,我使用 $_GET 获取错误号。所有错误信息都存储在一个数组中。

例子:

header( 'Location: error.php?n=11' ); 

但我不希望用户在 URL 中输入错误代码并查看所有其他错误消息。 为了防止这种情况,我认为我可以将引用页面列入白名单,并且仅在在我的白名单中找到引用者时才显示错误消息。

应该和这个差不多(还没有测试过;))

$accept = false;
$allowedReferer = array (0=>'page1.php', 'page2.php');
if (in_array($_SERVER['HTTP_REFERER'], $allowedReferer )) {$accept = true;}
if ($accept) { $n=$_GET['n'];echo "Error: " . $errorList[$n];}

这种方法是否足以避免间谍用户

我正在用 PHP5 做这个

谢谢

【问题讨论】:

    标签: php error-handling http-referer


    【解决方案1】:

    不,它不是远程安全的:HTTP Referer 标头很容易被欺骗,也不是必需的标头。我建议您阅读 this article 以获取利用代码(用 PHP 编写)的示例,或下载 this add-on 供 Firefox 使用您自己的浏览器来进行自己的操作。

    此外,您的$allowedReferer 数组应包含完整 URL,而不仅仅是脚本名称,否则该代码也可以从远程引用中被利用,例如来自

    http://www.example.org/page1.php
    

    总结:您不能在不要求身份验证的情况下限制对任何公共网络资源的访问。

    【讨论】:

      【解决方案2】:

      您可以简单地“就地”显示错误,而不是重定向,例如就像用类似的东西调整你现在的代码一样简单

      if ($error_condition)
      {
          $_GET['n']=11;
          include "/path/to/error.php";
          exit;
      }
      

      在实践中它可能会更复杂一些,但想法是一样的 - 用户会看到一条错误消息而无需重定向。确保输出某种错误标头,例如header("HTTP/1.0 401 Bad Request") 告诉浏览器它并没有真正看到请求的页面。

      如果您确实想要重定向,那么您可以通过包含错误编号的哈希值和只有您的代码知道的盐来创建一个“防篡改”URL,例如

      $n=11;
      $secret="foobar";
      $hash=md5($n.$secret);
      $url="http://{$_SERVER['HTTP_HOST']}/error.php?n={$n}&hash={$hash}";
      

      现在您的 error.php 可以检查是否正确创建了提供的哈希。如果是,那么它很可能是由您的代码而不是用户创建的。

      【讨论】:

        【解决方案3】:

        您不应使用外部重定向来访问错误页面。我的 PHP 结构是这样的:

        我有一个包含在每个页面中的通用文件,具有通用功能:处理登录/注销、设置常量等。有一个 error() 函数,您可以将错误信息传递给它将显示错误页面并退出。另一种方法是使用 index.php?include=pagename.php 习惯用法来实现通用功能,但我发现这更加不稳定且容易出错。

        如果您从外部重定向客户端(有时您显然需要这样做),则永远不要依赖通过该机制传递的信息。像所有用户输入一样,它本质上是不可信的,应该非常谨慎地进行清理和处理。也不要使用 cookie(同样的问题)。如果您需要在请求之间保留信息,请使用会话。

        【讨论】:

          【解决方案4】:

          HTTP_REFERER 可以被那些有足够激励措施的人轻易欺骗(telnet 是那里的首选工具),因此不应该被信任。

          无论如何,错误消息都不应该透露任何关键信息,因此我建议您将错误消息设计为可以显示给任何人的方式。

          或者使用随机散列来识别错误(而不是 11,使用 98d1ud109j2 等),这将存储在某个关联数组的中心位置:

          $errors[A_VERY_FATAL_ERROR] => "308dj10ijd"

          【讨论】:

            【解决方案5】:

            为什么不直接包含错误消息脚本?并且要摆脱以前的输出数据,请使用output control 对其进行缓冲并在出错时将其清除:

            if ($error) {
                ob_clear();
                $errorCode = 11;
                include 'error.php';
                exit;
            }
            

            【讨论】:

              【解决方案6】:

              为什么不包含错误页面,而不是重定向到错误页面。您可以使用 .htaccess 限制对包含错误内容的 php 文件的目录的访问:

              RedirectMatch 404 ^error-pages/*$
              

              在错误页面中,您可以拥有显示错误的可包含页面。

              使用这种方法,您可以确保没有人可以直接访问错误页面目录中的页面,但您仍然可以将它们包含在可公开访问的脚本中。

              【讨论】:

                【解决方案7】:

                如果您在发送标头之前处理错误,您可以轻松地创建一个函数来输出带有内容的基本 html 页面,然后立即退出。这样就不需要任何其他页面(我猜是功能页面除外)。

                就是检查有没有问题,如果有问题,调用函数就行了。

                我使用这样的函数,它甚至会在调用时写入数据,所以我有自己的错误日志...

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 2013-01-05
                  • 2013-09-20
                  • 2012-06-15
                  • 1970-01-01
                  • 2014-08-16
                  • 1970-01-01
                  • 2013-03-02
                  • 2012-05-06
                  相关资源
                  最近更新 更多