[英]How can I tell if my memory has been released securely by a PHP application?
This might be better suited for security.stackexchange.com, but I'm curious about PHP in particular. 这可能更适合security.stackexchange.com,但我特别好奇PHP。
I'm working with openssl in an application and I notice the free operations for the openssl resources. 我在应用程序中使用openssl,我注意到openssl资源的免费操作。 This could very well just be just a generic release of memory, but given the cryptographic nature it may be handled as a special case.
这很可能只是一个通用的内存版本,但鉴于加密性质,它可以作为特殊情况处理。
AFAIK inside the application space there is no way to ensure a variable is deleted from memory. 应用程序空间内的AFAIK无法确保从内存中删除变量。 However, in Zend land, do the C extensions clean up known sensitive data, or do they just release the memory?
但是,在Zend的土地上,C扩展是否会清除已知的敏感数据,还是只释放内存? Does
openssl_pkey_free
release the memory securely? openssl_pkey_free
是否openssl_pkey_free
释放内存? How can I go about making an assertion that it has been released securely to apply it to other extensions I may be curious about in the future? 我怎样才能断言它已被安全发布以将其应用于我将来可能会对其他扩展程序?
I'm not a security analyst, so my definition of securely is rather vague. 我不是安全分析师,所以我对安全的定义相当含糊。
Before I even look, my answer is: Since PHP is a dynamic language, you should assume it's not cleared until proven otherwise (eg with Volatility). 在我看之前,我的答案是:由于PHP是一种动态语言,你应该假设它在被证明不是之前就不会被清除 (例如使用Volatility)。 According to former FreeBSD security officer Colin Percival, "Zeroing Buffers is Insufficient" -- so it might not even matter.
根据前FreeBSD安全官Colin Percival的说法, “归零缓冲区不足” - 所以它甚至可能都不重要。
But that's an incredibly boring answer. 但这是一个令人难以置信的无聊答案。 What's under the hood?
引擎盖下有什么?
openssl_pkey_free()
is defined by PHP in ext/openssl/openssl.c#545 : 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
}
As you can see, it calls a function called EVP_PKEY_free()
, which is defined by openssl in /crypto/evp/p_lib.c#L376 : 如您所见,它调用一个名为
EVP_PKEY_free()
的函数,该函数由/crypto/evp/p_lib.c#L376中的openssl定义:
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);
}
It does some sanity checks then calls OPENSSL_free()
, which is just an alias for CRYPTO_free()
. 它会进行一些健全性检查,然后调用
OPENSSL_free()
,它只是CRYPTO_free()
的别名 。
Finally, CRYPTO_free()
is defined here : 最后,
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);
}
It seems to just call free_func()
in the typical case, which is a pointer to free()
. 它似乎只是在典型的情况下调用
free_func()
,它是一个指向free()
的指针。 At no point in these operations did I see any attempt to zero out memory. 在这些操作中,我没有看到任何将内存清零的尝试。
If you can install PECL extensions, libsodium offers \\Sodium\\memzero()
in addition to secure memory allocation utilities . 如果您可以安装PECL扩展, libsodium除安全内存分配实用程序外还提供
\\Sodium\\memzero()
。
Please remember that zeroing memory is a mitigation strategy for when a compromise happens. 请记住,归零内存是一种缓解策略,用于何时发生折衷。 If your PHP code can read the private key from disk (or from a database), the attacker can probably replay the code and steal the key directly.
如果您的PHP代码可以从磁盘(或从数据库)读取私钥,攻击者可能会重放代码并直接窃取密钥。 The way to protect against this is store your keys in a hardware security module and never touch it directly.
防止这种情况的方法是将密钥存储在硬件安全模块中 ,不要直接触摸它。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.