如何只隐藏 PHP 的 debug_backtrace 中的敏感参数?
How to hide only sensitive arguments in PHP's debug_backtrace?
考虑以下代码。如果发生异常,跟踪(将被记录并存储在数据库中)将包括敏感的 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"
}
免责声明:我(有点)假设您从未真正将 var_dump
的结果通过管道返回给您的用户。很明显(再一次)最终用户很少关心引擎的内部结构,因此向他们展示跟踪路由几乎不是处理服务器错误的好方法。但你是对的;出于各种原因,即使记录此信息实际上也不是一个好主意。
因此,回答最初的问题:好吧,您可以强制您的异常日志记录完全丢弃参数 - 或者限制它们的长度:
Note that PHP 7.4 introduced the setting zend.exception_ignore_args
,
which allowed removing argument information from exceptions completely
(in getTrace()
, getTraceAsString()
, etc.).
Setting zend.exception_string_param_max_len=0
still provides more information than completely disabling tracking args (you still know the argument is a string, and types of non-strings).
这仍然可能会使其他情况的调试复杂化。通过引入 zend.exception_string_param_max_len
config param:
在 PHP 8.0 中有所缓解
zend.exception_string_param_max_len is a new INI directive to set the
maximum string length in an argument of a stringified stack strace.
The idea behind this (quoted above) 是为了限制在记录异常时可能暴露的敏感数据的数量,而不会实际损害调试问题所需的数据。
请注意,此设置仅影响 getTraceAsString()
结果(您应该考虑使用它而不是 getTrace 的 var_dumping 结果)。
我最终在代码中添加了处理日志记录到 file/database 的逻辑,以清除跟踪中显示的特定函数的参数:
<?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
}
考虑以下代码。如果发生异常,跟踪(将被记录并存储在数据库中)将包括敏感的 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"
}
免责声明:我(有点)假设您从未真正将 var_dump
的结果通过管道返回给您的用户。很明显(再一次)最终用户很少关心引擎的内部结构,因此向他们展示跟踪路由几乎不是处理服务器错误的好方法。但你是对的;出于各种原因,即使记录此信息实际上也不是一个好主意。
因此,回答最初的问题:好吧,您可以强制您的异常日志记录完全丢弃参数 - 或者限制它们的长度:
Note that PHP 7.4 introduced the setting
zend.exception_ignore_args
, which allowed removing argument information from exceptions completely (ingetTrace()
,getTraceAsString()
, etc.).
Setting
zend.exception_string_param_max_len=0
still provides more information than completely disabling tracking args (you still know the argument is a string, and types of non-strings).
这仍然可能会使其他情况的调试复杂化。通过引入 zend.exception_string_param_max_len
config param:
zend.exception_string_param_max_len is a new INI directive to set the maximum string length in an argument of a stringified stack strace.
The idea behind this (quoted above) 是为了限制在记录异常时可能暴露的敏感数据的数量,而不会实际损害调试问题所需的数据。
请注意,此设置仅影响 getTraceAsString()
结果(您应该考虑使用它而不是 getTrace 的 var_dumping 结果)。
我最终在代码中添加了处理日志记录到 file/database 的逻辑,以清除跟踪中显示的特定函数的参数:
<?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
}