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

时间:2017-03-13 18:53:07

标签: security memory

最近来自维基解密has the CIA doing the following的泄密:

  

明确删除敏感数据(加密密钥,原始收集   数据,shellcode,上传模块等)尽快从内存中获取   不再需要以纯文本形式提供数据。

     

不要依赖操作系统在终止时执行此操作   执行。

我是* nix世界的开发者;我认为这仅仅是改变变量的值(确保我没有通过值;而是通过引用);所以,如果它是一个100个字符的字符串;写0是101个字符。这真的很简单吗?如果不是,为什么以及应该做什么呢?

注意:有类似的问题要求这个;但它在C#和Windows世界中。所以,我不认为这个问题是重复的。

2 个答案:

答案 0 :(得分:6)

  

我是* nix世界的开发者;我只是看到了这一点   改变变量的值(确保我没有通过值;和   而是通过参考);所以,如果它是一个100个字符的字符串;   写0这是101个字符。这真的很简单吗?如果不,   为什么以及应该做些什么呢?

应该这么简单。魔鬼在细节中。

  • 内存分配函数,例如 realloc ,不能保证单独留下内存(你不应该依赖它们以某种方式进行操作 - 另请参阅this question)。如果您分配1K内存,然后将其重新分配到10K,原始K 可能仍然在其他地方,包含其敏感的有效负载。它可能会被另一个不敏感的变量或缓冲区分配,或者通过新变量,可能访问部分或全部旧内容,就像松弛空间一样。在一些文件系统上。
  • 手动将内存归零(并且,对于大多数编译器,bzeromemset计为手动循环)可能会被轻微优化,特别是如果您将局部变量归零({{3解决方法)。
  • 某些功能可能会留下"痕迹"在本地缓冲区或内存中,它们分配和解除分配。
  • 在某些语言和框架中,数据的整个部分可能最终被移动(例如在所谓的"垃圾收集",如@gene注意到的那样)。您可以告诉GC不要处理您的敏感区域或其他方式" pin"为此,如果是这样,必须这样做。否则,数据可能会以多个部分副本结束。
  • 信息可能已经通过并留下了您不知道的痕迹(例如:通过网络发送的密码可能会留在网络库读取缓冲区中)。
  • 实时内存可能会被换出磁盘。

realloc做其事情的例子。内存得到部分重写,对于一些库,这只会#34;工作"如果" 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;
}

输出:

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

因此,地址a的内存被部分重写 - " Hello"失去了,#34;世界"仍然存在(以及b + 200)

所以你需要自己处理敏感区域的重新分配;更好的是,在程序启动时预先分配它。然后,告诉操作系统敏感的内存区域必须"bug" - actually a feature。然后,您需要以编译器无法干预的方式将其归零。你需要使用一个never be swapped to disk,你确定它不会自己做事:一个简单的字符串连接可以产生两三个数据副本 - 我相当肯定它发生在PHP 5.2中。

年前我给自己写了一个小型图书馆 - 还没有valgrind - 受史蒂夫马奎尔的编写固体代码的启发,除了覆盖各种在内存和字符串函数中,我最终覆盖了内存,然后计算了覆盖缓冲区的校验和。这不是为了安全,我用它来跟踪缓冲区上/下流,双重释放,使用释放的内存 - 这种事情。

然后你需要确保你的失败者工作 - 例如,如果程序中止会发生什么?可能使有意中止吗?

你需要深入实施防御,并始终考虑尽可能少地保留信息 - 例如在计算过程中清除中间缓冲区而不是等待并在最后一次释放整个批次,或者只是在退出计划时;尽可能保持哈希而不是密码;等等。

当然,所有这些都取决于信息 的敏感程度以及攻击面可能是什么(强制性xkcd参考:low-level enough language)。使用here图像重新启动PC可能是一种可行的替代方案。想象一下双启动计算机,其中memtest86设置为测试内存并将PC作为默认启动选项关闭。当您想要关闭系统时......您重新启动它。 PC将重新启动,默认情况下进入memtest86,在关闭电源之前,它会开始用0和1的行军填充所有可用的RAM。祝你好运冻结的启动信息

答案 1 :(得分:5)

完成后立即清除密码(密码,密钥等)是相当标准的做法。困难在于处理可能妨碍您的语言和平台功能。

例如,如果C ++编译器确定在写入后未读取数据,则可以optimize out调用memset。或者操作系统可能已经分页memory out to disk,可能会以这种方式保留数据。