安全清除内存并重新分配

Clearing memory securely and reallocations(安全清除内存并重新分配)
本文介绍了安全清除内存并重新分配的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果您想参加安全课程,请在此处进行讨论要将敏感信息(例如密码)存储在内存中,您必须:

Following the discussion here, if you want to have a secure class for storing sensitive information (e.g passwords) on memory, you have to:

  • memset/clear the memory before free it
  • 重新分配也必须遵循相同的规则 - 不要使用 realloc,而是使用 malloc 创建一个新的内存区域,将旧内存复制到新内存,然后 memset/clear 旧内存,然后最终释放它

所以这听起来不错,我创建了一个测试类来看看它是否有效.所以我做了一个简单的测试用例,我不断添加单词LOL"和WUT",然后在这个安全缓冲区类中添加一个数字大约一千次,销毁该对象,然后最终执行导致核心转储的操作.

So this sounds good, and I created a test class to see if this works. So I made a simple test case where I keep adding the words "LOL" and "WUT", followed by a number to this secure buffer class around a thousand times, destroying that object, before finally doing something that causes a core dump.

由于该类应该在销毁之前安全地清除内存,因此我不应该能够在 coredump 上找到LOLWUT".但是,我还是设法找到了它们,并想知道我的实现是否只是错误.但是,我使用 CryptoPP 库的 SecByteBlock 尝试了同样的事情:

Since the class is supposed to securely clear the memory before the destruction, I'm not supposed to be able to find a "LOLWUT" on the coredump. However, I managed to find them still, and wondered if my implementation is just buggy. However, I tried the same thing using CryptoPP library's SecByteBlock:

#include <cryptopp/osrng.h>
#include <cryptopp/dh.h>
#include <cryptopp/sha.h>
#include <cryptopp/aes.h>
#include <cryptopp/modes.h>
#include <cryptopp/filters.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
using namespace std;

int main(){
   {
      CryptoPP::SecByteBlock moo;

      int i;
      for(i = 0; i < 234; i++){
         moo += (CryptoPP::SecByteBlock((byte*)"LOL", 3));
         moo += (CryptoPP::SecByteBlock((byte*)"WUT", 3));

         char buffer[33];
         sprintf(buffer, "%d", i);
         string thenumber (buffer);

         moo += (CryptoPP::SecByteBlock((byte*)thenumber.c_str(), thenumber.size()));
      }

      moo.CleanNew(0);

   }

   sleep(1);

   *((int*)NULL) = 1;

   return 0;
}

然后编译使用:

g++ clearer.cpp -lcryptopp -O0

然后启用核心转储

ulimit -c 99999999

然后,启用核心转储并运行它

But then, enabling core dump and running it

./a.out ; grep LOLWUT core ; echo hello

给出以下输出

Segmentation fault (core dumped)
Binary file core matches
hello

这是什么原因造成的?由于 SecByteBlock 的 append 引起的重新分配,应用程序的整个内存区域是否重新分配?

What is causing this? Did the whole memory region for the application realloc itself, because of the reallocation caused by SecByteBlock's append?

另外,这是 SecByteBlock 的文档

edit:使用 vim 检查核心转储后,我得到了这个:http://imgur.com/owkaw

edit: After checking the core dump using vim, I got this: http://imgur.com/owkaw

edit2:更新了代码,使其更易于编译,以及编译说明

edit2: updated code so it's more readily compilable, and compilation instructions

final edit3:看起来 memcpy 是罪魁祸首.请参阅 Rasmus 在下面的答案中的 mymemcpy 实现.

final edit3: It looks like memcpy is the culprit. See Rasmus' mymemcpy implementation on his answer below.

推荐答案

这是另一个更直接地重现问题的程序:

Here is another program that reproduces the problem more directly:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

inline void SecureWipeBuffer(char* buf, size_t n){
  volatile char* p = buf;
  asm volatile("rep stosb" : "+c"(n), "+D"(p) : "a"(0) : "memory");
}

void mymemcpy(char* b, const char* a, size_t n){
  char* s1 = b;
  const char* s2= a;
  for(; 0<n; --n) *s1++ = *s2++;
}

int main(){
  const size_t size1 = 200;
  const size_t size2 = 400;

  char* b = new char[size1];
  for(int j=0;j<size1-10;j+=10){
    memcpy(b+j, "LOL", 3);
    memcpy(b+j+3, "WUT", 3);
    sprintf((char*) (b+j+6), "%d", j);
  }
  char* nb = new char[size2];
  memcpy(nb, b, size1);
  //mymemcpy(nb, b, size1);
  SecureWipeBuffer(b,size1);
  SecureWipeBuffer(nb,size2);

  *((int*)NULL) = 1;

  return 0;    
}

如果您将 memcpy 替换为 mymemcpy 或使用较小的尺寸,问题就会消失,所以我最好的猜测是内置 memcpy 会留下部分复制数据在内存中.

If you replace memcpy with mymemcpy or use smaller sizes the problem goes away, so my best guess is that the builtin memcpy does something that leaves part of the copied data in memory.

我想这只是表明从内存中清除敏感数据实际上是不可能的,除非它是从头开始设计到整个系统中的.

I guess this just shows that clearing sensitive data from memory is practically impossible unless it is designed into the entire system from scratch.

这篇关于安全清除内存并重新分配的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本站部分内容来源互联网,如果有图片或者内容侵犯您的权益请联系我们删除!

相关文档推荐

Rising edge interrupt triggering multiple times on STM32 Nucleo(在STM32 Nucleo上多次触发上升沿中断)
How to use va_list correctly in a sequence of wrapper functions calls?(如何在一系列包装函数调用中正确使用 va_list?)
OpenGL Perspective Projection Clipping Polygon with Vertex Outside Frustum = Wrong texture mapping?(OpenGL透视投影裁剪多边形,顶点在视锥外=错误的纹理映射?)
How does one properly deserialize a byte array back into an object in C++?(如何正确地将字节数组反序列化回 C++ 中的对象?)
What free tiniest flash file system could you advice for embedded system?(您可以为嵌入式系统推荐什么免费的最小闪存文件系统?)
Volatile member variables vs. volatile object?(易失性成员变量与易失性对象?)