PHP - 为了安全起见,通过引用返回敏感数据?

PHP - Returning sensitive data by reference for security?

也许有点偏执,但我很好奇。

假设我正在处理来自 POST 的密码。完成后,我想擦拭并删除它。我读到 PHP 可能会或可能不会在垃圾收集擦除它之前将 $variable 的值保留在内存中一段时间​​,因此建议设置 $variable = null 擦除它并释放在使用 unset($variable).

之前立即调高内存

现在,我意识到,如果攻击者可以访问您服务器的内存,那就太晚了。但是,至少出于理论上的考虑,我想知道 PHP 是如何处理这个问题的,如果我没记错的话,对此稍微严格一点不会伤害 (或者可以吗? ).

所以我有一个函数可以做到这一点,基本上:

class SomeClass {
    // [...code...]
    public function &example_get_password() {
        $return = $_POST['password']; // or $this->_post['password'], or anything else
        $_POST['password'] = null;
        unset($_POST['password']);
        return $return;
    }
}

这个功能在现实中有点不同,但这就是它的要点(实际上,我从另一个问题中得到了一些关于它的非常好的提示)。我想知道的是当我这样做时会发生什么:

$_input = new SomeClass();
$password =& $_input->example_get_password();
//hash password, $hash = hash
$password = null; unset($password);

这里发生了什么,与所有相同的过程相反,但没有引用?我意识到 unset 不会删除引用的变量,但是因为它在里面完成执行的函数的范围,我希望一旦对它的最后一次引用被切断,它就会自动取消设置,对吗?不管怎样,它已被覆盖为 null.

这样做有什么好处吗?

宽泛的问题,但我会试一试。

PHP 为您管理内存,作为 PHP 程序员,您通常不需要担心内部结构,也不应尝试 out-smart 它们。对服务器内存的任何不必要的访问都应被视为 PHP 本身的错误并已修复。您还应该知道,当一个变量是 'wiped' 时,它的内容仍然可以(部分)存在于内存中;例如,即使您分配了 null,您的密码字符串也可能是可读的。

垃圾回收

在某些情况下,通过将 null 分配给变量来确保您自己释放内存的建议是正确的。但这纯粹是为了性能,而不是安全。

可以吗?

我觉得可以。有一个 class 内存错误称为 Use-After-Free 个错误。顾名思义,问题是您的程序仍然使用它之前释放的内存,而攻击者有机会更改内存。 PHP 在过去的几年里有很多这样的错误——主要与 unserialize 函数有关。其中一个发生在有人将某些东西分配给魔术 __wakeup 函数中的 属性 时。 List of bug reports by one of my favorite reporters 如果你有兴趣。

这里发生了什么,与所有相同的过程相反,但没有引用?

只要你不创建任何循环结构,或者改变全局变量,就没有区别。示例:

$array = []; $array[] = $array; $array[] = $password;

这里$password只有在垃圾收集器运行并收集$array时才会被释放。

这样做有什么好处吗?

好奇总是有好处的。但是我看不出使用这种高级语言对内存进行微观管理有什么好处。异常一如既往地证明了规则。

自从我提到 unserialize不要在不受信任的数据上使用它。曾经.

简答,没有。将变量设置为 null 将告诉 PHP 立即摆脱它,但正如您所猜测的那样,这可能还不够。有一些工具,例如 libsodium-php(在下面讨论)会尝试执行您的建议,但简而言之,它们也不起作用。

如果你想做一些测试,你可以在一个进程中向内存写入一些东西,然后在清理它等之后转储该进程(请参阅下面的文章)。正如他们所说,您需要保护服务器、协议、补丁管理等,这将是最好的方法。

非常有趣的文章:

https://www.jujens.eu/posts/en/2017/Nov/26/php-clean-password-tests/ https://www.sjoerdlangkemper.nl/2016/05/22/should-passwords-be-cleared-from-memory/

密码提示:

  • “使用旨在对密码进行哈希处理的算法对它们进行哈希处理,例如 bcryt 或 argon2(而不是与 sha 相关的算法或最差的 md5)。板条他们。别 除非需要,否则从数据库加载哈希。不要装傻 密码内容或长度的限制(但检查它是 强的)。保护自己免受 XSS 和 CRSF 保护您的服务器和 数据库