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 保护您的服务器和
数据库
也许有点偏执,但我很好奇。
假设我正在处理来自 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 保护您的服务器和 数据库