例如,让我们使用伪代码尝试获取存储在已分配(然后释放
)内存中的 RSA 私钥:
int main(){
bigNum priKey;
while(true) {
void *mem = malloc(2024); //allocate a good amount of chunk
if(rsaKeyIn(mem, &priKey))
break;
}
printf("RSA PRK found: %s", priKey.getText())
return 0;
}
问题:这可能吗?或者是否有可能恢复任何其他 secret 数据?
或者为了安全起见,操作系统是否将空闲
的内存归零?如果不是这种情况,我们是否应该在释放之前手动用零填充分配的内存?
最佳答案
这是可能的,因为释放内存并不一定意味着它被清除。
例如,给定以下代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[])
{
int i, len = 20;
char *p = malloc(len);
strcpy(p, "this is a test!!");
printf("&p=%p, p=%s\n", &p, p);
for (i=0; i<len; i++) {
printf("%02x ", p[i]);
}
printf("\n");
free(p);
// undefined behavior below: dereferencing freed memory
printf("p=%s\n", p);
for (i=0; i<len; i++) {
printf("%02x ", p[i]);
}
printf("\n");
return 0;
}
我的系统输出如下:
&p=0x7ffd24e08290, p=this is a test!!
74 68 69 73 20 69 73 20 61 20 74 65 73 74 21 21 00 00 00 00
p=
00 00 00 00 00 00 00 00 61 20 74 65 73 74 21 21 00 00 00 00
因此,如果您的程序存在允许攻击者控制它的安全漏洞,他们可以转储已释放内存的内容并暴露敏感数据。
因此,一旦不再需要包含 secret 数据的内存,就应将其删除。对此的幼稚方法是在内存块上调用 memset
,但是如果许多编译器发现在该点之后不再使用内存,则会对其进行优化。
在 C 标准中定义了一个名为 memset_s
的函数,它保证不会被优化掉,但并不是所有的实现都有它。你需要找到一些库调用来清除我不会优化的内存。像 OpenSSL 这样的库会在您调用它们的清理例程时为您执行此操作(参见 this post 作为示例)。
关于c - 是否可以通过分配内存来恢复 secret 数据(例如用于解密的空闲内存中的 RSA 私钥)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57077378/