【问题标题】:Safely passing a password (a stack trace issue)安全地传递密码(堆栈跟踪问题)
【发布时间】:2016-01-08 15:41:10
【问题描述】:

我注意到我的开发服务器的 php_errors.log 文件在我之前的错误修复狂欢之后重新出现,但这次我注意到一些相当令人不安的事情......

[06-Jan-2016 01:29:29 UTC] PHP 致命错误:未捕获的 PDOException:SQLSTATE[HY000] [2002] /home/niet/public_html/classes/DB.class.php 中没有此类文件或目录:14
堆栈跟踪:
#0 /home/niet/public_html/classes/DB.class.php(14): PDO->__construct('mysql:host=loca...', 'niet', '我的实际密码!强>',数组)
#1 /home/niet/public_html/classes/DB.class.php(47): DB::connect()
#2 ...

不用说,这是一个问题。所以基本上,我的问题很简单:

如何将字符串传递给函数,如果出现问题,它不会显示在堆栈跟踪中?

为了聪明,我尝试了这个:

new PDO(
    "mysql:host=localhost.....",
    "niet",
    new class { public function __toString() { return "correct horse battery staple"; }}
);

虽然它成功连接到数据库,但抛出的异常(例如错误密码)仍然显示字符串值,而不是匿名类。如果我使用“普通”类尝试从跟踪中“隐藏”变量,则会出现类似问题。

【问题讨论】:

  • xkcd 参考 +1。为什么堆栈跟踪中的密码会出现问题?当然,有权访问服务器日志的人也有权访问配置文件?
  • 也许您可以使用 try 和 catch.. php.net/manual/en/language.exceptions.php 并在生产中始终禁用 error_reporting..
  • @JimL 虽然这是真的,但我不喜欢可能需要保持安全的信息最终被丢弃在不应该出现的地方的想法。例如,这里是我的 DB 密码,但如果是用户的帐户密码在跟踪中结束了怎么办?还是他们的个人信息?
  • 您确定不会将用户密码存储在数据库中吗?
  • 简单的答案——你不能将一个字符串传递给一个函数,这样它就不会显示在堆栈跟踪中——尽管你可以稍微配置一下 PDO。您还可以提出您无法防范的不同灾难场景,这些场景可能会破坏时空结构。到目前为止,您肯定知道,您可以做的是使用已知的最佳实践来最大程度地减少安全问题 - 例如,我将使用 SSL 和 MySQL 密码(不是 HTTP SSL,而是 PHP > MySQL SSL)

标签: php


【解决方案1】:

您可以设置自己的异常处理程序并只打印异常消息而不是堆栈跟踪,例如

function exception_handler($e) {
    echo "<b>Exception in file: </b>" . $e->getFile() . "<br>";
    echo "<b>Exception on line: </b>" . $e->getLine() . "<br>";
    echo "<b>Exception message: </b>" . $e->getMessage();
}

set_exception_handler('exception_handler');

所以你仍然会得到一个有用的错误消息,但不包含任何敏感数据:

文件中的异常: C:\xampp\htdocs\path\file.php
在线异常: 220
异常消息: SQLSTATE[HY000] [1045] 用户'root'@'localhost'的访问被拒绝(使用>密码:YES)

【讨论】:

  • 好吧,我可以做到,事实上我已经有了一个全局异常处理程序。但是没有痕迹,我怎么能希望找到错误的原因呢? ;)
  • @NiettheDarkAbsol 您可以打印文件和exception 的行,这样您就可以确切地知道它来自哪里。但你只是不输出跟踪。
  • @NiettheDarkAbsol 使用异常处理程序更新了答案,以便您确切知道错误在哪里。
  • 尽管如此......但错误通常是由跟踪中某处传递的参数不是预期的结果引起的。
【解决方案2】:

在生产环境中,您应该禁用任何错误消息。在您的 PHP.ini 文件中设置 display_errors = off 以不透露有关您服务器的任何详细信息。

此外,您可以设置 $pdo-&gt;setAttribute(PDO::ERRMODE_SILENT) 以使 PDO 静音。您可以查看manual 以获取更多错误代码。

// 编辑:仍然可以在静默模式下记录错误:

$pdo = new PDO($server, $user, $password);

// Let us assume that 'foo' column does not exist
$query  = 'SELECT foo FROM bar';
$result = $pdo->query($query);

// Log error message
if ($pdo->errorInfo()) {
  print_r($pdo -> errorInfo());
}

【讨论】:

  • 错误消息由全局异常处理程序捕获和处理,但我关心的是 PHP 的错误日志记录生成的内部日志。此外,无声错误是有史以来最糟糕的主意:p
  • 其实ERRMODE_SILENT是默认值。您仍然可以在静默模式下记录错误。我相应地更新了我的答案。此外,在生产环境中,您很可能永远不想公开错误消息。
  • 我认为全局异常捕获器在这里仍然是更好的选择 - 如果我真的需要针对数据库错误做一些特定的事情:if( $globalerror instanceof PDOException):3
猜你喜欢
  • 2010-10-09
  • 1970-01-01
  • 1970-01-01
  • 2011-08-07
  • 2020-05-09
  • 1970-01-01
  • 2011-05-25
  • 2011-05-13
  • 1970-01-01
相关资源
最近更新 更多