最近来自维基解密的漏洞让CIA做了以下事情:
只要不再需要纯文本格式的数据,就要从内存中明确删除敏感数据(加密密钥,原始收集数据,shellcode,上传的模块等).
不要依赖操作系统在执行终止时执行此操作.
我是*nix世界的开发者; 我认为这仅仅是改变变量的值(确保我没有通过值;而是通过引用); 所以,如果它是一个100个字符的字符串; 写0是101个字符.这真的很简单吗?如果不是,为什么以及应该做什么呢?
注意:有类似的问题要求这个; 但它在C#和Windows世界中.所以,我不认为这个问题是重复的.
我是*nix世界的开发者; 我认为这仅仅是改变变量的值(确保我没有通过值;而是通过引用); 所以,如果它是一个100个字符的字符串; 写0是101个字符.这真的很简单吗?如果不是,为什么以及应该做什么呢?
它应该是这么简单.细节决定成败.
bzero并memset计算为手动循环)可能会轻微优化,特别是如果你将局部变量归零("bug" - 实际上是一个功能,有解决方法).realloc做它的事情的例子.内存被部分重写,并且对于某些库,如果"a"不是唯一分配的区域,那么这只会"工作"(因此你需要声明c并在a之后立即分配一些东西,这样a不是最后一个对象并且离开自由成长):
int main() {
char *a;
char *b;
a = malloc(1024);
strcpy(a, "Hello");
strcpy(a + 200, "world");
printf("a at %08ld is %s...%s\n", a, a, a + 200);
b = realloc(a, 10240);
strcpy(b, "Hey!");
printf("a at %08ld is %s...%s, b at %08ld is %s\n", a, a, a + 200, b, b);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出:
a at 19828752 is Hello...world
a at 19828752 is 8????...world, b at 19830832 is Hey!
Run Code Online (Sandbox Code Playgroud)
所以地址a的内存被部分重写 - "Hello"丢失,"world"仍然存在(以及b + 200).
所以你需要自己处理敏感区域的重新分配; 更好的是,在程序启动时预先分配它.然后,告诉操作系统必须永远不要将敏感的内存区域交换到磁盘.然后你需要以编译器不能干扰的方式将其归零.而且你需要使用一个低级别的语言,你肯定不会自己做的事情:一个简单的字符串连接可以产生两个或三个数据副本 - 我相当肯定它发生在PHP 5.2中.
几年前我给自己写了一个小型图书馆 - 还valgrind没有 - 受史蒂夫马奎尔的编写固体代码的启发,除了覆盖各种内存和字符串函数之外,我最终覆盖了内存,然后计算了覆盖缓冲区的校验和.这不是为了安全,我用它来跟踪缓冲区上/下流,双重释放,使用释放的内存 - 这种事情.
然后你需要确保你的失败者工作 - 例如,如果程序中止会发生什么?或许才有可能使之中止的目的是什么?
您需要深入实施防御,并始终考虑尽可能少地保留信息 - 例如在计算期间清除中间缓冲区而不是等待并在最后一次释放整个批次,或者只是退出计划时; 尽可能保持哈希而不是密码; 等等.
当然,这一切都取决于信息的敏感程度以及攻击面可能是什么(强制xkcd参考:这里).用memtest86图像重新启动PC 可能是一个可行的选择.想象一下双启动计算机,其中memtest86设置为测试内存并将PC作为默认启动选项关闭.当你想关闭系统时...你重新启动它.PC将重新启动,默认情况下进入memtest86,在关闭电源之前,它将开始用0和1的行军填充所有可用的RAM.祝你好运冷冻引导从信息是.