【问题标题】:How to hide only sensitive arguments in PHP's debug_backtrace?如何在 PHP 的 debug_backtrace 中仅隐藏敏感参数?
【发布时间】:2021-09-03 14:18:45
【问题描述】:

考虑以下代码。如果发生异常,跟踪(将被记录并存储在数据库中)将包括敏感的password 数据。在这种情况下如何隐藏敏感数据,同时允许其他非敏感参数?

<?php
$user = 'john';
$pass = 'secret';

function auth($user, $pass) {
    // authentication logic
}

function login($user, $pass) {
    throw new Exception('Unexpected error');

    // various logic
    auth($user, $pass);
    // various logic
}

try {
    login($user, $pass);
} catch (Throwable $e) {
    send_to_log($e->getTrace()); // This reveals the password "secret"
}

【问题讨论】:

  • 将数据写入日志文件。
  • 您为什么要向最终用户显示回溯的结果?不要这样做。
  • @miken32 为什么您认为代码示例反映了向最终用户显示的内容?我说的是插入到数据库或日志文件中的数据,最终用户永远看不到。

标签: php security logging credentials


【解决方案1】:

免责声明:我(有点)假设您从未真正将var_dump 的结果通过管道传回给您的用户。很明显,最终用户很少关心引擎的内部结构(再一次,有点),因此向他们展示跟踪路由几乎从来都不是处理服务器错误的好方法。但你是对的;出于各种原因,即使记录此信息实际上也可能不是一个好主意。

所以,回答最初的问题:好吧,您可以强制异常日志记录完全丢弃参数 - 或限制它们的长度:

请注意,PHP 7.4 引入了设置zend.exception_ignore_args, 这允许完全从异常中删除参数信息 (在getTrace()getTraceAsString() 等)。

设置zend.exception_string_param_max_len=0 仍然提供比完全禁用跟踪参数更多的信息(您仍然知道参数是字符串,以及非字符串的类型)。

这可能会使其他情况的调试复杂化。这在 PHP 8.0 中通过引入 zend.exception_string_param_max_len config param 得到了一定程度的缓解:

zend.exception_string_param_max_len 是一个新的 INI 指令,用于设置 字符串化堆栈 strace 的参数中的最大字符串长度。

The idea behind this (quoted above) 用于限制在记录异常时可能暴露的敏感数据的数量,而不会实际损害调试问题所需的数据。

请注意,此设置仅影响 getTraceAsString() 结果(您应该考虑使用它而不是 getTrace 的 var_dumping 结果)。

【讨论】:

  • 当您的回答仅涉及字符串长度时,我投了反对票。完全关闭参数的存储是一个更好的解决方案,但 OP 的代码表明他们会用它做一些愚蠢的事情。 (它正在征求意见。)
  • 我明白了,谢谢你的解释。是的,有时我确实假设人们不会做对我来说没有意义的事情——有时这种假设会失败。因此,在帖子顶部添加了免责声明。
  • 好吧,我确实理解 miken32 的推理:在解释中偷工减料(并假设切工是很明显的)有时会在这里失火,当其他人来查看代码时。但是,是的,对我而言,问题本质上更多是关于限制传递给异常跟踪的数据量,而不是关于存储这些跟踪的特定方式。
  • 任何认为原始var_dump() 将显示给最终用户的人只是故意为难,因为很明显这只是一个示例。我很震惊像 @miken32 这样讨厌的人为了解释而对一个简单的例子进行了解释。
【解决方案2】:

我最终在处理记录到文件/数据库的代码中添加了逻辑,以清除跟踪中显示的特定函数的参数:

<?php
function send_to_log(Throwable $e) {
    $noArgs = [
        'login' => true,
        'auth' => true,
        // ...
    ];

    $trace = $e->getTrace();
    foreach ($trace as &$err) {
        if (isset($noArgs[$err['function'] ?? ''])) {
            $cnt = count($err['args'] ?? []);
            if ($cnt > 0) {
                $err['args'] = array_fill(0, $cnt, 'REDACTED');
            }
        }
    }
    unset($err);

    var_dump($trace); /* This now shows "REDACTED" for all arguments
    to functions specified in the $noArgs array */

    // logging logic
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-04-29
    • 2015-11-21
    • 1970-01-01
    • 2017-09-12
    • 1970-01-01
    • 2021-02-25
    • 1970-01-01
    相关资源
    最近更新 更多