从PHP的物理内存中清除变量的值

问题描述:

一般问题是:在PHP中未设置变量之后,是否可以从物理内存中删除String变量的值?从PHP的物理内存中清除变量的值

这个问题来自于安全标准的某些要求(在处理某些重要数据时,不应该将数据从内存转储到磁盘)。根据“Is memory encrypted?”主题,没有好的方法来加密内存中的数据。

因此,在PHP中取消设置字符串变量时,您无法确定内存中的数据是否被覆盖。关于为变量设置新值的同样故事。

因此,我很感兴趣,如果可以从内存中清除变量值而不更改核心代码unset方法?

+0

@jprofitt重新分配可能只会改变存储在变量中的引用而不会覆盖该字符串。但我不是PHP内部专家... – mensi 2012-04-10 12:14:33

+0

@mensi是啊,这是我在同一条船!即将编辑我的评论以包含该声明。 – jprofitt 2012-04-10 12:15:08

+0

@jprofitt mensi是对的,我提到它的问题 - PHP将创建新的参考。 – WASD42 2012-04-10 12:15:41

所以据我所知,问题不在于使用unset()或PHP的垃圾回收器,而是要确保已使用的内存实际上在物理层上清除了?

简单的方式 - 只需设置你重置(或与此有关的任何其他值)之前为空What's better at freeing memory with PHP: unset() or $var = null

硬盘和supid办法是分配所有PHP内存垃圾,以确保它被覆盖,但我不确定虚拟内存是否固定在预定义的diapason上,或者根据流程需求进行更改。

+1

这没有任何意义,因为'$ a ='hello'; $ b = $ a; $ b = null;'会产生不良的副作用。我非常怀疑php实际上会将内存清零。 (这将是一个愚蠢的事情) – mensi 2012-04-10 12:46:05

+0

好吧,这样$ b **就变**了。 $ a仍然有它的价值,因为分配是通过引用 – 2012-04-10 12:49:03

+1

完成的我离php内部专家很远,但我更怀疑设置$ a = null;实际上会让'你好'走开。它不会被$ a引用,但字符串本身仍然会浮动,直到内存被重用。 – Cerad 2012-04-10 14:18:12

首先,我不确定擦除字符串是否符合您所描述的安全要求,因为理论上仍然可以在擦除字符串之前转储内存。但是无论如何,这是不可能的,因为你无法在内存中处理数据。无论如何,如果你想确保字符串被擦除,我认为在PHP中这样做的唯一方法是遍历字符串并修改每个字符:记住,内存的内容不会消失,直到被覆盖,即使您没有对变量的引用并且PHP GC已经运行。

我相信这将工作:

for($i=0; $i < strlen($str); $i++) 
    $str[$i] = 'x'; 
+0

+1:我怀疑这确实是你可以在PHP中做的最好的。当然,并不能保证内存中可能没有其他字符串的其他副本会被忽略。 – 2012-04-10 13:19:03

+0

@IlmariKaronen我认为只要字符串只被读取而不被操作,它就应该起作用。字符串操作函数可能会创建副本并返回新字符串,而不是就地修改;因此我避开了这些并使用了字符访问。 – 2012-04-10 13:28:13

+0

问题是,我们不知道OP可能用字符串_before_擦除它。 PHP只是喜欢复制字符串,除非清除这些副本的_all_(这可能是不可能的,如果您调用一个内部副本并释放它的函数而不先擦除)可能会留下一些字符串在记忆中。 – 2012-04-10 13:43:56

做了一些测试使用PHP 5.6:

<?php 
    $cc = 'AAAABBBBCCCCDDDD'; 
    #v1: unset($cc); 
    #v2: $cc=null; 
    #v3: for($i=0; $i < strlen($cc); $i++) $cc[$i] = 'x'; 
    sleep(500); // enough time for taking script pid and run the memory dump 
?> 

试过以上脚本的每个版本(启用#V1,启用#V2,启用#V3 ); 转储进程的内存(请参阅https://serverfault.com/a/408929/374467),并且'AAAABBBBCCCCDDDD'字符串始终显示在生成的二进制文件(其中包含进程内存)中。还测试何时将$ cc值作为命令行参数($ argv)发送。同样的结果。

迄今为止,我发现没有可靠的方式来在PHP中执行此操作。