明确从内存中删除敏感数据



WikiLeaks最近的泄漏使中央情报局执行以下操作:

确实明确删除敏感数据(加密密钥,原始收集 一旦,数据,shellCode,上传模块等) 不再需要以纯文本形式进行数据。

不依靠操作系统在终止后执行此操作 执行。

我是 *Nix World的开发人员;我认为这只是更改变量的价值(确保我不按价值传递;而不是引用);因此,如果这是一个字符串,那就是100个字符;写0是101个字符。真的很简单吗?如果没有,为什么以及应该做什么?

注意:有类似的问题提出了这一点。但这在C#和Windows世界中。因此,我不认为这个问题是重复的。

我是 *Nix World的开发人员;我只将其视为 更改变量的价值(确保我不按价值传递;并且 而是通过引用);因此,如果这是一个字符串,那就是100个字符; 写0是101个字符。真的很简单吗?如果不, 为什么以及应该做什么?

应该很简单。魔鬼在细节中。

  • 内存分配功能,例如 realloc ,不能保证单独留下记忆(您不应依靠它们的方式或另一种方式 - 另请参阅此问题)。如果您分配了1k的内存,则将其分配给10K,您的原始K 可能仍然在其他地方,包含其敏感有效负载。然后,它可能由另一个不敏感的变量或缓冲区进行分配在某些文件系统上。
  • 手动归零的内存(以及大多数编译器,bzeromemset将其视为手动循环)可能会被杂乱地优化,尤其是当您要归零局部变量(" bug" - 实际上是一个功能,带有变方法)。<<<<<<<<<<<<<<<<<<<<<<<<<<。/li>
  • 某些功能可能会在本地缓冲区或记忆中留下"痕迹",或者它们分配和发行分配。
  • 在某些语言和框架中,所有数据的整个部分可能最终被移动(例如,在所谓的"垃圾收集"期间,如@Gene所述)。您也许可以告诉GC不要处理您的敏感区域或以其他方式将其"固定"以此为效果,如果是这样,则必须这样做。否则,数据可能最终以多个部分副本。
  • 信息可能已经通过了您不知道的范围(琐事示例:通过网络发送的密码可能会徘徊在网络库中读取缓冲区)。
  • 实时内存可能被换成磁盘。

realloc做事的示例。内存获得部分重写,如果" a"不是唯一的分配区域(因此,您还需要在A之后立即宣布C并分配某些内容,因此不是最后一个物体,可以自由生长):

int main() {
        char *a;
        char *b;
        a = malloc(1024);
        strcpy(a, "Hello");
        strcpy(a + 200, "world");
        printf("a at %08ld is %s...%sn", a, a, a + 200);
        b = realloc(a, 10240);
        strcpy(b, "Hey!");
        printf("a at %08ld is %s...%s, b at %08ld is %sn", a, a, a + 200, b, b);
        return 0;
}

输出:

 a at 19828752 is Hello...world
 a at 19828752 is 8????...world, b at 19830832 is Hey!

因此,地址A处的内存部分被重写 - " Hello"丢失,"世界"仍然存在(以及B 200)

因此,您需要亲自处理敏感区域的重新集中;更好的是,在计划启动时将其分配给所有这些。然后,告诉OS,绝对不能将敏感的内存区域换成磁盘。然后,您需要以编译器无法干扰的方式将其归零。而且,您需要使用一种低级语言,您肯定不会单独做任何事情:简单的字符串串联可以产生数据的两个或三个副本 - 我相当确定它发生在PHP 5.2中。<<<<<<<<<<<<<<

很久以前,我写了一个小库 - 还没有valgrind - 灵感来自史蒂夫·马奎尔(Steve Maguire)的编写实心代码,除了覆盖各种内存和字符串功能外,我最终覆盖了内存然后计算覆盖缓冲区的校验和。这不是为了安全性,我用它来跟踪缓冲区在流量上/下方,双释放,使用释放内存 - 这种东西。

然后您需要确保您的故障保护工作 - 例如,如果程序中止该程序会发生什么?可能是有可能故意流产的可能吗?

您需要深入实施防御,并始终查看保持尽可能少的信息的方法 - 例如在计算过程中清除中间缓冲区,或者只是在退出程序时;尽可能保留哈希而不是密码;等等。

当然,所有这些都取决于信息的敏感性以及攻击表面可能是什么(强制性XKCD参考:此处)。使用memtest86图像重新启动PC可能是可行的替代方法。想想带有MEMTEST86的双启动计算机设置为默认引导选项,以测试内存并将其供电。当您要关闭系统时... 重新启动它。PC将重新启动,默认情况下输入Memtest86,并且在永久电源之前,它将开始用零和零的行进部队填充所有可用的RAM。祝您好运,从

零完成后立即完成秘密(密码,键等)与他们在一起是相当标准的做法。困难在于处理可以妨碍您的语言和平台功能。

例如,C 编译器可以优化对memset的调用,如果它确定在写入后未读取数据。或操作系统可能已经将内存分配到磁盘上,有可能以这种方式将数据丢弃。

最新更新