这种方法是否足够好/安全,足以向用户显示错误? - PHP

时间:2009-02-19 10:56:06

标签: php error-handling http-referer

我正在开发一个网站,由于用户输入或其他原因,我需要显示一些错误消息。 为此,我有一个名为 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

由于

7 个答案:

答案 0 :(得分:8)

不,它不是远程安全的:HTTP Referer标头对于欺骗是微不足道的,也不是必需的标头。我建议您阅读this article以获取利用代码(使用PHP编写)的示例,或者下载this add-on以便Firefox在您自己的浏览器中自行完成。

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

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

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

答案 1 :(得分:5)

而不是重定向,您可以简单地“就地”显示错误 - 例如简单的事情就像使用

之类的东西调整你现有的代码一样简单
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可以检查是否正确创建了提供的哈希。如果是,则很可能它是由您的代码创建的,而不是用户。

答案 2 :(得分:4)

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

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

如果您从外部重定向客户端(有时您显然需要这样做),则永远不要依赖通过该机制传递的信息。像所有用户输入一样,它本身就不值得信任,应该进行消毒处理并极其谨慎地对待。不要使用cookies(同样的问题)。如果您需要在请求之间保留信息,请使用会话。

答案 3 :(得分:1)

那些有足够激励的人可以轻易地欺骗

HTTP_REFERERtelnet是那里的首选工具),不应该被信任。

错误消息永远不应该揭示任何关键的内容,因此我建议您设计错误消息,以便可以向任何人展示。

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

$errors[A_VERY_FATAL_ERROR] => "308dj10ijd"

答案 4 :(得分:1)

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

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

答案 5 :(得分:0)

而不是重定向到错误页面,为什么不包含错误页面。您可以使用.htaccess:

限制对包含包含错误内容的php文件的目录的访问
RedirectMatch 404 ^error-pages/*$

并且在错误页面内,您可以使用包含显示错误的页面。

使用此方法,您可以确定没有人可以直接访问error-pages目录中的页面,但您仍然可以将它们包含在可公开访问的脚本中。

答案 6 :(得分:0)

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

就像检查是否存在问题一样简单,如果有问题,只需调用该函数。

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