这可能更适合security.stackeexchange.com,但我对PHP特别好奇。
我正在一个应用程序中使用openssl,我注意到了openssl资源的免费操作。这很可能只是内存的一般发布,但考虑到加密的性质,它可能会作为特殊情况处理。
AFAIK在应用程序空间内,无法确保从内存中删除变量。然而,在Zend领域,C扩展是清理已知的敏感数据,还是只是释放内存?openssl_pkey_free
是否安全释放内存?我该如何断言它已经安全发布,以将其应用于我未来可能好奇的其他扩展?
我不是安全分析师,所以我对安全的定义相当模糊。
TL;DR:没有
在我看之前,我的答案是:由于PHP是一种动态语言,您应该假设它没有被清除,直到被证明(例如使用Volatility)。根据前FreeBSD安全官员Colin Percival的说法,"清零缓冲区不足"——所以这可能根本无关紧要。
但这是一个令人难以置信的无聊答案。引擎盖下面是什么?
openssl_pkey_free()做什么
openssl_pkey_free()
由PHP在ext/openssl/openssl.c#545:中定义
void EVP_PKEY_free(EVP_PKEY *x)
{
int i;
if (x == NULL)
return;
i = CRYPTO_add(&x->references, -1, CRYPTO_LOCK_EVP_PKEY);
#ifdef REF_PRINT
REF_PRINT("EVP_PKEY", x);
#endif
if (i > 0)
return;
#ifdef REF_CHECK
if (i < 0) {
fprintf(stderr, "EVP_PKEY_free, bad reference count'n");
abort();
}
#endif
EVP_PKEY_free_it(x);
if (x->attributes)
sk_X509_ATTRIBUTE_pop_free(x->attributes, X509_ATTRIBUTE_free);
OPENSSL_free(x);
}
static void EVP_PKEY_free_it(EVP_PKEY *x)
{
if (x->ameth && x->ameth->pkey_free) {
x->ameth->pkey_free(x);
x->pkey.ptr = NULL;
}
#ifndef OPENSSL_NO_ENGINE
if (x->engine) {
ENGINE_finish(x->engine);
x->engine = NULL;
}
#endif
}
如您所见,它调用了一个名为EVP_PKEY_free()
的函数,该函数由openssl在/crypto/evp/p-lib.c#L376:中定义
void EVP_PKEY_free(EVP_PKEY *x)
{
int i;
if (x == NULL)
return;
i = CRYPTO_add(&x->references, -1, CRYPTO_LOCK_EVP_PKEY);
#ifdef REF_PRINT
REF_PRINT("EVP_PKEY", x);
#endif
if (i > 0)
return;
#ifdef REF_CHECK
if (i < 0) {
fprintf(stderr, "EVP_PKEY_free, bad reference count'n");
abort();
}
#endif
EVP_PKEY_free_it(x);
if (x->attributes)
sk_X509_ATTRIBUTE_pop_free(x->attributes, X509_ATTRIBUTE_free);
OPENSSL_free(x);
}
它进行一些健全性检查,然后调用OPENSSL_free()
,这只是CRYPTO_free()
的别名。
最后,这里定义了CRYPTO_free()
:
void CRYPTO_free(void *str)
{
if (free_debug_func != NULL)
free_debug_func(str, 0);
#ifdef LEVITTE_DEBUG_MEM
fprintf(stderr, "LEVITTE_DEBUG_MEM: < 0x%p'n", str);
#endif
free_func(str);
if (free_debug_func != NULL)
free_debug_func(NULL, 1);
}
在典型的情况下,它似乎只是调用free_func()
,它是指向free()
的指针。在这些操作中,我没有看到任何试图清空内存的行为。
但我真的想在PHP中实现零内存。我怎么能
如果您可以安装PECL扩展,那么libsodium除了提供安全内存分配实用程序外,还提供'Sodium'memzero()
。
请记住,当妥协发生时,清零内存是一种缓解策略。如果您的PHP代码可以从磁盘(或数据库)读取私钥,则攻击者可能会重放代码并直接窃取密钥。防止这种情况的方法是将钥匙存放在硬件安全模块中,千万不要直接触摸。